Skip to content
This repository has been archived by the owner on Sep 28, 2022. It is now read-only.

Commit

Permalink
Change multicall error validation behaviour
Browse files Browse the repository at this point in the history
Change error validation behaviour to prevent entire observable stream from erroring giving errorred values an opportunity to update with valid values at a later time
  • Loading branch information
michaelelliot committed Feb 24, 2020
1 parent abec280 commit 8214d55
Show file tree
Hide file tree
Showing 14 changed files with 215 additions and 102 deletions.
12 changes: 9 additions & 3 deletions packages/dai-plugin-mcd/src/schemas/_validators.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,13 @@ export const tag = (strings, ...keys) => (...values) => {
};

export const validateAddress = (...args) => address =>
!/^0x[0-9a-fA-F]{40}$/.test(address) && tag(...args)({ address });
(!/^0x[0-9a-fA-F]{40}$/.test(address) ||
address === '0x0000000000000000000000000000000000000000') &&
tag(...args)({ address: address === null ? '(null)' : address });

export const validatProxyAddressResult = (...args) => (proxyAddress, [address]) =>
proxyAddress === '0x0000000000000000000000000000000000000000' && tag(...args)({ address }); // prettier-ignore
export const validateVaultId = id =>
!/^\d+$/.test(id) &&
`Invalid vault id: must be a positive integer. Received ${id}`;

export const validateVaultTypeResult = vaultType =>
!vaultType && 'Vault does not exist';
8 changes: 1 addition & 7 deletions packages/dai-plugin-mcd/src/schemas/cdpManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
VAULTS_CREATED,
VAULT_OWNER
} from './_constants';
import { validateVaultId, validateVaultTypeResult } from './_validators';

export const cdpManagerUrns = {
generate: id => ({
Expand All @@ -17,13 +18,6 @@ export const cdpManagerUrns = {
returns: [VAULT_ADDRESS]
};

const validateVaultId = id =>
!/^\d+$/.test(id) &&
`Invalid vault id: must be a positive integer. Received ${id}`;

const validateVaultTypeResult = vaultType =>
!vaultType && 'Vault does not exist';

export const cdpManagerIlks = {
generate: id => ({
id: `CDP_MANAGER.ilks(${id})`,
Expand Down
16 changes: 9 additions & 7 deletions packages/dai-plugin-mcd/src/schemas/computed.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ import {
COLLATERAL_TYPE_COLLATERALIZATION,
COLLATERAL_TYPE_DATA
} from './_constants';
import { validateAddress } from './_validators';
import { validateAddress, validateVaultId } from './_validators';

export const collateralTypePrice = {
generate: collateralTypeName => ({
Expand Down Expand Up @@ -106,8 +106,7 @@ export const vaultTypeAndAddress = {

export const vaultExternalOwner = {
generate: id => ({
dependencies: [[PROXY_OWNER, [VAULT_OWNER, id]]],
// TODO: throw error if no owner (DSProxy contract doesn't exist)
dependencies: [[PROXY_OWNER, [VAULT_OWNER, id]], [VAULT_OWNER, id]],
computed: owner => owner
})
};
Expand Down Expand Up @@ -381,7 +380,10 @@ export const vault = {
.toNumber();
}
})
})
}),
validate: {
args: validateVaultId
}
};

export const daiLockedInDsr = {
Expand All @@ -395,7 +397,7 @@ export const daiLockedInDsr = {
}
}),
validate: {
args: validateAddress`Invalid address: ${'address'}`
args: validateAddress`Invalid address for daiLockedInDsr: ${'address'}`
}
};

Expand Down Expand Up @@ -461,7 +463,7 @@ export const savings = {
})
}),
validate: {
args: validateAddress`Invalid address: ${'address'}`
args: validateAddress`Invalid address for savings: ${'address'}`
}
};

Expand Down Expand Up @@ -491,7 +493,7 @@ export const userVaultsList = {
)
}),
validate: {
args: validateAddress`Invalid address: ${'address'}`
args: validateAddress`Invalid address for userVaultsList: ${'address'}`
}
};

