From d99aa1a7426c27ef3176f84768a85c1c4bedf9b9 Mon Sep 17 00:00:00 2001 From: Lawrence Wang Date: Fri, 22 May 2020 17:01:54 -0700 Subject: [PATCH 1/2] update migrations plugin with changes from migrate-dashboard --- .../contracts/abiMap.json | 14 +- .../contracts/abis/CageFree.json | 1 + .../contracts/abis/DSValue.json | 1 + .../contracts/abis/DaiJoin.json | 1 + .../contracts/abis/DssProxyActionsEnd.json | 1 + .../contracts/abis/ESM.json | 1 + .../contracts/abis/GemJoin.json | 1 + .../contracts/addresses/kovan.json | 24 +- .../contracts/addresses/mainnet.json | 8 +- .../contracts/addresses/testnet.json | 10 +- .../scripts/install-testchain-outputs.sh | 11 +- .../src/MigrationService.js | 12 +- .../dai-plugin-migrations/src/constants.js | 4 +- .../GlobalSettlementCollateralClaims.js | 79 +++++- .../migrations/GlobalSettlementDaiRedeemer.js | 84 +++++++ .../migrations/GlobalSettlementSavingsDai.js | 2 +- .../src/migrations/RedeemCollateral.js | 25 ++ .../src/migrations/RedeemSai.js | 25 ++ .../src/migrations/SingleToMultiCdp.js | 42 ++++ .../test/MigrationService.spec.js | 17 +- .../test/helpers/index.js | 45 +++- .../test/helpers/mocks.js | 14 +- .../test/kovan/kovan.test.js | 8 +- .../test/migrations/ChiefMigrate.spec.js | 8 +- .../GlobalSettlementCollateralClaims.spec.js | 39 ++- .../GlobalSettlementDaiRedeemer.spec.js | 25 +- .../test/migrations/RedeemCollateral.spec.js | 41 ++++ .../test/migrations/RedeemSai.spec.js | 57 +++++ .../test/migrations/SingleToMultiCdp.spec.js | 230 +++++++++--------- 29 files changed, 622 insertions(+), 208 deletions(-) create mode 100644 packages/dai-plugin-migrations/contracts/abis/CageFree.json create mode 100644 packages/dai-plugin-migrations/contracts/abis/DSValue.json create mode 100644 packages/dai-plugin-migrations/contracts/abis/DaiJoin.json create mode 100644 packages/dai-plugin-migrations/contracts/abis/DssProxyActionsEnd.json create mode 100644 packages/dai-plugin-migrations/contracts/abis/ESM.json create mode 100644 packages/dai-plugin-migrations/contracts/abis/GemJoin.json create mode 100644 packages/dai-plugin-migrations/src/migrations/RedeemCollateral.js create mode 100644 packages/dai-plugin-migrations/src/migrations/RedeemSai.js create mode 100644 packages/dai-plugin-migrations/test/migrations/RedeemCollateral.spec.js create mode 100644 packages/dai-plugin-migrations/test/migrations/RedeemSai.spec.js diff --git a/packages/dai-plugin-migrations/contracts/abiMap.json b/packages/dai-plugin-migrations/contracts/abiMap.json index 1fc091a05..9719c3979 100644 --- a/packages/dai-plugin-migrations/contracts/abiMap.json +++ b/packages/dai-plugin-migrations/contracts/abiMap.json @@ -6,10 +6,20 @@ "CDP_MANAGER_1": "DssCdpManager", "MCD_DAI_1": "Dai", "MCD_POT_1": "Pot", + "MCD_END": "End", + "MCD_VAT": "Vat", + "GET_CDPS": "GetCdps", + "CDP_MANAGER": "DssCdpManager", + "MCD_DAI": "Dai", + "MCD_POT": "Pot", "REDEEMER": "Redeemer", "MIGRATION": "ScdMcdMigration", "MIGRATION_PROXY_ACTIONS": "MigrationProxyActions", "OLD_CHIEF": "DSChief", "OLD_VOTE_PROXY_FACTORY": "VoteProxyFactory", - "OLD_MKR": "DSToken" -} + "OLD_MKR": "DSToken", + "MCD_JOIN_*": "GemJoin", + "PROXY_ACTIONS_END": "DssProxyActionsEnd", + "SAI_CAGEFREE": "CageFree", + "MCD_ESM": "ESM" +} \ No newline at end of file diff --git a/packages/dai-plugin-migrations/contracts/abis/CageFree.json b/packages/dai-plugin-migrations/contracts/abis/CageFree.json new file mode 100644 index 000000000..f291b462a --- /dev/null +++ b/packages/dai-plugin-migrations/contracts/abis/CageFree.json @@ -0,0 +1 @@ +[{"inputs":[{"internalType":"address","name":"_tap","type":"address"},{"internalType":"address","name":"_weth","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"FreeCash","type":"event"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"constant":false,"inputs":[{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"freeCash","outputs":[{"internalType":"uint256","name":"cashoutBalance","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"sai","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"tap","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"weth","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"}] diff --git a/packages/dai-plugin-migrations/contracts/abis/DSValue.json b/packages/dai-plugin-migrations/contracts/abis/DSValue.json new file mode 100644 index 000000000..bb6b88387 --- /dev/null +++ b/packages/dai-plugin-migrations/contracts/abis/DSValue.json @@ -0,0 +1 @@ +[{"constant":false,"inputs":[{"name":"owner_","type":"address"}],"name":"setOwner","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"wut","type":"bytes32"}],"name":"poke","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"read","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"peek","outputs":[{"name":"","type":"bytes32"},{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"authority_","type":"address"}],"name":"setAuthority","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"void","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"authority","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"anonymous":true,"inputs":[{"indexed":true,"name":"sig","type":"bytes4"},{"indexed":true,"name":"guy","type":"address"},{"indexed":true,"name":"foo","type":"bytes32"},{"indexed":true,"name":"bar","type":"bytes32"},{"indexed":false,"name":"wad","type":"uint256"},{"indexed":false,"name":"fax","type":"bytes"}],"name":"LogNote","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"authority","type":"address"}],"name":"LogSetAuthority","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"}],"name":"LogSetOwner","type":"event"}] \ No newline at end of file diff --git a/packages/dai-plugin-migrations/contracts/abis/DaiJoin.json b/packages/dai-plugin-migrations/contracts/abis/DaiJoin.json new file mode 100644 index 000000000..85a7d6e79 --- /dev/null +++ b/packages/dai-plugin-migrations/contracts/abis/DaiJoin.json @@ -0,0 +1 @@ +[{"inputs":[{"internalType":"address","name":"vat_","type":"address"},{"internalType":"address","name":"dai_","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":true,"inputs":[{"indexed":true,"internalType":"bytes4","name":"sig","type":"bytes4"},{"indexed":true,"internalType":"address","name":"usr","type":"address"},{"indexed":true,"internalType":"bytes32","name":"arg1","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"arg2","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"}],"name":"LogNote","type":"event"},{"constant":false,"inputs":[],"name":"cage","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"dai","outputs":[{"internalType":"contract DSTokenLike","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"usr","type":"address"}],"name":"deny","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"usr","type":"address"},{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"exit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"usr","type":"address"},{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"join","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"live","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"usr","type":"address"}],"name":"rely","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"vat","outputs":[{"internalType":"contract VatLike","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"wards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"}] \ No newline at end of file diff --git a/packages/dai-plugin-migrations/contracts/abis/DssProxyActionsEnd.json b/packages/dai-plugin-migrations/contracts/abis/DssProxyActionsEnd.json new file mode 100644 index 000000000..5a52aee00 --- /dev/null +++ b/packages/dai-plugin-migrations/contracts/abis/DssProxyActionsEnd.json @@ -0,0 +1 @@ +[{"constant":false,"inputs":[{"internalType":"address","name":"ethJoin","type":"address"},{"internalType":"address","name":"end","type":"address"},{"internalType":"bytes32","name":"ilk","type":"bytes32"},{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"cashETH","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"gemJoin","type":"address"},{"internalType":"address","name":"end","type":"address"},{"internalType":"bytes32","name":"ilk","type":"bytes32"},{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"cashGem","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"apt","type":"address"},{"internalType":"address","name":"urn","type":"address"},{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"daiJoin_join","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"manager","type":"address"},{"internalType":"address","name":"ethJoin","type":"address"},{"internalType":"address","name":"end","type":"address"},{"internalType":"uint256","name":"cdp","type":"uint256"}],"name":"freeETH","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"manager","type":"address"},{"internalType":"address","name":"gemJoin","type":"address"},{"internalType":"address","name":"end","type":"address"},{"internalType":"uint256","name":"cdp","type":"uint256"}],"name":"freeGem","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"daiJoin","type":"address"},{"internalType":"address","name":"end","type":"address"},{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"pack","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}] \ No newline at end of file diff --git a/packages/dai-plugin-migrations/contracts/abis/ESM.json b/packages/dai-plugin-migrations/contracts/abis/ESM.json new file mode 100644 index 000000000..fad9de4b5 --- /dev/null +++ b/packages/dai-plugin-migrations/contracts/abis/ESM.json @@ -0,0 +1 @@ +[{"inputs":[{"internalType":"address","name":"gem_","type":"address"},{"internalType":"address","name":"end_","type":"address"},{"internalType":"address","name":"pit_","type":"address"},{"internalType":"uint256","name":"min_","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":true,"inputs":[{"indexed":true,"internalType":"bytes4","name":"sig","type":"bytes4"},{"indexed":true,"internalType":"address","name":"usr","type":"address"},{"indexed":true,"internalType":"bytes32","name":"arg1","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"arg2","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"}],"name":"LogNote","type":"event"},{"constant":true,"inputs":[],"name":"Sum","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"end","outputs":[{"internalType":"contract EndLike","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"fire","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"fired","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"gem","outputs":[{"internalType":"contract GemLike","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"join","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"min","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"pit","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"sum","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"}] \ No newline at end of file diff --git a/packages/dai-plugin-migrations/contracts/abis/GemJoin.json b/packages/dai-plugin-migrations/contracts/abis/GemJoin.json new file mode 100644 index 000000000..9967dcbaf --- /dev/null +++ b/packages/dai-plugin-migrations/contracts/abis/GemJoin.json @@ -0,0 +1 @@ +[{"inputs":[{"internalType":"address","name":"vat_","type":"address"},{"internalType":"bytes32","name":"ilk_","type":"bytes32"},{"internalType":"address","name":"gem_","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":true,"inputs":[{"indexed":true,"internalType":"bytes4","name":"sig","type":"bytes4"},{"indexed":true,"internalType":"address","name":"usr","type":"address"},{"indexed":true,"internalType":"bytes32","name":"arg1","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"arg2","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"}],"name":"LogNote","type":"event"},{"constant":false,"inputs":[],"name":"cage","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"dec","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"usr","type":"address"}],"name":"deny","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"usr","type":"address"},{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"exit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"gem","outputs":[{"internalType":"contract GemLike","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"ilk","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"usr","type":"address"},{"internalType":"uint256","name":"wad","type":"uint256"}],"name":"join","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"live","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"usr","type":"address"}],"name":"rely","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"vat","outputs":[{"internalType":"contract VatLike","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"wards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"}] \ No newline at end of file diff --git a/packages/dai-plugin-migrations/contracts/addresses/kovan.json b/packages/dai-plugin-migrations/contracts/addresses/kovan.json index 8629a31f7..f16883707 100644 --- a/packages/dai-plugin-migrations/contracts/addresses/kovan.json +++ b/packages/dai-plugin-migrations/contracts/addresses/kovan.json @@ -1,15 +1,21 @@ { "TUB": "0xa71937147b55Deb8a530C7229C442Fd3F31b7db2", - "GET_CDPS_1": "0x592301a23d37c591C5856f28726AF820AF8e7014", - "CDP_MANAGER_1": "0x1476483dD8C35F25e568113C5f70249D3976ba21", - "MCD_END_1": "0x24728AcF2E2C403F5d2db4Df6834B8998e56aA5F", - "MCD_VAT_1": "0xbA987bDB501d131f766fEe8180Da5d81b34b69d9", - "MCD_DAI_1": "0x4F96Fe3b7A6Cf9725f59d353F723c1bDb64CA6Aa", - "MCD_POT_1": "0xEA190DBDC7adF265260ec4dA6e9675Fd4f5A78bb", + "GET_CDPS_1": "0x592301a23d37c591c5856f28726af820af8e7014", + "CDP_MANAGER_1": "0x1476483dd8c35f25e568113c5f70249d3976ba21", + "MCD_END_1": "0x24728acf2e2c403f5d2db4df6834b8998e56aa5f", + "MCD_VAT_1": "0xba987bdb501d131f766fee8180da5d81b34b69d9", + "MCD_DAI_1": "0x4f96fe3b7a6cf9725f59d353f723c1bdb64ca6aa", + "MCD_POT_1": "0xea190dbdc7adf265260ec4da6e9675fd4f5a78bb", "REDEEMER": "0x2c0f31271673cc29927be725104642aad65a253e", "OLD_MKR": "0x4bb514a7f83fbb13c2b41448208e89fabbcfe2fb", - "MIGRATION": "0x411B2Faa662C8e3E5cF8f01dFdae0aeE482ca7b0", - "MIGRATION_PROXY_ACTIONS": "0xF56765d255463139d3aff1613705a5520764Ab93", + "MIGRATION": "0x411b2faa662c8e3e5cf8f01dfdae0aee482ca7b0", + "MIGRATION_PROXY_ACTIONS": "0xf56765d255463139d3aff1613705a5520764ab93", "OLD_CHIEF": "0xbbffc76e94b34f72d96d054b31f6424249c1337d", - "OLD_VOTE_PROXY_FACTORY": null + "OLD_VOTE_PROXY_FACTORY": "0x3E08741A68c2d964d172793cD0Ad14292F658cd8", + "PROXY_ACTIONS_END": "0x7c3f28f174F2b0539C202a5307Ff48efa61De982", + "MCD_JOIN_ETH_A": "0x775787933e92b709f2a3c70aa87999696e74a9f8", + "MCD_JOIN_DAI": "0x5aa71a3ae1c0bd6ac27a1f28e1415fffb6f15b8c", + "MCD_JOIN_BAT_A": "0x2a4C485B1B8dFb46acCfbeCaF75b6188A59dBd0a", + "MCD_JOIN_USDC_A": "0x4c514656E7dB7B859E994322D2b511d99105C1Eb", + "SAI_CAGEFREE": "0xF3095A1822cA8fb3D0955595fA3888b68C4B8124" } diff --git a/packages/dai-plugin-migrations/contracts/addresses/mainnet.json b/packages/dai-plugin-migrations/contracts/addresses/mainnet.json index 266aba8ca..2a69e675d 100644 --- a/packages/dai-plugin-migrations/contracts/addresses/mainnet.json +++ b/packages/dai-plugin-migrations/contracts/addresses/mainnet.json @@ -9,5 +9,11 @@ "MCD_DAI_1": "0x6b175474e89094c44da98b954eedeac495271d0f", "MCD_POT_1": "0x197e90f9fad81970ba7976f33cbd77088e5d7cf7", "OLD_CHIEF": "0x8e2a84d6ade1e7fffee039a35ef5f19f13057152", - "OLD_VOTE_PROXY_FACTORY": "0xa63E145309cadaa6A903a19993868Ef7E85058BE" + "OLD_VOTE_PROXY_FACTORY": "0xa63E145309cadaa6A903a19993868Ef7E85058BE", + "PROXY_ACTIONS_END": "0x7AfF9FC9faD225e3c88cDA06BC56d8Aca774bC57", + "MCD_JOIN_ETH_A": "0x2f0b23f53734252bda2277357e97e1517d6b042a", + "MCD_JOIN_DAI": "0x9759a6ac90977b93b58547b4a71c78317f391a28", + "MCD_JOIN_BAT_A": "0x3D0B1912B66114d4096F48A8CEe3A56C231772cA", + "MCD_JOIN_USDC_A": "0xA191e578a6736167326d05c119CE0c90849E84B7", + "SAI_CAGEFREE": "0x9fdc15106da755f9FfD5b0BA9854Cfb89602E0fd" } diff --git a/packages/dai-plugin-migrations/contracts/addresses/testnet.json b/packages/dai-plugin-migrations/contracts/addresses/testnet.json index 3dc10a265..f78df368e 100644 --- a/packages/dai-plugin-migrations/contracts/addresses/testnet.json +++ b/packages/dai-plugin-migrations/contracts/addresses/testnet.json @@ -1,5 +1,6 @@ { "TUB": "0xE82CE3D6Bf40F2F9414C8d01A35E3d9eb16a1761", + "TAP": "0x6896659267c3c9fd055d764327199a98e571e00d", "GET_CDPS_1": "0x883c76966eA1D1AFEC54a1c20f84A57a287BB021", "CDP_MANAGER_1": "0xb3dc8De316349D8cE5168FE33C2E75c4f0cd0FFE", "MCD_END_1": "0xb002A319887185e56d787A5c90900e13834a85E3", @@ -11,5 +12,12 @@ "OLD_CHIEF": "0x1d24598fa8B77811E68243A2746CC553E68ca03B", "OLD_VOTE_PROXY_FACTORY": "0xa9D33Ce18803b0742460ffb1b33B6c40f95178BC", "MIGRATION": "0x2978B18F7c68B2957e701FC6D82C8De5B55833f2", - "MIGRATION_PROXY_ACTIONS": "0x19BDC4b950285a608E50F3b5E7DF154FacBda861" + "MIGRATION_PROXY_ACTIONS": "0x19BDC4b950285a608E50F3b5E7DF154FacBda861", + "PROXY_ACTIONS_END": "0x5E6085775Cd0B41fC70d1A6B48a0451bf7aCa801", + "MCD_JOIN_ETH_A": "0xF7Cbc73FE7d30c68AD7b64D293D4F52F76027261", + "MCD_JOIN_DAI": "0x55320248dC50Ef6dABc88ECbc294Fd5e2e1f4eC6", + "MCD_JOIN_BAT_A": "0xEB9d9336b4A89260bC4B94ee6a34e2faF46B0CA5", + "MCD_JOIN_USDC_A": "0x77d6250c22eCBA016a4F6D1a917BF5b2ED0704C5", + "SAI_CAGEFREE": "0xb0ae8c0856259C6fe000F8e2C14507E5FC167D48", + "MCD_ESM": "0x2125C30dA5DcA0819aEC5e4cdbF58Bfe91918e43" } diff --git a/packages/dai-plugin-migrations/scripts/install-testchain-outputs.sh b/packages/dai-plugin-migrations/scripts/install-testchain-outputs.sh index 4936ff5df..7d3e9c08f 100755 --- a/packages/dai-plugin-migrations/scripts/install-testchain-outputs.sh +++ b/packages/dai-plugin-migrations/scripts/install-testchain-outputs.sh @@ -8,7 +8,7 @@ CONTRACTS=$CWD/../contracts SOURCE=${1:-$CWD/../../../node_modules/@makerdao/testchain} # Relevant contracts from SCD: -for CONTRACT in "TUB","SaiTub" "REDEEMER","Redeemer" "OLD_MKR","DSToken" "OLD_CHIEF","DSChief" +for CONTRACT in "TUB","SaiTub" "REDEEMER","Redeemer" "OLD_MKR","DSToken" "OLD_CHIEF","DSChief" "SAI_CAGEFREE","CageFree" "OLD_VOTE_PROXY_FACTORY","VoteProxyFactory" do IFS=',' read NAME ABI <<< "${CONTRACT}" ADDRESS=`jq ".$NAME" "$SOURCE/out/addresses.json"` @@ -17,6 +17,15 @@ do done # Relevant contracts from MCD: +for CONTRACT in "MCD_JOIN_ETH_A","GemJoin" "MCD_JOIN_DAI","DaiJoin" "MCD_JOIN_BAT_A","GemJoin" "MIGRATION","ScdMcdMigration" "MIGRATION_PROXY_ACTIONS","MigrationProxyActions" "PROXY_ACTIONS_END","DssProxyActionsEnd" "MCD_JOIN_USDC_A","GemJoin" "MCD_ESM","ESM" +do + IFS=',' read NAME ABI <<< "${CONTRACT}" + ADDRESS=`jq ".$NAME" "$SOURCE/out/addresses-mcd.json"` + jq ".$NAME=$ADDRESS" $CONTRACTS/addresses/testnet.json > testnet.tmp && mv testnet.tmp $CONTRACTS/addresses/testnet.json + cp $SOURCE/out/mcd/$ABI.abi $CONTRACTS/abis/$ABI.json +done + +# Contracts (from MCD) with numbered versions: for CONTRACT in "MCD_END","END" "MCD_VAT","VAT" "GET_CDPS","GetCdps" "CDP_MANAGER","DssCdpManager" "MCD_DAI","Dai" "MCD_POT","Pot" do IFS=',' read NAME ABI <<< "${CONTRACT}" diff --git a/packages/dai-plugin-migrations/src/MigrationService.js b/packages/dai-plugin-migrations/src/MigrationService.js index d788feb36..13fdbca7b 100644 --- a/packages/dai-plugin-migrations/src/MigrationService.js +++ b/packages/dai-plugin-migrations/src/MigrationService.js @@ -8,6 +8,9 @@ import SaiToDai from './migrations/SaiToDai'; import MkrRedeemer from './migrations/MkrRedeemer'; import DaiToSai from './migrations/DaiToSai'; import ChiefMigrate from './migrations/ChiefMigrate'; +import RedeemSai from './migrations/RedeemSai'; +import RedeemCollateral from './migrations/RedeemCollateral'; + const { SINGLE_TO_MULTI_CDP, SAI_TO_DAI, @@ -24,7 +27,9 @@ const migrations = { [Migrations.GLOBAL_SETTLEMENT_SAVINGS_DAI]: GlobalSettlementSavingsDai, [Migrations.GLOBAL_SETTLEMENT_COLLATERAL_CLAIMS]: GlobalSettlementCollateralClaims, [Migrations.GLOBAL_SETTLEMENT_DAI_REDEEMER]: GlobalSettlementDaiRedeemer, - [Migrations.MKR_REDEEMER]: MkrRedeemer + [Migrations.MKR_REDEEMER]: MkrRedeemer, + [Migrations.REDEEM_SAI]: RedeemSai, + [Migrations.REDEEM_COLLATERAL]: RedeemCollateral }; export default class MigrationService extends PublicService { @@ -58,7 +63,10 @@ export default class MigrationService extends PublicService { [SAI_TO_DAI]: await this.getMigration(SAI_TO_DAI).check(), [DAI_TO_SAI]: await this.getMigration(DAI_TO_SAI).check(), [CHIEF_MIGRATE]: await this.getMigration(CHIEF_MIGRATE).check(), - [MKR_REDEEMER]: await this.getMigration(MKR_REDEEMER).check() + [MKR_REDEEMER]: await this.getMigration(MKR_REDEEMER).check(), + [Migrations.GLOBAL_SETTLEMENT_COLLATERAL_CLAIMS]: await this.getMigration( + Migrations.GLOBAL_SETTLEMENT_COLLATERAL_CLAIMS + ).check() }; } diff --git a/packages/dai-plugin-migrations/src/constants.js b/packages/dai-plugin-migrations/src/constants.js index 8b7520716..9dfbd6efe 100644 --- a/packages/dai-plugin-migrations/src/constants.js +++ b/packages/dai-plugin-migrations/src/constants.js @@ -12,7 +12,9 @@ export const Migrations = { GLOBAL_SETTLEMENT_COLLATERAL_CLAIMS: 'global-settlement-collateral-claims', GLOBAL_SETTLEMENT_DAI_REDEEMER: 'global-settlement-dai-redeemer', MKR_REDEEMER: 'mkr-redeemer', - CHIEF_MIGRATE: 'chief-migrate' + CHIEF_MIGRATE: 'chief-migrate', + REDEEM_SAI: 'redeem-sai', + REDEEM_COLLATERAL: 'redeem-collateral' }; export const WAD = new BigNumber('1e18'); diff --git a/packages/dai-plugin-migrations/src/migrations/GlobalSettlementCollateralClaims.js b/packages/dai-plugin-migrations/src/migrations/GlobalSettlementCollateralClaims.js index 64ea021ff..05f0cf93c 100644 --- a/packages/dai-plugin-migrations/src/migrations/GlobalSettlementCollateralClaims.js +++ b/packages/dai-plugin-migrations/src/migrations/GlobalSettlementCollateralClaims.js @@ -9,28 +9,27 @@ export default class GlobalSettlementCollateralClaims { async check() { const end = this._container.get('smartContract').getContract('MCD_END_1'); - const isInGlobalSettlement = !(await end.live()); - if (!isInGlobalSettlement) return false; - - const address = - (await this._container.get('proxy').currentProxy()) || - this._container.get('accounts').currentAddress(); - + const live = await end.live(); + const emergencyShutdownActive = live.eq(0); + if (!emergencyShutdownActive) return false; + const address = await this._container.get('proxy').currentProxy(); + if (!address) return false; const cdpManager = this._container .get('smartContract') .getContract('CDP_MANAGER_1'); const vat = this._container.get('smartContract').getContract('MCD_VAT_1'); - const [ids, , ilks] = await this._container + const cdps = await this._container .get('smartContract') .getContract('GET_CDPS_1') .getCdpsDesc(cdpManager.address, address); + const { ids, ilks } = cdps; const freeCollateral = await Promise.all( ids.map(async (id, i) => { const urn = await cdpManager.urns(id); const vatUrn = await vat.urns(ilks[i], urn); - const tag = await end.tags(ilks[i]); + const tag = await end.tag(ilks[i]); const ilk = await vat.ilks(ilks[i]); const owed = new BigNumber(vatUrn.art) @@ -38,11 +37,67 @@ export default class GlobalSettlementCollateralClaims { .div(RAY) .times(tag) .div(RAY); - - return tag.gt(0) && new BigNumber(vatUrn.ink).minus(owed).gt(0); + const redeemable = + tag.gt(0) && new BigNumber(vatUrn.ink).minus(owed).gt(0); + const tagDivRay = new BigNumber(tag).div(RAY); + return { id, owed, redeemable, ilk, urn, tag: tagDivRay }; }) ); + if (!freeCollateral.some(v => v.redeemable)) return false; + return freeCollateral; + } + + freeEth(cdpId) { + const cdpManagerAddress = this._container + .get('smartContract') + .getContractAddress('CDP_MANAGER_1'); + const endAddress = this._container + .get('smartContract') + .getContractAddress('MCD_END_1'); + const ethJoinAddress = this._container + .get('smartContract') + .getContractAddress('MCD_JOIN_ETH_A'); + return this._container + .get('smartContract') + .getContract('PROXY_ACTIONS_END') + .freeETH(cdpManagerAddress, ethJoinAddress, endAddress, cdpId, { + dsProxy: true + }); + } - return freeCollateral.some(exists => exists); + freeBat(cdpId) { + const cdpManagerAddress = this._container + .get('smartContract') + .getContractAddress('CDP_MANAGER_1'); + const endAddress = this._container + .get('smartContract') + .getContractAddress('MCD_END_1'); + const gemJoinAddress = this._container + .get('smartContract') + .getContractAddress('MCD_JOIN_BAT_A'); + return this._container + .get('smartContract') + .getContract('PROXY_ACTIONS_END') + .freeGem(cdpManagerAddress, gemJoinAddress, endAddress, cdpId, { + dsProxy: true + }); + } + + freeUsdc(cdpId) { + const cdpManagerAddress = this._container + .get('smartContract') + .getContractAddress('CDP_MANAGER_1'); + const endAddress = this._container + .get('smartContract') + .getContractAddress('MCD_END_1'); + const gemJoinAddress = this._container + .get('smartContract') + .getContractAddress('MCD_JOIN_USDC_A'); + return this._container + .get('smartContract') + .getContract('PROXY_ACTIONS_END') + .freeGem(cdpManagerAddress, gemJoinAddress, endAddress, cdpId, { + dsProxy: true + }); } } diff --git a/packages/dai-plugin-migrations/src/migrations/GlobalSettlementDaiRedeemer.js b/packages/dai-plugin-migrations/src/migrations/GlobalSettlementDaiRedeemer.js index 633118862..f4cb22247 100644 --- a/packages/dai-plugin-migrations/src/migrations/GlobalSettlementDaiRedeemer.js +++ b/packages/dai-plugin-migrations/src/migrations/GlobalSettlementDaiRedeemer.js @@ -1,4 +1,7 @@ import { MDAI_1 } from '../index'; +import { stringToBytes } from '../utils'; +import BigNumber from 'bignumber.js'; +import { WAD } from '../constants'; export default class GlobalSettlementDaiRedeemer { constructor(container) { @@ -24,6 +27,7 @@ export default class GlobalSettlementDaiRedeemer { const cdpManagerAddress = smartContract.getContractAddress('CDP_MANAGER_1'); + //TODO; don't just look at ilks related to the address's Vaults const [, , ilks] = await smartContract .getContract('GET_CDPS_1') .getCdpsDesc(cdpManagerAddress, address); @@ -37,4 +41,84 @@ export default class GlobalSettlementDaiRedeemer { return fixes.some(fix => fix.gt(0)); } + + async endGemBalance(ilk) { + const vat = this._container.get('smartContract').getContract('MCD_VAT_1'); + const endAddress = this._container + .get('smartContract') + .getContractAddress('MCD_END_1'); + const gemBalance = await vat.gem(stringToBytes(ilk), endAddress); + return BigNumber(gemBalance).div(WAD); + } + + async bagAmount(address) { + const end = this._container.get('smartContract').getContract('MCD_END_1'); + const bag = await end.bag(address); + return MDAI_1.wei(bag); + } + + async packDai(daiAmount) { + const formattedAmount = MDAI_1(daiAmount).toFixed('wei'); + const endAddress = this._container + .get('smartContract') + .getContractAddress('MCD_END_1'); + const daiJoinAddress = this._container + .get('smartContract') + .getContractAddress('MCD_JOIN_DAI'); + return this._container + .get('smartContract') + .getContract('PROXY_ACTIONS_END') + .pack(daiJoinAddress, endAddress, formattedAmount, { dsProxy: true }); + } + + async cashEth(daiAmount) { + const formattedAmount = MDAI_1(daiAmount).toFixed('wei'); + const joinAddress = this._container + .get('smartContract') + .getContractAddress('MCD_JOIN_ETH_A'); + const endAddress = this._container + .get('smartContract') + .getContractAddress('MCD_END_1'); + const ilkBytes = stringToBytes('ETH-A'); + return this._container + .get('smartContract') + .getContract('PROXY_ACTIONS_END') + .cashETH(joinAddress, endAddress, ilkBytes, formattedAmount, { + dsProxy: true + }); + } + + async cashBat(daiAmount) { + const formattedAmount = MDAI_1(daiAmount).toFixed('wei'); + const joinAddress = this._container + .get('smartContract') + .getContractAddress('MCD_JOIN_BAT_A'); + const endAddress = this._container + .get('smartContract') + .getContractAddress('MCD_END_1'); + const ilkBytes = stringToBytes('BAT-A'); + return this._container + .get('smartContract') + .getContract('PROXY_ACTIONS_END') + .cashGem(joinAddress, endAddress, ilkBytes, formattedAmount, { + dsProxy: true + }); + } + + async cashUsdc(daiAmount) { + const formattedAmount = MDAI_1(daiAmount).toFixed('wei'); + const joinAddress = this._container + .get('smartContract') + .getContractAddress('MCD_JOIN_USDC_A'); + const endAddress = this._container + .get('smartContract') + .getContractAddress('MCD_END_1'); + const ilkBytes = stringToBytes('USDC-A'); + return this._container + .get('smartContract') + .getContract('PROXY_ACTIONS_END') + .cashGem(joinAddress, endAddress, ilkBytes, formattedAmount, { + dsProxy: true + }); + } } diff --git a/packages/dai-plugin-migrations/src/migrations/GlobalSettlementSavingsDai.js b/packages/dai-plugin-migrations/src/migrations/GlobalSettlementSavingsDai.js index 663a46186..1412fea9b 100644 --- a/packages/dai-plugin-migrations/src/migrations/GlobalSettlementSavingsDai.js +++ b/packages/dai-plugin-migrations/src/migrations/GlobalSettlementSavingsDai.js @@ -7,7 +7,7 @@ export default class GlobalSettlementSavingsDai { async check() { const smartContract = this._container.get('smartContract'); const end = smartContract.getContract('MCD_END_1'); - const isInGlobalSettlement = !(await end.live()); + const isInGlobalSettlement = (await end.live()).eq(0); if (!isInGlobalSettlement) return false; const address = diff --git a/packages/dai-plugin-migrations/src/migrations/RedeemCollateral.js b/packages/dai-plugin-migrations/src/migrations/RedeemCollateral.js new file mode 100644 index 000000000..ebfdec127 --- /dev/null +++ b/packages/dai-plugin-migrations/src/migrations/RedeemCollateral.js @@ -0,0 +1,25 @@ +export default class RedeemCollateral { + constructor(manager) { + this._manager = manager; + return this; + } + + _contract(name) { + return this._manager.get('smartContract').getContract(name); + } + + cooldown() { + return this._contract('SAI_TOP').cooldown(); + } + + async pethInTap() { + const fog = await this._contract('SAI_TAP').fog(); + return fog / Math.pow(10, 18); + } + + redeemCollateral(cdp, wad) { + // This will be replaced with the new contract method + // that atomically exits/unwraps + return cdp.freePeth(wad); + } +} diff --git a/packages/dai-plugin-migrations/src/migrations/RedeemSai.js b/packages/dai-plugin-migrations/src/migrations/RedeemSai.js new file mode 100644 index 000000000..3f105d538 --- /dev/null +++ b/packages/dai-plugin-migrations/src/migrations/RedeemSai.js @@ -0,0 +1,25 @@ +import { DAI } from '..'; + +export default class RedeemSai { + constructor(manager) { + this._manager = manager; + this._tap = this._manager.get('smartContract').getContract('SAI_TAP'); + return this; + } + + off() { + return this._tap.off(); + } + + async getRate() { + const fix = await this._tap.fix(); + return fix / Math.pow(10, 27); + } + + redeemSai(wad) { + const cageFree = this._manager + .get('smartContract') + .getContract('SAI_CAGEFREE'); + return cageFree.freeCash(DAI(wad).toFixed(18)); + } +} diff --git a/packages/dai-plugin-migrations/src/migrations/SingleToMultiCdp.js b/packages/dai-plugin-migrations/src/migrations/SingleToMultiCdp.js index f3a9e510e..2fad162f7 100644 --- a/packages/dai-plugin-migrations/src/migrations/SingleToMultiCdp.js +++ b/packages/dai-plugin-migrations/src/migrations/SingleToMultiCdp.js @@ -1,6 +1,7 @@ import { tracksTransactionsWithOptions } from '../utils'; import { getIdBytes, stringToBytes } from '../utils'; import { SAI, MKR } from '..'; +import dsValue from '../../contracts/abis/DSValue.json'; export default class SingleToMultiCdp { constructor(manager) { @@ -10,6 +11,36 @@ export default class SingleToMultiCdp { async check() { const address = this._manager.get('accounts').currentAddress(); + + if (global.scdESTest) { + if (global.testnet) { + console.log('fudging cdp id data for testnet'); + const proxyAddress = await this._manager.get('proxy').currentProxy(); + return { + [address]: [1], + [proxyAddress]: [2, 3, 4, 5, 6] + }; + } + + console.log('looking up cdp ids from logs; excludes proxy cdps'); + const scs = this._manager.get('smartContract'); + const ws = this._manager.get('web3'); + const { utils } = ws._web3; + const { LogNewCup } = scs.getContract('SAI_TUB').interface.events; + + const logs = await ws.getPastLogs({ + address: scs.getContractAddress('SAI_TUB'), + topics: [ + utils.keccak256(utils.toHex(LogNewCup.signature)), + '0x000000000000000000000000' + address.replace(/^0x/, '') + ], + fromBlock: 4750000 // Dec 17, 2017 on mainnet; earlier on Kovan + }); + return logs.length > 0 + ? { [address]: logs.map(l => parseInt(l.data, 16)) } + : {}; + } + const proxyAddress = await this._manager.get('proxy').currentProxy(); const idsFromProxy = proxyAddress ? await this._manager.get('cdp').getCdpIds(proxyAddress) @@ -46,6 +77,17 @@ export default class SingleToMultiCdp { } async _requireAllowance(cupId, payment) { + const pepAddress = await this._manager + .get('smartContract') + .getContract('SAI_TUB') + .pep(); + const mkrOracleActive = ( + await this._manager + .get('smartContract') + .getContractByAddressAndAbi(pepAddress, dsValue) + .peek() + )[1]; + if (payment === 'MKR' && !mkrOracleActive) return; const address = this._manager.get('web3').currentAddress(); const proxyAddress = await this._manager.get('proxy').currentProxy(); const cdp = await this._manager.get('cdp').getCdp(cupId); diff --git a/packages/dai-plugin-migrations/test/MigrationService.spec.js b/packages/dai-plugin-migrations/test/MigrationService.spec.js index 21973758d..654540e6b 100644 --- a/packages/dai-plugin-migrations/test/MigrationService.spec.js +++ b/packages/dai-plugin-migrations/test/MigrationService.spec.js @@ -7,6 +7,8 @@ import GlobalSettlementSavingsDai from '../src/migrations/GlobalSettlementSaving import GlobalSettlementCollateralClaims from '../src/migrations/GlobalSettlementCollateralClaims'; import GlobalSettlementDaiRedeemer from '../src/migrations/GlobalSettlementDaiRedeemer'; import MkrRedeemer from '../src/migrations/MkrRedeemer'; +import RedeemSai from '../src/migrations/RedeemSai'; +import RedeemCollateral from '../src/migrations/RedeemCollateral'; let maker, service; @@ -41,10 +43,12 @@ test('can fetch a list of all migrations', () => { Migrations.GLOBAL_SETTLEMENT_COLLATERAL_CLAIMS, Migrations.GLOBAL_SETTLEMENT_DAI_REDEEMER, Migrations.MKR_REDEEMER, - Migrations.CHIEF_MIGRATE + Migrations.CHIEF_MIGRATE, + Migrations.REDEEM_SAI, + Migrations.REDEEM_COLLATERAL ]) ); - expect(ids.length).toEqual(8); + expect(ids.length).toEqual(10); }); test('getting each migration returns a valid migration', () => { @@ -64,6 +68,10 @@ test('getting each migration returns a valid migration', () => { expect(service.getMigration(Migrations.MKR_REDEEMER)).toBeInstanceOf( MkrRedeemer ); + expect(service.getMigration(Migrations.REDEEM_SAI)).toBeInstanceOf(RedeemSai); + expect(service.getMigration(Migrations.REDEEM_COLLATERAL)).toBeInstanceOf( + RedeemCollateral + ); }); test('getting a non-existent migration returns undefined', () => { @@ -78,7 +86,8 @@ test('runAllChecks', async () => { [Migrations.DAI_TO_SAI]: expect.anything(), [Migrations.SINGLE_TO_MULTI_CDP]: {}, [Migrations.CHIEF_MIGRATE]: expect.anything(), - [Migrations.MKR_REDEEMER]: expect.anything() + [Migrations.MKR_REDEEMER]: expect.anything(), + [Migrations.GLOBAL_SETTLEMENT_COLLATERAL_CLAIMS]: expect.anything() }); - // expect(result[Migrations.SAI_TO_DAI].eq(0)).toBeTruthy(); + expect(result[Migrations.SAI_TO_DAI].eq(0)).toBeTruthy(); }); diff --git a/packages/dai-plugin-migrations/test/helpers/index.js b/packages/dai-plugin-migrations/test/helpers/index.js index c9dbed70f..96d727ab8 100644 --- a/packages/dai-plugin-migrations/test/helpers/index.js +++ b/packages/dai-plugin-migrations/test/helpers/index.js @@ -133,11 +133,40 @@ export async function migrateSaiToDai(amount, maker) { await daiMigration.execute(amount); } -// // Get wad amount of SAI from user's wallet: -// saiJoin.gem().transferFrom(msg.sender, address(this), wad); -// // Join the SAI wad amount to the `vat`: -// saiJoin.join(address(this), wad); -// // Lock the SAI wad amount to the CDP and generate the same wad amount of DAI -// vat.frob(saiJoin.ilk(), address(this), address(this), address(this), toInt(wad), toInt(wad)); -// // Send DAI wad amount as a ERC20 token to the user's wallet -// daiJoin.exit(msg.sender, wad); +export async function shutDown(randomize) { + const maker = await migrationMaker(); + const top = maker.service('smartContract').getContract('SAI_TOP'); + const proxy = await maker.service('proxy').ensureProxy(); + const normalCdp = await openLockAndDrawScdCdp(maker, randomize); + + const bites = []; + for (let i = 0; i < (randomize ? 5 : 1); i++) { + console.log('creating', i); + const proxyCdp = await maker + .service('cdp') + .openProxyCdpLockEthAndDrawSai( + 2 + (randomize ? Math.random() : 0), + 103 + (randomize ? Math.random() * 20 : 0), + proxy + ); + + bites.push(() => proxyCdp.bite()); + } + + await top.cage(); + await normalCdp.bite(); + for (let i = 0; i < bites.length; i++) { + console.log('biting', i); + await bites[i](); + } + await top.setCooldown(0); + await new Promise(r => setTimeout(r, 1000)); + await top.flow(); +} + +async function openLockAndDrawScdCdp(maker, randomize) { + const cdp = await maker.service('cdp').openCdp(); + await cdp.lockEth(1 + (randomize ? Math.random() : 0)); + await cdp.drawSai(111 + (randomize ? Math.random() * 20 : 0)); + return cdp; +} diff --git a/packages/dai-plugin-migrations/test/helpers/mocks.js b/packages/dai-plugin-migrations/test/helpers/mocks.js index 219e8010e..5a91e8fb1 100644 --- a/packages/dai-plugin-migrations/test/helpers/mocks.js +++ b/packages/dai-plugin-migrations/test/helpers/mocks.js @@ -19,18 +19,18 @@ export async function mockCdpIds(maker, { forAccount, forProxy } = {}) { export const globalSettlement = { beforeCage: () => ({ - live: async () => true, - tags: async () => new BigNumber(0), + live: async () => new BigNumber(1), + tag: async () => new BigNumber(0), fix: async () => new BigNumber(0) }), afterCage: () => ({ - live: async () => false, - tags: async () => new BigNumber(0), + live: async () => new BigNumber(0), + tag: async () => new BigNumber(0), fix: async () => new BigNumber(0) }), afterCageCollateral: tags => ({ - live: async () => false, - tags: async ilk => { + live: async () => new BigNumber(0), + tag: async ilk => { const ilkAsString = bytesToString(ilk); return tags[ilkAsString] ? RAY.times(new BigNumber(1).div(tags[ilkAsString])) @@ -39,7 +39,7 @@ export const globalSettlement = { fix: async () => new BigNumber(0) }), afterFlow: fixes => ({ - live: async () => false, + live: async () => new BigNumber(0), fix: async ilk => { const ilkAsString = bytesToString(ilk); return fixes[ilkAsString] diff --git a/packages/dai-plugin-migrations/test/kovan/kovan.test.js b/packages/dai-plugin-migrations/test/kovan/kovan.test.js index f44ebdc9d..6055bca8a 100644 --- a/packages/dai-plugin-migrations/test/kovan/kovan.test.js +++ b/packages/dai-plugin-migrations/test/kovan/kovan.test.js @@ -1,7 +1,6 @@ import Maker from '@makerdao/dai'; import McdPlugin from '@makerdao/dai-plugin-mcd'; import MigrationPlugin from '../../src'; -import { SAI, MKR } from '../../src'; import { ServiceRoles, Migrations } from '../../src/constants'; async function mcdMaker({ @@ -35,16 +34,14 @@ async function mcdMaker({ } async function openLockAndDrawScdCdp(drawAmount, maker) { - const cdp = await maker.openCdp({ dsProxy: true }); + const cdp = await maker.service('cdp').openCdp({ dsProxy: true }); await cdp.lockEth('0.1', { dsProxy: true }); - await cdp.drawDai(drawAmount, { dsProxy: true }); + await cdp.drawSai(drawAmount, { dsProxy: true }); return cdp; } xtest('kovan', async () => { const maker = await mcdMaker(); - const sai = maker.getToken(SAI); - const mkr = maker.getToken(MKR); const migrationContract = maker .service('smartContract') .getContract('MIGRATION'); @@ -59,7 +56,6 @@ xtest('kovan', async () => { // await mkr.approveUnlimited(proxyAddress); const cdp = await openLockAndDrawScdCdp('1', maker); - const info = await cdp.getInfo(); await cdp.give(proxyAddress); const id = cdp.id; await migrationContract.swapSaiToDai('5000000000000000000'); diff --git a/packages/dai-plugin-migrations/test/migrations/ChiefMigrate.spec.js b/packages/dai-plugin-migrations/test/migrations/ChiefMigrate.spec.js index 0fd210fa5..59ae543cd 100644 --- a/packages/dai-plugin-migrations/test/migrations/ChiefMigrate.spec.js +++ b/packages/dai-plugin-migrations/test/migrations/ChiefMigrate.spec.js @@ -31,7 +31,7 @@ describe('Chief Migration', () => { expect(mkrLockedViaProxy.toNumber()).toBe(0); }); - xtest('if the account has some MKR locked directly in old chief, return the amount', async () => { + test('if the account has some MKR locked directly in old chief, return the amount', async () => { const oldChief = maker .service('smartContract') .getContractByName('OLD_CHIEF'); @@ -45,11 +45,11 @@ describe('Chief Migration', () => { await oldChief.lock(LOCK_AMOUNT.toFixed('wei')); const { mkrLockedDirectly, mkrLockedViaProxy } = await migration.check(); - expect(mkrLockedViaProxy.toNumber()).toBe(0); expect(mkrLockedDirectly.isEqual(LOCK_AMOUNT)).toBeTruthy(); + expect(mkrLockedViaProxy.toNumber()).toBe(0); }); - xtest('if the account has some MKR locked via proxy in old chief, return the amount', async () => { + test('if the account has some MKR locked via proxy in old chief, return the amount', async () => { const oldVoteProxyFactory = maker .service('smartContract') .getContractByName('OLD_VOTE_PROXY_FACTORY'); @@ -85,7 +85,7 @@ describe('Chief Migration', () => { await voteProxy.lock(LOCK_AMOUNT.toFixed('wei')); const { mkrLockedDirectly, mkrLockedViaProxy } = await migration.check(); - expect(mkrLockedViaProxy.isEqual(LOCK_AMOUNT)).toBeTruthy(); expect(mkrLockedDirectly.toNumber()).toBe(0); + expect(mkrLockedViaProxy.isEqual(LOCK_AMOUNT)).toBeTruthy(); }); }); diff --git a/packages/dai-plugin-migrations/test/migrations/GlobalSettlementCollateralClaims.spec.js b/packages/dai-plugin-migrations/test/migrations/GlobalSettlementCollateralClaims.spec.js index c6d17dfac..47c8ee028 100644 --- a/packages/dai-plugin-migrations/test/migrations/GlobalSettlementCollateralClaims.spec.js +++ b/packages/dai-plugin-migrations/test/migrations/GlobalSettlementCollateralClaims.spec.js @@ -29,8 +29,8 @@ describe('Global Settlement Collateral Claims migration', () => { test('if the system is NOT in global settlement and there is no collateral, return false', async () => { mockContracts(smartContract, { MCD_END_1: globalSettlement.beforeCage() }); - - expect(await migration.check()).toBeFalsy(); + const check = await migration.check(); + expect(check).toBe(false); }); test('if the system is NOT in global settlement and there is collateral, return false', async () => { @@ -38,14 +38,14 @@ describe('Global Settlement Collateral Claims migration', () => { await setupCollateral(maker, 'ETH-A', { price: 150, debtCeiling: 50 }); await cdpManager.openLockAndDraw('ETH-A', ETH(0.1), MDAI(1)); - - expect(await migration.check()).toBeFalsy(); + const check = await migration.check(); + expect(check).toBe(false); }); test('if the system IS in global settlement, but collateral is not caged, and there is no collateral, return false', async () => { mockContracts(smartContract, { MCD_END_1: globalSettlement.afterCage() }); - - expect(await migration.check()).toBeFalsy(); + const check = await migration.check(); + expect(check).toBe(false); }); test('if the system IS in global settlement, but collateral is not caged, and there is collateral, return false', async () => { @@ -53,16 +53,16 @@ describe('Global Settlement Collateral Claims migration', () => { await cdpManager.openLockAndDraw('ETH-A', ETH(0.1), MDAI(1)); mockContracts(smartContract, { MCD_END_1: globalSettlement.afterCage() }); - - expect(await migration.check()).toBeFalsy(); + const check = await migration.check(); + expect(check).toBe(false); }); test('if the system IS in global settlement and collateral is caged, and there is no collateral, return false', async () => { mockContracts(smartContract, { MCD_END_1: globalSettlement.afterCageCollateral({ 'ETH-A': 150 }) }); - - expect(await migration.check()).toBeFalsy(); + const check = await migration.check(); + expect(check).toBe(false); }); test('if the system IS in global settlement and collateral is caged, and there is NO collateral to skim, return false', async () => { @@ -72,8 +72,8 @@ describe('Global Settlement Collateral Claims migration', () => { mockContracts(smartContract, { MCD_END_1: globalSettlement.afterCageCollateral({ 'ETH-A': 80 }) }); - - expect(await migration.check()).toBeFalsy(); + const check = await migration.check(); + expect(check).toBe(false); }); test('if the system IS in global settlement and collateral is caged, and there IS collateral to skim, return true', async () => { @@ -83,7 +83,20 @@ describe('Global Settlement Collateral Claims migration', () => { mockContracts(smartContract, { MCD_END_1: globalSettlement.afterCageCollateral({ 'ETH-A': 150 }) }); + const num = (await migration.check()).filter(c => c.redeemable).length; + expect(num).toBe(1); + }); - expect(await migration.check()).toBeTruthy(); + xtest('freeEth', async () => { + await setupCollateral(maker, 'ETH-A', { price: 150, debtCeiling: 50 }); + const cdp = await cdpManager.openLockAndDraw('ETH-A', ETH(0.1), MDAI(1)); + mockContracts(smartContract, { + MCD_END_1: globalSettlement.afterCageCollateral({ 'ETH-A': 150 }) + }); + //somehow check eth balance to be returned + //check Eth balance + //call free eth + await migration.freeEth(cdp.id); + //confirm eth balance = prev eth balance - eth to be freed }); }); diff --git a/packages/dai-plugin-migrations/test/migrations/GlobalSettlementDaiRedeemer.spec.js b/packages/dai-plugin-migrations/test/migrations/GlobalSettlementDaiRedeemer.spec.js index 02b3e1f0c..c819a2f88 100644 --- a/packages/dai-plugin-migrations/test/migrations/GlobalSettlementDaiRedeemer.spec.js +++ b/packages/dai-plugin-migrations/test/migrations/GlobalSettlementDaiRedeemer.spec.js @@ -1,7 +1,6 @@ import { migrationMaker, setupCollateral } from '../helpers'; import { mockContracts, globalSettlement } from '../helpers/mocks'; import { takeSnapshot, restoreSnapshot } from '@makerdao/test-helpers'; -import TestAccountProvider from '@makerdao/test-helpers/src/TestAccountProvider'; import { ServiceRoles, Migrations } from '../../src/constants'; import { MDAI, ETH } from '@makerdao/dai-plugin-mcd'; @@ -59,7 +58,7 @@ describe('Global Settlement Dai Redeemer migration', () => { expect(await migration.check()).toBeFalsy(); }); - test('if the system IS in global settlement, collateral price has been fixed, the user owns DAI, and the user has locked collateral, return true', async () => { + xtest('if the system IS in global settlement, collateral price has been fixed, the user owns DAI, return true', async () => { await setupCollateral(maker, 'ETH-A', { price: 150, debtCeiling: 50 }); await cdpManager.openLockAndDraw('ETH-A', ETH(0.1), MDAI(9)); @@ -71,26 +70,4 @@ describe('Global Settlement Dai Redeemer migration', () => { expect(await migration.check()).toBeTruthy(); }); - - test('if the system IS in global settlement, collateral price has been fixed, the user owns DAI, but the user does NOT have locked collateral, return false', async () => { - await setupCollateral(maker, 'ETH-A', { price: 150, debtCeiling: 50 }); - await cdpManager.openLockAndDraw('ETH-A', ETH(0.1), MDAI(9)); - - const account2 = TestAccountProvider.nextAccount(); - - const mdai = maker.service('token').getToken(MDAI); - await mdai.transfer(account2.address, 9); - - await maker.addAccount({ ...account2, type: 'privateKey' }); - maker.useAccount(account2.address); - expect((await mdai.balance()).toNumber()).toBe(9); - - mockContracts(smartContract, { - MCD_END_1: globalSettlement.afterFlow({ - 'ETH-A': 10 - }) - }); - - expect(await migration.check()).toBeFalsy(); - }); }); diff --git a/packages/dai-plugin-migrations/test/migrations/RedeemCollateral.spec.js b/packages/dai-plugin-migrations/test/migrations/RedeemCollateral.spec.js new file mode 100644 index 000000000..c22758c9c --- /dev/null +++ b/packages/dai-plugin-migrations/test/migrations/RedeemCollateral.spec.js @@ -0,0 +1,41 @@ +import { migrationMaker, shutDown } from '../helpers'; +import { ServiceRoles, Migrations } from '../../src/constants'; +import { takeSnapshot, restoreSnapshot } from '@makerdao/test-helpers'; + +let maker, migration, snapshotData; + +describe('Redeem collateral', () => { + beforeAll(async () => { + jest.setTimeout(30000); + + maker = await migrationMaker(); + snapshotData = await takeSnapshot(maker); + const service = maker.service(ServiceRoles.MIGRATION); + migration = service.getMigration(Migrations.REDEEM_COLLATERAL); + await shutDown(); + await migration._contract('SAI_TOP').setCooldown(0); + }); + + afterAll(async () => { + await restoreSnapshot(snapshotData, maker); + }); + + test('should get the remaining cooldown', async () => { + const cooldown = await migration.cooldown(); + expect(cooldown.toNumber()).toBe(0); + }); + + test('should get the total peth in tap', async () => { + expect(await migration.pethInTap()).toBe(0.535); + }); + + test('should redeem collateral', async () => { + const cdp = await maker.service('cdp').getCdp(1); + const peth = maker.getToken('PETH'); + const address = maker.service('web3').currentAddress(); + const collateral = await cdp.getCollateralValue(); + await migration.redeemCollateral(cdp, collateral); + const pethBalance = await peth.balanceOf(address); + expect(pethBalance.toNumber()).toBe(collateral.toNumber()); + }); +}); diff --git a/packages/dai-plugin-migrations/test/migrations/RedeemSai.spec.js b/packages/dai-plugin-migrations/test/migrations/RedeemSai.spec.js new file mode 100644 index 000000000..9fe24b63a --- /dev/null +++ b/packages/dai-plugin-migrations/test/migrations/RedeemSai.spec.js @@ -0,0 +1,57 @@ +import { migrationMaker, shutDown } from '../helpers'; +import { ServiceRoles, Migrations } from '../../src/constants'; +import { takeSnapshot, restoreSnapshot } from '@makerdao/test-helpers'; +import { ETH } from '@makerdao/dai'; + +let maker, migration, snapshotData; + +describe('Redeem Sai', () => { + beforeAll(async () => { + jest.setTimeout(30000); + + maker = await migrationMaker(); + snapshotData = await takeSnapshot(maker); + const service = maker.service(ServiceRoles.MIGRATION); + migration = service.getMigration(Migrations.REDEEM_SAI); + await shutDown(); + }); + + afterAll(async () => { + await restoreSnapshot(snapshotData, maker); + }); + + test('should be off after shutdown', async () => { + const off = await migration.off(); + expect(off).toBe(true); + }); + + test('should get the exchange rate', async () => { + const rate = await migration.getRate(); + expect(rate).toBe(0.0025); + }); + + test('should redeem sai', async () => { + const sai = maker.getToken('SAI'); + const web3Service = maker.service('web3'); + const address = web3Service.currentAddress(); + const cageFree = maker.service('smartContract').getContract('SAI_CAGEFREE') + .address; + await sai.approveUnlimited(cageFree); + const saiBalanceBeforeRedemption = await sai.balanceOf(address); + const ethBalanceBeforeRedemption = ETH.wei( + await web3Service.getBalance(address) + ); + await migration.redeemSai(5); + const saiBalanceAfterRedemption = await sai.balanceOf(address); + const ethBalanceAfterRedemption = ETH.wei( + await web3Service.getBalance(address) + ); + + expect(saiBalanceAfterRedemption).toEqual( + saiBalanceBeforeRedemption.minus(5) + ); + expect(ethBalanceAfterRedemption.toNumber()).toBeGreaterThan( + ethBalanceBeforeRedemption.toNumber() + ); + }); +}); diff --git a/packages/dai-plugin-migrations/test/migrations/SingleToMultiCdp.spec.js b/packages/dai-plugin-migrations/test/migrations/SingleToMultiCdp.spec.js index 7ee66e6f1..828265549 100644 --- a/packages/dai-plugin-migrations/test/migrations/SingleToMultiCdp.spec.js +++ b/packages/dai-plugin-migrations/test/migrations/SingleToMultiCdp.spec.js @@ -26,59 +26,60 @@ async function openLockAndDrawScdCdp(drawAmount) { await cdp.give(proxy); return cdp; } +beforeAll(async () => { + maker = await migrationMaker(); + migration = maker + .service(ServiceRoles.MIGRATION) + .getMigration(Migrations.SINGLE_TO_MULTI_CDP); +}); -describe('SCD to MCD CDP Migration', () => { - beforeEach(async () => { - maker = await migrationMaker(); - const service = maker.service(ServiceRoles.MIGRATION); - migration = service.getMigration(Migrations.SINGLE_TO_MULTI_CDP); +describe('checks', () => { + test('if there are no cdps, return false', async () => { + await mockCdpIds(maker); + + expect(await migration.check()).toMatchObject({}); }); - describe('checks', () => { - beforeEach(async () => { - snapshotData = await takeSnapshot(maker); + test('if there are cdps owned by a proxy, but no cdps owned by the account, return true', async () => { + await mockCdpIds(maker, { forProxy: [{ id: '123' }] }); + expect(await migration.check()).toMatchObject({ + [await maker.currentProxy()]: [{ id: '123' }], + [maker.currentAddress()]: [] }); + }); - afterEach(async () => { - await restoreSnapshot(snapshotData, maker); + test('if there are cdps owned by the account, but no cdps owned by a proxy, return true', async () => { + await mockCdpIds(maker, { forAccount: [{ id: '123' }] }); + expect(await migration.check()).toMatchObject({ + [await maker.currentProxy()]: [], + [maker.currentAddress()]: [{ id: '123' }] }); + }); - test('if there are no cdps, return false', async () => { - await mockCdpIds(maker); - - expect(await migration.check()).toMatchObject({}); + test('if there are both cdps owned by the account and proxy, return true', async () => { + await mockCdpIds(maker, { + forAccount: [{ id: '123' }], + forProxy: [{ id: '234' }] }); - - test('if there are cdps owned by a proxy, but no cdps owned by the account, return true', async () => { - await mockCdpIds(maker, { forProxy: [{ id: '123' }] }); - expect(await migration.check()).toMatchObject({ - [await maker.currentProxy()]: [{ id: '123' }], - [maker.currentAddress()]: [] - }); + expect(await migration.check()).toMatchObject({ + [await maker.currentProxy()]: [{ id: '234' }], + [maker.currentAddress()]: [{ id: '123' }] }); + }); - test('if there are cdps owned by the account, but no cdps owned by a proxy, return true', async () => { - await mockCdpIds(maker, { forAccount: [{ id: '123' }] }); - expect(await migration.check()).toMatchObject({ - [await maker.currentProxy()]: [], - [maker.currentAddress()]: [{ id: '123' }] - }); - }); + test('if there is no sai locked in the mcd migration cdp, return 0', async () => { + const saiLiquidity = await migration.migrationSaiAvailable(); + expect(saiLiquidity.toFixed('wei')).toBe('0'); + }); - test('if there are both cdps owned by the account and proxy, return true', async () => { - await mockCdpIds(maker, { - forAccount: [{ id: '123' }], - forProxy: [{ id: '234' }] - }); - expect(await migration.check()).toMatchObject({ - [await maker.currentProxy()]: [{ id: '234' }], - [maker.currentAddress()]: [{ id: '123' }] - }); + describe('with sai drawn', () => { + beforeEach(async () => { + jest.setTimeout(20000); + snapshotData = await takeSnapshot(maker); }); - test('if there is no sai locked in the mcd migration cdp, return 0', async () => { - const saiLiquidity = await migration.migrationSaiAvailable(); - expect(saiLiquidity.toFixed('wei')).toBe('0'); + afterEach(async () => { + await restoreSnapshot(snapshotData, maker); }); test('if there is sai locked in the mcd migration cdp, return the amount that is there', async () => { @@ -95,87 +96,92 @@ describe('SCD to MCD CDP Migration', () => { await maker .service('mcd:cdpManager') .openLockAndDraw('ETH-A', ETH(2), DAI(99998)); + const available = await migration.migrationSaiAvailable(); - // 999850480759163986 expect(available.toFixed('wei')).toBe('1999999999999999999'); }); - - test('saiAmountNeededToBuyMkr', async () => { - await placeLimitOrder(migration._manager); - const saiAmount = await migration.saiAmountNeededToBuyMkr(MKR(0.5)); - expect(saiAmount).toEqual(SAI(10)); - }); }); - describe.each(['DEBT', 'GEM'])('pay with %s', payment => { - let cdp, proxyAddress; + test('saiAmountNeededToBuyMkr', async () => { + await placeLimitOrder(migration._manager); + const saiAmount = await migration.saiAmountNeededToBuyMkr(MKR(0.5)); + expect(saiAmount).toEqual(SAI(10)); + }); +}); - beforeEach(async () => { - jest.setTimeout(20000); - snapshotData = await takeSnapshot(maker); - proxyAddress = await maker.service('proxy').currentProxy(); - await openLockAndDrawScdCdp(100); - cdp = await openLockAndDrawScdCdp(10); - await migrateSaiToDai(50, maker); - }); +describe.each(['MKR'])('pay with %s', payment => { + let cdp, proxyAddress; - afterEach(async () => { - await restoreSnapshot(snapshotData, maker); - }); + beforeEach(async () => { + jest.setTimeout(30000); + maker = await migrationMaker(); + migration = maker + .service(ServiceRoles.MIGRATION) + .getMigration(Migrations.SINGLE_TO_MULTI_CDP); + + snapshotData = await takeSnapshot(maker); + proxyAddress = await maker.service('proxy').currentProxy(); + await openLockAndDrawScdCdp(100); + cdp = await openLockAndDrawScdCdp(10); + await migrateSaiToDai(50, maker); + }); - test('execute', async () => { - let maxPayAmount, minRatio; + afterEach(async () => { + await restoreSnapshot(snapshotData, maker); + }); - if (payment !== 'MKR') { - await placeLimitOrder(migration._manager); - maxPayAmount = 10; - } - if (payment === 'DEBT') minRatio = 150; - await maker.service('price').setMkrPrice(100); + test('execute', async () => { + let maxPayAmount, minRatio; - const manager = maker.service('mcd:cdpManager'); - const scdCollateral = await cdp.getCollateralValue(); - const scdDebt = await cdp.getDebtValue(); - await mineBlocks(maker.service('web3'), 3); - await maker - .service('smartContract') - .getContract('MCD_POT') - .drip(); - - const mcdCdpsBeforeMigration = await manager.getCdpIds(proxyAddress); - - const newId = await migration.execute( - cdp.id, - payment, - maxPayAmount, - minRatio - ); - await manager.reset(); - - const mcdCdpsAfterMigration = await manager.getCdpIds(proxyAddress); - const mcdCdpId = mcdCdpsAfterMigration[0].id; - expect(newId).toEqual(mcdCdpId); - - maker.service('mcd:cdpType').reset(); - const mcdCdp = await manager.getCdp(mcdCdpId); - const mcdCollateral = mcdCdp.collateralAmount.toNumber(); - const mcdDebt = mcdCdp.debtValue.toNumber(); - - expect(mcdCollateral).toEqual(scdCollateral.toNumber()); - expect(mcdDebt).toBeCloseTo(scdDebt.toNumber(), 1); - - let message; - try { - await maker.service('cdp').getCdp(cdp.id); - } catch (err) { - message = err.message; - } - - expect(message).toEqual("That CDP doesn't exist--try opening a new one."); - - expect(mcdCdpsAfterMigration.length).toEqual( - mcdCdpsBeforeMigration.length + 1 - ); - }); + if (payment !== 'MKR') { + await placeLimitOrder(migration._manager); + maxPayAmount = 10; + } + if (payment === 'DEBT') minRatio = 150; + await maker.service('price').setMkrPrice(100); + + const manager = maker.service('mcd:cdpManager'); + const scdCollateral = await cdp.getCollateralValue(); + const scdDebt = await cdp.getDebtValue(); + await mineBlocks(maker.service('web3'), 3); + await maker + .service('smartContract') + .getContract('MCD_POT') + .drip(); + + const mcdCdpsBeforeMigration = await manager.getCdpIds(proxyAddress); + + const newId = await migration.execute( + cdp.id, + payment, + maxPayAmount, + minRatio + ); + await manager.reset(); + + const mcdCdpsAfterMigration = await manager.getCdpIds(proxyAddress); + const mcdCdpId = mcdCdpsAfterMigration[0].id; + expect(newId).toEqual(mcdCdpId); + + maker.service('mcd:cdpType').resetAllCdpTypes(); + const mcdCdp = await manager.getCdp(mcdCdpId); + const mcdCollateral = mcdCdp.collateralAmount.toNumber(); + const mcdDebt = mcdCdp.debtValue.toNumber(); + + expect(mcdCollateral).toEqual(scdCollateral.toNumber()); + expect(mcdDebt).toBeCloseTo(scdDebt.toNumber(), 1); + + let message; + try { + await maker.service('cdp').getCdp(cdp.id); + } catch (err) { + message = err.message; + } + + expect(message).toEqual("That CDP doesn't exist--try opening a new one."); + + expect(mcdCdpsAfterMigration.length).toEqual( + mcdCdpsBeforeMigration.length + 1 + ); }); }); From 726c5c0f01bd896bc8e1b784f19bd64249241ddc Mon Sep 17 00:00:00 2001 From: Lawrence Wang Date: Fri, 22 May 2020 17:09:19 -0700 Subject: [PATCH 2/2] dai-plugin-migrations-v1.2.0 --- packages/dai-plugin-migrations/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/dai-plugin-migrations/package.json b/packages/dai-plugin-migrations/package.json index 8c78e4abd..254ba3051 100644 --- a/packages/dai-plugin-migrations/package.json +++ b/packages/dai-plugin-migrations/package.json @@ -1,7 +1,7 @@ { "name": "@makerdao/dai-plugin-migrations", "description": "Plugin to add migrations to dai.js", - "version": "1.1.0", + "version": "1.2.0", "license": "MIT", "main": "dist/index.js", "browser": "umd/index.js",