Expand Down
5 changes: 5 additions & 0 deletions packages/dai-plugin-mcd/src/schemas/getCdps.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
USER_VAULT_ADDRESSES,
USER_VAULT_TYPES
} from './_constants';
import { validateAddress } from './_validators';
import { bytesToString } from '../utils';

export const getCdps = {
Expand All @@ -17,6 +18,10 @@ export const getCdps = {
proxyAddress
]
}),
validate: {
args: (_, address) =>
validateAddress`Invalid address for getCdps: ${'address'}`(address)
},
returns: [
[USER_VAULT_IDS, v => v.map(n => n.toNumber())],
[USER_VAULT_ADDRESSES],
Expand Down
15 changes: 9 additions & 6 deletions packages/dai-plugin-mcd/src/schemas/proxyRegistry.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
import { PROXY_ADDRESS } from './_constants';
// import { validateAddress, validatProxyAddressResult } from './_validators';
import { validateAddress } from './_validators';

export const proxyRegistryProxies = {
generate: address => ({
id: `PROXY_REGISTRY.proxies(${address})`,
contract: 'PROXY_REGISTRY',
call: ['proxies(address)(address)', address]
call: ['proxies(address)(address)', address],
transforms: {
[PROXY_ADDRESS]: v =>
v === '0x0000000000000000000000000000000000000000' ? null : v
}
}),
// validate: {
// args: validateAddress`Invalid address: ${'address'}`,
// [PROXY_ADDRESS]: validatProxyAddressResult`No proxy found for account address: ${'address'}`
// },
validate: {
args: validateAddress`Invalid address for proxyAddress: ${'address'}`
},
returns: [[PROXY_ADDRESS]]
};

Expand Down
12 changes: 11 additions & 1 deletion packages/dai-plugin-mcd/src/schemas/token.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { getMcdToken } from '../utils';
import BigNumber from 'bignumber.js';

import { TOKEN_BALANCE, TOKEN_ALLOWANCE_BASE } from './_constants';
import { validateAddress } from './_validators';

export const ALLOWANCE_AMOUNT = BigNumber(
'0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
Expand Down Expand Up @@ -76,7 +77,16 @@ export const tokenAllowance = {
: [TOKEN_ALLOWANCE_BASE, address, proxyAddress, symbol]
],
computed: v => v
})
}),
validate: {
args: (address, proxyAddress) =>
validateAddress`Invalid address for tokenAllowance: ${'address'}`(
address
) ||
validateAddress`Invalid proxy address for tokenAllowance: ${'address'}`(
proxyAddress
)
}
};

export const adapterBalance = {
Expand Down
5 changes: 2 additions & 3 deletions packages/dai-plugin-mcd/test/schemas/cat.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,8 @@ test(LIQUIDATOR_ADDRESS, async () => {
const address = await maker.latest(LIQUIDATOR_ADDRESS, 'ETH-A');
expect(address.toLowerCase()).toEqual(expected);

expect(() => {
maker.latest(LIQUIDATOR_ADDRESS, null);
}).toThrow(/invalid/i);
const promise = maker.latest(LIQUIDATOR_ADDRESS, null);
await expect(promise).rejects.toThrow(/invalid/i);
});

test(LIQUIDATION_PENALTY, async () => {
Expand Down
5 changes: 2 additions & 3 deletions packages/dai-plugin-mcd/test/schemas/cdpManager.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,8 @@ test(VAULT_TYPE, async () => {
await expect(vaultType2).rejects.toThrow(/does not exist/i);

const cdpId3 = -9000;
expect(() => {
maker.latest(VAULT_TYPE, cdpId3);
}).toThrow(/invalid vault id/i);
const vaultType3 = maker.latest(VAULT_TYPE, cdpId3);
await expect(vaultType3).rejects.toThrow(/invalid vault id/i);
});

test(VAULTS_CREATED, async () => {
Expand Down
100 changes: 69 additions & 31 deletions packages/dai-plugin-mcd/test/schemas/computed.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,13 @@ import computedSchemas from '../../src/schemas/computed';

import { createCurrencyRatio } from '@makerdao/currency';

let maker, snapshotData, address, address2, proxyAddress, expectedVaultAddress;
let maker,
multicall,
snapshotData,
address,
address2,
proxyAddress,
expectedVaultAddress;

const ETH_A_COLLATERAL_AMOUNT = ETH(1);
const ETH_A_DEBT_AMOUNT = MDAI(1);
Expand All @@ -78,9 +84,9 @@ beforeAll(async () => {
});
address = maker.service('web3').currentAddress();
address2 = TestAccountProvider.nextAccount().address;

maker.service('multicall').createWatcher();
maker.service('multicall').registerSchemas({
multicall = maker.service('multicall');
multicall.createWatcher();
multicall.registerSchemas({
vatIlks,
vatUrns,
vatGem,
Expand All @@ -101,7 +107,7 @@ beforeAll(async () => {
getCdps,
...computedSchemas
});
maker.service('multicall').start();
multicall.start();

await setupCollateral(maker, 'ETH-A', {
price: ETH_A_PRICE
Expand Down Expand Up @@ -134,6 +140,42 @@ afterAll(async () => {
await restoreSnapshot(snapshotData, maker);
});

test(DAI_LOCKED_IN_DSR, async () => {
const daiLockedInDsr = await maker.latest(DAI_LOCKED_IN_DSR, address);
expect(daiLockedInDsr.symbol).toEqual('DSR-DAI');
expect(daiLockedInDsr.toNumber()).toBeCloseTo(1, 18);
});

test(`${DAI_LOCKED_IN_DSR} using invalid account address`, async () => {
const promise = maker.latest(DAI_LOCKED_IN_DSR, '0xfoobar');
await expect(promise).rejects.toThrow(/invalid/i);
});

test(`${DAI_LOCKED_IN_DSR} before and after account has proxy`, async () => {
const nextAccount = TestAccountProvider.nextAccount();
await maker.addAccount({ ...nextAccount, type: 'privateKey' });
maker.useAccount(nextAccount.address);

const promise = maker.latest(DAI_LOCKED_IN_DSR, nextAccount.address);
await expect(promise).rejects.toThrow(/invalid/i);

await maker.service('proxy').ensureProxy();
await mineBlocks(maker.service('token'), 1);

const daiLockedInDsr = await maker.latest(
DAI_LOCKED_IN_DSR,
nextAccount.address
);
expect(daiLockedInDsr.symbol).toEqual('DSR-DAI');
expect(daiLockedInDsr.toNumber()).toEqual(0);
});

test(TOTAL_DAI_LOCKED_IN_DSR, async () => {
const totalDaiLockedInDsr = await maker.latest(TOTAL_DAI_LOCKED_IN_DSR);
expect(totalDaiLockedInDsr.symbol).toEqual('DSR-DAI');
expect(totalDaiLockedInDsr.toNumber()).toBeCloseTo(1, 18);
});

test(COLLATERAL_TYPE_PRICE, async () => {
const ethAPrice = await maker.latest(COLLATERAL_TYPE_PRICE, 'ETH-A');
expect(ethAPrice.toNumber()).toEqual(180);
Expand Down Expand Up @@ -333,32 +375,8 @@ test(`${VAULT} with non-existent id`, async () => {

test(`${VAULT} with invalid id`, async () => {
const cdpId = -9000;
expect(() => {
maker.latest(VAULT, cdpId);
}).toThrow(/invalid vault id/i);
});

test(DAI_LOCKED_IN_DSR, async () => {
const daiLockedInDsr = await maker.latest(DAI_LOCKED_IN_DSR, address);
expect(daiLockedInDsr.symbol).toEqual('DSR-DAI');
expect(daiLockedInDsr.toNumber()).toBeCloseTo(1, 18);
});

test.skip(`${DAI_LOCKED_IN_DSR} using invalid account address`, async () => {
expect(() => {
maker.latest(DAI_LOCKED_IN_DSR, '0xfoobar');
}).toThrow(/invalid/i);
});

test.skip(`${DAI_LOCKED_IN_DSR} using account with no proxy`, async () => {
const promise = maker.latest(DAI_LOCKED_IN_DSR, address2);
await expect(promise).rejects.toThrow();
});

test(TOTAL_DAI_LOCKED_IN_DSR, async () => {
const totalDaiLockedInDsr = await maker.latest(TOTAL_DAI_LOCKED_IN_DSR);
expect(totalDaiLockedInDsr.symbol).toEqual('DSR-DAI');
expect(totalDaiLockedInDsr.toNumber()).toBeCloseTo(1, 18);
const vault = maker.latest(VAULT, cdpId);
await expect(vault).rejects.toThrow(/invalid vault id/i);
});

test(BALANCE, async () => {
Expand Down Expand Up @@ -423,6 +441,16 @@ test(ALLOWANCE, async () => {
maker.useAccount('default');
});

test(`${ALLOWANCE} using invalid account address`, async () => {
const promise = maker.latest(ALLOWANCE, 'BAT', null);
await expect(promise).rejects.toThrow(/invalid address/i);
});

test(`${ALLOWANCE} for account with no proxy`, async () => {
const promise = maker.latest(ALLOWANCE, 'BAT', address2);
await expect(promise).rejects.toThrow(/invalid proxy/i);
});

test(USER_VAULTS_LIST, async () => {
const [batVault, ethVault] = await maker.latest(USER_VAULTS_LIST, address);

Expand All @@ -440,6 +468,16 @@ test(USER_VAULTS_LIST, async () => {
);
});

test(`${USER_VAULTS_LIST} for account with no proxy`, async () => {
const promise = maker.latest(USER_VAULTS_LIST, address2);
await expect(promise).rejects.toThrow(/invalid/i);
});

test(`${USER_VAULTS_LIST} for account with no proxy`, async () => {
const promise = maker.latest(USER_VAULTS_LIST, address2);
await expect(promise).rejects.toThrow(/invalid/i);
});

test(PROXY_OWNER, async () => {
const proxyOwner = await maker.latest(PROXY_OWNER, proxyAddress);
expect(isValidAddressString(proxyOwner)).toEqual(true);
Expand Down
12 changes: 11 additions & 1 deletion packages/dai-plugin-mcd/test/schemas/pot.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import {
ANNUAL_DAI_SAVINGS_RATE,
DATE_EARNINGS_LAST_ACCRUED
} from '../../src/schemas';

import potSchemas from '../../src/schemas/pot';

let maker, snapshotData, cdpMgr, saveService;
Expand Down Expand Up @@ -69,6 +68,17 @@ test(SAVINGS_DAI, async () => {
expect(savingsDai.toNumber()).toBeCloseTo(0.99995);
});

test(`${SAVINGS_DAI} using invalid account address`, async () => {
const promise1 = maker.latest(SAVINGS_DAI, '0xfoobar');
await expect(promise1).rejects.toThrow(/invalid/i);

const promise2 = maker.latest(
SAVINGS_DAI,
'0x0000000000000000000000000000000000000000'
);
await expect(promise2).rejects.toThrow(/invalid/i);
});

test(DAI_SAVINGS_RATE, async () => {
const daiSavingsRate = await maker.latest(DAI_SAVINGS_RATE);
expect(daiSavingsRate).toEqual(BigNumber('1.000000000315522921573372069'));
Expand Down
13 changes: 6 additions & 7 deletions packages/dai-plugin-mcd/test/schemas/proxyRegistry.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,16 +40,15 @@ test(PROXY_ADDRESS, async () => {
expect(proxy2).toEqual(proxyAddress2);
});

test.skip(`${PROXY_ADDRESS} using invalid account address`, async () => {
expect(() => {
maker.latest(PROXY_ADDRESS, '0xfoobar');
}).toThrow(/invalid/i);
test(`${PROXY_ADDRESS} using invalid account address`, async () => {
const promise = maker.latest(PROXY_ADDRESS, '0xfoobar');
await expect(promise).rejects.toThrow(/invalid/i);
});

test.skip(`${PROXY_ADDRESS} using account with no proxy`, async () => {
const promise = maker.latest(
test(`${PROXY_ADDRESS} using account with no proxy`, async () => {
const proxy = await maker.latest(
PROXY_ADDRESS,
'0x1111111111111111111111111111111111111111'
);
await expect(promise).rejects.toThrow(/no proxy found/i);
expect(proxy).toBeNull();
});
Loading

0 comments on commit 8214d55

Please sign in to comment.