diff --git a/package-lock.json b/package-lock.json index 5c5dd07b..8479fd20 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,6 +17,7 @@ "chalk": "^5.0.0", "dotenv": "^10.0.0", "hardhat-docgen": "^1.2.0", + "inquirer": "^8.2.0", "minimist": "^1.2.5", "solc": "^0.8.10", "typechain": "^6.0.5" @@ -31,6 +32,7 @@ "@tenderly/hardhat-tenderly": "^1.0.13", "@types/chai": "^4.2.22", "@types/chai-as-promised": "^7.1.4", + "@types/inquirer": "^8.1.3", "@types/mocha": "^9.0.0", "@types/node": "^16.11.11", "chai": "^4.3.4", @@ -4158,6 +4160,31 @@ "@types/node": "*" } }, + "node_modules/@types/inquirer": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@types/inquirer/-/inquirer-8.1.3.tgz", + "integrity": "sha512-AayK4ZL5ssPzR1OtnOLGAwpT0Dda3Xi/h1G0l1oJDNrowp7T1423q4Zb8/emr7tzRlCy4ssEri0LWVexAqHyKQ==", + "dev": true, + "dependencies": { + "@types/through": "*", + "rxjs": "^7.2.0" + } + }, + "node_modules/@types/inquirer/node_modules/rxjs": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.4.0.tgz", + "integrity": "sha512-7SQDi7xeTMCJpqViXh8gL/lebcwlp3d831F05+9B44A4B0WfsEwUQHR64gsH1kvJ+Ep/J9K2+n1hVl1CsGN23w==", + "dev": true, + "dependencies": { + "tslib": "~2.1.0" + } + }, + "node_modules/@types/inquirer/node_modules/tslib": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz", + "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==", + "dev": true + }, "node_modules/@types/level-errors": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@types/level-errors/-/level-errors-3.0.0.tgz", @@ -4283,6 +4310,15 @@ "@types/sinon": "*" } }, + "node_modules/@types/through": { + "version": "0.0.30", + "resolved": "https://registry.npmjs.org/@types/through/-/through-0.0.30.tgz", + "integrity": "sha512-FvnCJljyxhPM3gkRgWmxmDZyAQSiBQQWLI0A0VFL0K7W1oRUrPJSqNO0NvTnLkBcotdlp3lKvaT0JrnyRDkzOg==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/underscore": { "version": "1.11.2", "resolved": "https://registry.npmjs.org/@types/underscore/-/underscore-1.11.2.tgz", @@ -5230,6 +5266,29 @@ "file-uri-to-path": "1.0.0" } }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bl/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/blakejs": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/blakejs/-/blakejs-1.1.0.tgz", @@ -5762,6 +5821,11 @@ "upper-case-first": "^1.1.0" } }, + "node_modules/chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==" + }, "node_modules/check-error": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", @@ -6013,6 +6077,36 @@ "node": ">= 4.0" } }, + "node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dependencies": { + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-spinners": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.1.tgz", + "integrity": "sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-width": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", + "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", + "engines": { + "node": ">= 10" + } + }, "node_modules/cliui": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", @@ -6055,6 +6149,14 @@ "node": ">=6" } }, + "node_modules/clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", + "engines": { + "node": ">=0.8" + } + }, "node_modules/clone-response": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", @@ -6649,6 +6751,14 @@ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, + "node_modules/defaults": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", + "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", + "dependencies": { + "clone": "^1.0.2" + } + }, "node_modules/defer-to-connect": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", @@ -8466,6 +8576,19 @@ "node": ">=0.10.0" } }, + "node_modules/external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dependencies": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/extglob": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", @@ -8604,6 +8727,20 @@ "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz", "integrity": "sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==" }, + "node_modules/figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/file-uri-to-path": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", @@ -21803,6 +21940,152 @@ "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", "dev": true }, + "node_modules/inquirer": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.0.tgz", + "integrity": "sha512-0crLweprevJ02tTuA6ThpoAERAGyVILC4sS74uib58Xf/zSr1/ZWtmm7D5CI+bSQEaA04f0K7idaHpQbSWgiVQ==", + "dependencies": { + "ansi-escapes": "^4.2.1", + "chalk": "^4.1.1", + "cli-cursor": "^3.1.0", + "cli-width": "^3.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.21", + "mute-stream": "0.0.8", + "ora": "^5.4.1", + "run-async": "^2.4.0", + "rxjs": "^7.2.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "through": "^2.3.6" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/inquirer/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/inquirer/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/inquirer/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/inquirer/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/inquirer/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/inquirer/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/inquirer/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/inquirer/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/inquirer/node_modules/rxjs": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.4.0.tgz", + "integrity": "sha512-7SQDi7xeTMCJpqViXh8gL/lebcwlp3d831F05+9B44A4B0WfsEwUQHR64gsH1kvJ+Ep/J9K2+n1hVl1CsGN23w==", + "dependencies": { + "tslib": "~2.1.0" + } + }, + "node_modules/inquirer/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/inquirer/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/inquirer/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/inquirer/node_modules/tslib": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz", + "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==" + }, "node_modules/internal-slot": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", @@ -22090,6 +22373,14 @@ "npm": ">=3" } }, + "node_modules/is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "engines": { + "node": ">=8" + } + }, "node_modules/is-lower-case": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/is-lower-case/-/is-lower-case-1.1.3.tgz", @@ -22252,6 +22543,17 @@ "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", "dev": true }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-upper-case": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/is-upper-case/-/is-upper-case-1.1.2.tgz", @@ -23673,6 +23975,11 @@ "imul": "^1.0.0" } }, + "node_modules/mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" + }, "node_modules/nan": { "version": "2.13.2", "resolved": "https://registry.npmjs.org/nan/-/nan-2.13.2.tgz", @@ -24247,6 +24554,28 @@ "wrappy": "1" } }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/onetime/node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "engines": { + "node": ">=6" + } + }, "node_modules/open": { "version": "7.4.2", "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", @@ -24292,6 +24621,126 @@ "node": ">= 0.8.0" } }, + "node_modules/ora": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "dependencies": { + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/ora/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/ora/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/ora/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/ora/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/ora/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/ora/node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ora/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/os-browserify": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", @@ -25519,6 +25968,18 @@ "lowercase-keys": "^1.0.0" } }, + "node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/ret": { "version": "0.1.15", "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", @@ -25589,6 +26050,14 @@ "rlp": "bin/rlp" } }, + "node_modules/run-async": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", + "engines": { + "node": ">=0.12.0" + } + }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -25992,8 +26461,7 @@ "node_modules/signal-exit": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", - "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", - "dev": true + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==" }, "node_modules/simple-concat": { "version": "1.0.1", @@ -26966,19 +27434,6 @@ "tar-stream": "^2.1.4" } }, - "node_modules/tar-fs/node_modules/bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", - "dev": true, - "optional": true, - "peer": true, - "dependencies": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, "node_modules/tar-fs/node_modules/readable-stream": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", @@ -27086,6 +27541,11 @@ "deprecated": "testrpc has been renamed to ganache-cli, please use this package from now on.", "dev": true }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" + }, "node_modules/through2": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", @@ -28221,6 +28681,14 @@ "node": ">=0.10.0" } }, + "node_modules/wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", + "dependencies": { + "defaults": "^1.0.3" + } + }, "node_modules/web3": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/web3/-/web3-1.6.1.tgz", @@ -33074,6 +33542,33 @@ "@types/node": "*" } }, + "@types/inquirer": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/@types/inquirer/-/inquirer-8.1.3.tgz", + "integrity": "sha512-AayK4ZL5ssPzR1OtnOLGAwpT0Dda3Xi/h1G0l1oJDNrowp7T1423q4Zb8/emr7tzRlCy4ssEri0LWVexAqHyKQ==", + "dev": true, + "requires": { + "@types/through": "*", + "rxjs": "^7.2.0" + }, + "dependencies": { + "rxjs": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.4.0.tgz", + "integrity": "sha512-7SQDi7xeTMCJpqViXh8gL/lebcwlp3d831F05+9B44A4B0WfsEwUQHR64gsH1kvJ+Ep/J9K2+n1hVl1CsGN23w==", + "dev": true, + "requires": { + "tslib": "~2.1.0" + } + }, + "tslib": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz", + "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==", + "dev": true + } + } + }, "@types/level-errors": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@types/level-errors/-/level-errors-3.0.0.tgz", @@ -33198,6 +33693,15 @@ "@types/sinon": "*" } }, + "@types/through": { + "version": "0.0.30", + "resolved": "https://registry.npmjs.org/@types/through/-/through-0.0.30.tgz", + "integrity": "sha512-FvnCJljyxhPM3gkRgWmxmDZyAQSiBQQWLI0A0VFL0K7W1oRUrPJSqNO0NvTnLkBcotdlp3lKvaT0JrnyRDkzOg==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, "@types/underscore": { "version": "1.11.2", "resolved": "https://registry.npmjs.org/@types/underscore/-/underscore-1.11.2.tgz", @@ -33990,6 +34494,28 @@ "file-uri-to-path": "1.0.0" } }, + "bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, "blakejs": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/blakejs/-/blakejs-1.1.0.tgz", @@ -34451,6 +34977,11 @@ "upper-case-first": "^1.1.0" } }, + "chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==" + }, "check-error": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", @@ -34656,6 +35187,24 @@ "source-map": "~0.6.0" } }, + "cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "requires": { + "restore-cursor": "^3.1.0" + } + }, + "cli-spinners": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.1.tgz", + "integrity": "sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==" + }, + "cli-width": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", + "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==" + }, "cliui": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", @@ -34691,6 +35240,11 @@ } } }, + "clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=" + }, "clone-response": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", @@ -35170,6 +35724,14 @@ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, + "defaults": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", + "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", + "requires": { + "clone": "^1.0.2" + } + }, "defer-to-connect": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", @@ -36679,6 +37241,16 @@ "is-extendable": "^1.0.1" } }, + "external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "requires": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + } + }, "extglob": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", @@ -36793,6 +37365,14 @@ "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz", "integrity": "sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==" }, + "figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, "file-uri-to-path": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", @@ -47139,6 +47719,118 @@ "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", "dev": true }, + "inquirer": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.0.tgz", + "integrity": "sha512-0crLweprevJ02tTuA6ThpoAERAGyVILC4sS74uib58Xf/zSr1/ZWtmm7D5CI+bSQEaA04f0K7idaHpQbSWgiVQ==", + "requires": { + "ansi-escapes": "^4.2.1", + "chalk": "^4.1.1", + "cli-cursor": "^3.1.0", + "cli-width": "^3.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.21", + "mute-stream": "0.0.8", + "ora": "^5.4.1", + "run-async": "^2.4.0", + "rxjs": "^7.2.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "through": "^2.3.6" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + }, + "rxjs": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.4.0.tgz", + "integrity": "sha512-7SQDi7xeTMCJpqViXh8gL/lebcwlp3d831F05+9B44A4B0WfsEwUQHR64gsH1kvJ+Ep/J9K2+n1hVl1CsGN23w==", + "requires": { + "tslib": "~2.1.0" + } + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + }, + "tslib": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz", + "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==" + } + } + }, "internal-slot": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz", @@ -47324,6 +48016,11 @@ "resolved": "https://registry.npmjs.org/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz", "integrity": "sha1-fY035q135dEnFIkTxXPggtd39VQ=" }, + "is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==" + }, "is-lower-case": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/is-lower-case/-/is-lower-case-1.1.3.tgz", @@ -47429,6 +48126,11 @@ "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", "dev": true }, + "is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==" + }, "is-upper-case": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/is-upper-case/-/is-upper-case-1.1.2.tgz", @@ -48606,6 +49308,11 @@ "imul": "^1.0.0" } }, + "mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" + }, "nan": { "version": "2.13.2", "resolved": "https://registry.npmjs.org/nan/-/nan-2.13.2.tgz", @@ -49090,6 +49797,21 @@ "wrappy": "1" } }, + "onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "requires": { + "mimic-fn": "^2.1.0" + }, + "dependencies": { + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" + } + } + }, "open": { "version": "7.4.2", "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", @@ -49125,6 +49847,89 @@ "word-wrap": "~1.2.3" } }, + "ora": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "requires": { + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "requires": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, "os-browserify": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", @@ -50089,6 +50894,15 @@ "lowercase-keys": "^1.0.0" } }, + "restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "requires": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + } + }, "ret": { "version": "0.1.15", "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", @@ -50140,6 +50954,11 @@ "bn.js": "^4.11.1" } }, + "run-async": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==" + }, "run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -50458,8 +51277,7 @@ "signal-exit": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", - "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", - "dev": true + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==" }, "simple-concat": { "version": "1.0.1", @@ -51268,19 +52086,6 @@ "tar-stream": "^2.1.4" }, "dependencies": { - "bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", - "dev": true, - "optional": true, - "peer": true, - "requires": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, "readable-stream": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", @@ -51369,6 +52174,11 @@ "integrity": "sha512-afH1hO+SQ/VPlmaLUFj2636QMeDvPCeQMc/9RBMW0IfjNe9gFD9Ra3ShqYkB7py0do1ZcCna/9acHyzTJ+GcNA==", "dev": true }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" + }, "through2": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", @@ -52286,6 +53096,14 @@ } } }, + "wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", + "requires": { + "defaults": "^1.0.3" + } + }, "web3": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/web3/-/web3-1.6.1.tgz", diff --git a/package.json b/package.json index 6c3139d9..6dfdd041 100644 --- a/package.json +++ b/package.json @@ -4,11 +4,12 @@ "description": "", "directories": {}, "scripts": { - "test": "hardhat test", + "test": "hardhat run scripts/tests/global-test.ts", "coverage": "./node_modules/.bin/solidity-coverage", "check": "node status-checks/huskyCheck.js", "check-husky": "node status-checks/huskyCheck.js", - "deploy": "node scripts/deployConnectorsFromCmd.js" + "deploy": "node scripts/deployConnectorsFromCmd.js", + "test:runner": "hardhat run scripts/tests/run-tests.ts" }, "repository": { "type": "git", @@ -29,6 +30,7 @@ "chalk": "^5.0.0", "dotenv": "^10.0.0", "hardhat-docgen": "^1.2.0", + "inquirer": "^8.2.0", "minimist": "^1.2.5", "solc": "^0.8.10", "typechain": "^6.0.5" @@ -43,6 +45,7 @@ "@tenderly/hardhat-tenderly": "^1.0.13", "@types/chai": "^4.2.22", "@types/chai-as-promised": "^7.1.4", + "@types/inquirer": "^8.1.3", "@types/mocha": "^9.0.0", "@types/node": "^16.11.11", "chai": "^4.3.4", diff --git a/scripts/tests/command.ts b/scripts/tests/command.ts new file mode 100644 index 00000000..51a07234 --- /dev/null +++ b/scripts/tests/command.ts @@ -0,0 +1,33 @@ +import { execFile, spawn } from "child_process"; + +interface ICommand { + readonly cmd: string; + readonly args: string[]; + readonly env: { + [param: string]: string; + }; +} + +export async function execScript(input: ICommand): Promise { + return new Promise((resolve, reject) => { + let cmdEnv = Object.create(process.env); + for (let param in input.env) { + cmdEnv[param] = input.env[param]; + } + + const proc = spawn(input.cmd, [...input.args], { + env: cmdEnv, + shell: true, + stdio: "inherit", + }); + + proc.on("exit", (code) => { + if (code !== 0) { + reject(code); + return; + } + + resolve(code); + }); + }); +} diff --git a/scripts/tests/encodeFlashcastData.ts b/scripts/tests/encodeFlashcastData.ts index 934b58e6..8e4b9d9f 100644 --- a/scripts/tests/encodeFlashcastData.ts +++ b/scripts/tests/encodeFlashcastData.ts @@ -1,7 +1,7 @@ import hre from "hardhat"; const { web3 } = hre; -import { encodeSpells } from "./encodeSpells.js"; +import { encodeSpells } from "./encodeSpells"; export default function encodeFlashcastData(spells: any) { const encodeSpellsData = encodeSpells(spells); diff --git a/scripts/tests/global-test.ts b/scripts/tests/global-test.ts new file mode 100644 index 00000000..7a00510f --- /dev/null +++ b/scripts/tests/global-test.ts @@ -0,0 +1,44 @@ +import { promises as fs } from "fs"; + +import { join } from "path"; +import { execScript } from "./command"; + +let start: number, end: number; + +async function testRunner() { + const chain = ["avalanche", "mainnet", "polygon"]; + start = Date.now(); + + for (let ch of chain) { + console.log(`πŸ“—Running test for %c${ch}: `, "blue"); + let path: string; + const testsPath = join(__dirname, "../../test", ch); + await fs.access(testsPath); + const availableTests = await fs.readdir(testsPath); + + if (availableTests.length !== 0) { + for (let test of availableTests) { + path = join(testsPath, test); + path += "/*"; + await execScript({ + cmd: "npx", + args: ["hardhat", "test", path], + env: { + networkType: ch, + }, + }); + } + } + } + + end = Date.now(); +} + +testRunner() + .then(() => + console.log( + `πŸ™Œ finished running the test, total time taken ${(end - start) / + 1000} sec` + ) + ) + .catch((err) => console.error("❌ failed due to error: ", err)); diff --git a/scripts/tests/run-tests.ts b/scripts/tests/run-tests.ts new file mode 100644 index 00000000..de48de95 --- /dev/null +++ b/scripts/tests/run-tests.ts @@ -0,0 +1,58 @@ +import inquirer from "inquirer"; +import { promises as fs } from "fs"; + +import { join } from "path"; +import { execScript } from "./command"; + +let start: number, end: number; + +async function testRunner() { + const { chain } = await inquirer.prompt([ + { + name: "chain", + message: "What chain do you want to run tests on?", + type: "list", + choices: ["mainnet", "polygon", "avalanche", "arbitrum"], + }, + ]); + const testsPath = join(__dirname, "../../test", chain); + await fs.access(testsPath); + const availableTests = await fs.readdir(testsPath); + if (availableTests.length === 0) { + throw new Error(`No tests available for ${chain}`); + } + + const { testName } = await inquirer.prompt([ + { + name: "testName", + message: "For which resolver you want to run the tests?", + type: "list", + choices: ["all", ...availableTests], + }, + ]); + start = Date.now(); + let path: string; + if (testName === "all") { + path = availableTests.map((file) => join(testsPath, file)).join(" "); + } else { + path = join(testsPath, testName); + } + path += "/*"; + + await execScript({ + cmd: "npx", + args: ["hardhat", "test", path], + env: { + networkType: chain, + }, + }); + end = Date.now(); +} + +testRunner() + .then(() => + console.log( + `πŸ™Œ finished the test runner, time taken ${(end - start) / 1000} sec` + ) + ) + .catch((err) => console.error("❌ failed due to error: ", err)); diff --git a/test/mainnet/uniswap-sell-beta/uniswap-sell-beta.ts b/test/arbitrum/uniswap-sell-beta/uniswap-sell-beta.ts similarity index 96% rename from test/mainnet/uniswap-sell-beta/uniswap-sell-beta.ts rename to test/arbitrum/uniswap-sell-beta/uniswap-sell-beta.ts index 73b9df8b..dc3ad518 100644 --- a/test/mainnet/uniswap-sell-beta/uniswap-sell-beta.ts +++ b/test/arbitrum/uniswap-sell-beta/uniswap-sell-beta.ts @@ -51,8 +51,8 @@ describe("Uniswap-sell-beta", function () { } beforeEach(async () => { - const account0 = "0x36cc7B13029B5DEe4034745FB4F24034f3F2ffc6"; - const account1 = "0xce2cc46682e9c6d5f174af598fb4931a9c0be68e"; + const account0 = "0xa067668661c84476afcdc6fa5d758c4c01c34352"; + const account1 = "0x0db3fe3b770c95a0b99d1ed6f2627933466c0dd8"; const [owner, add1, add2] = await ethers.getSigners(); await impersonate(owner.address, account1, USDC_ADDR, 6); diff --git a/test/mainnet/b.protocol/b.compound.test.ts b/test/mainnet/b.protocol/b.compound.test.ts index fbda13f9..4ef6c0ba 100644 --- a/test/mainnet/b.protocol/b.compound.test.ts +++ b/test/mainnet/b.protocol/b.compound.test.ts @@ -10,7 +10,7 @@ import { getMasterSigner } from "../../../scripts/tests/getMasterSigner" import { addresses } from "../../../scripts/constant/addresses"; import { abis } from "../../../scripts/constant/abis"; import { constants } from "../../../scripts/constant/constant"; -import { ConnectV2Compound__factory } from "../../../typechain"; +import { ConnectV2BCompound__factory } from "../../../typechain"; import type { Signer, Contract } from "ethers"; describe("B.Compound", function () { @@ -19,7 +19,7 @@ describe("B.Compound", function () { let dsaWallet0: any; let masterSigner: Signer; let instaConnectorsV2: Contract; - let connector: any; + let connector: Contract; const wallets = provider.getWallets() const [wallet0, wallet1, wallet2, wallet3] = wallets @@ -40,7 +40,7 @@ describe("B.Compound", function () { instaConnectorsV2 = await ethers.getContractAt(abis.core.connectorsV2, addresses.core.connectorsV2); connector = await deployAndEnableConnector({ connectorName, - contractArtifact: ConnectV2Compound__factory, + contractArtifact: ConnectV2BCompound__factory, signer: masterSigner, connectors: instaConnectorsV2 }) diff --git a/test/mainnet/basic-ERC1155/ERC1155-transfer.ts b/test/mainnet/basic-ERC1155/ERC1155-transfer.ts index 5c85581a..88fc918b 100644 --- a/test/mainnet/basic-ERC1155/ERC1155-transfer.ts +++ b/test/mainnet/basic-ERC1155/ERC1155-transfer.ts @@ -56,9 +56,8 @@ describe("BASIC-ERC1155", function () { await hre.network.provider.send("hardhat_setBalance", [ TOKEN_OWNER_ADDR, - "0x1000000000000000", + "0x10000000000000000", ]); - // get tokenOwner tokenOwner = await ethers.getSigner( TOKEN_OWNER_ADDR diff --git a/test/mainnet/basic-ERC721/ERC721-transfer.ts b/test/mainnet/basic-ERC721/ERC721-transfer.ts index db4acb9e..2fb3c24d 100644 --- a/test/mainnet/basic-ERC721/ERC721-transfer.ts +++ b/test/mainnet/basic-ERC721/ERC721-transfer.ts @@ -55,7 +55,7 @@ describe("BASIC-ERC721", function () { await network.provider.send("hardhat_setBalance", [ TOKEN_OWNER_ADDR, - "0x1000000000000000", + "0x10000000000000000", ]); // get tokenOwner diff --git a/test/mainnet/liquity/liquity.contracts.ts b/test/mainnet/liquity/liquity.contracts.ts index f6a6df74..44fa6534 100644 --- a/test/mainnet/liquity/liquity.contracts.ts +++ b/test/mainnet/liquity/liquity.contracts.ts @@ -1,95 +1,95 @@ -const TROVE_MANAGER_ADDRESS = "0xA39739EF8b0231DbFA0DcdA07d7e29faAbCf4bb2"; -const TROVE_MANAGER_ABI = [ - "function getTroveColl(address _borrower) external view returns (uint)", - "function getTroveDebt(address _borrower) external view returns (uint)", - "function getTroveStatus(address _borrower) external view returns (uint)", - "function redeemCollateral(uint _LUSDAmount, address _firstRedemptionHint, address _upperPartialRedemptionHint, address _lowerPartialRedemptionHint, uint _partialRedemptionHintNICR, uint _maxIterations, uint _maxFee) external returns (uint)", - "function getNominalICR(address _borrower) external view returns (uint)", - "function liquidate(address _borrower) external", - "function liquidateTroves(uint _n) external", -]; +// const TROVE_MANAGER_ADDRESS = "0xA39739EF8b0231DbFA0DcdA07d7e29faAbCf4bb2"; +// const TROVE_MANAGER_ABI = [ +// "function getTroveColl(address _borrower) external view returns (uint)", +// "function getTroveDebt(address _borrower) external view returns (uint)", +// "function getTroveStatus(address _borrower) external view returns (uint)", +// "function redeemCollateral(uint _LUSDAmount, address _firstRedemptionHint, address _upperPartialRedemptionHint, address _lowerPartialRedemptionHint, uint _partialRedemptionHintNICR, uint _maxIterations, uint _maxFee) external returns (uint)", +// "function getNominalICR(address _borrower) external view returns (uint)", +// "function liquidate(address _borrower) external", +// "function liquidateTroves(uint _n) external", +// ]; -const BORROWER_OPERATIONS_ADDRESS = - "0x24179CD81c9e782A4096035f7eC97fB8B783e007"; -const BORROWER_OPERATIONS_ABI = [ - "function openTrove(uint256 _maxFee, uint256 _LUSDAmount, address _upperHint, address _lowerHint) external payable", - "function closeTrove() external", -]; +// const BORROWER_OPERATIONS_ADDRESS = +// "0x24179CD81c9e782A4096035f7eC97fB8B783e007"; +// const BORROWER_OPERATIONS_ABI = [ +// "function openTrove(uint256 _maxFee, uint256 _LUSDAmount, address _upperHint, address _lowerHint) external payable", +// "function closeTrove() external", +// ]; -const LUSD_TOKEN_ADDRESS = "0x5f98805A4E8be255a32880FDeC7F6728C6568bA0"; -const LUSD_TOKEN_ABI = [ - "function transfer(address _to, uint256 _value) public returns (bool success)", - "function balanceOf(address account) external view returns (uint256)", - "function approve(address spender, uint256 amount) external returns (bool)", -]; +// const LUSD_TOKEN_ADDRESS = "0x5f98805A4E8be255a32880FDeC7F6728C6568bA0"; +// const LUSD_TOKEN_ABI = [ +// "function transfer(address _to, uint256 _value) public returns (bool success)", +// "function balanceOf(address account) external view returns (uint256)", +// "function approve(address spender, uint256 amount) external returns (bool)", +// ]; -const ACTIVE_POOL_ADDRESS = "0xDf9Eb223bAFBE5c5271415C75aeCD68C21fE3D7F"; -const ACTIVE_POOL_ABI = ["function getLUSDDebt() external view returns (uint)"]; +// const ACTIVE_POOL_ADDRESS = "0xDf9Eb223bAFBE5c5271415C75aeCD68C21fE3D7F"; +// const ACTIVE_POOL_ABI = ["function getLUSDDebt() external view returns (uint)"]; -const PRICE_FEED_ADDRESS = "0x4c517D4e2C851CA76d7eC94B805269Df0f2201De"; -const PRICE_FEED_ABI = ["function fetchPrice() external returns (uint)"]; +// const PRICE_FEED_ADDRESS = "0x4c517D4e2C851CA76d7eC94B805269Df0f2201De"; +// const PRICE_FEED_ABI = ["function fetchPrice() external returns (uint)"]; -const HINT_HELPERS_ADDRESS = "0xE84251b93D9524E0d2e621Ba7dc7cb3579F997C0"; -const HINT_HELPERS_ABI = [ - "function getRedemptionHints(uint _LUSDamount, uint _price, uint _maxIterations) external view returns (address firstRedemptionHint, uint partialRedemptionHintNICR, uint truncatedLUSDamount)", - "function getApproxHint(uint _CR, uint _numTrials, uint _inputRandomSeed) view returns (address hintAddress, uint diff, uint latestRandomSeed)", - "function computeNominalCR(uint _coll, uint _debt) external pure returns (uint)", -]; +// const HINT_HELPERS_ADDRESS = "0xE84251b93D9524E0d2e621Ba7dc7cb3579F997C0"; +// const HINT_HELPERS_ABI = [ +// "function getRedemptionHints(uint _LUSDamount, uint _price, uint _maxIterations) external view returns (address firstRedemptionHint, uint partialRedemptionHintNICR, uint truncatedLUSDamount)", +// "function getApproxHint(uint _CR, uint _numTrials, uint _inputRandomSeed) view returns (address hintAddress, uint diff, uint latestRandomSeed)", +// "function computeNominalCR(uint _coll, uint _debt) external pure returns (uint)", +// ]; -const SORTED_TROVES_ADDRESS = "0x8FdD3fbFEb32b28fb73555518f8b361bCeA741A6"; -const SORTED_TROVES_ABI = [ - "function findInsertPosition(uint256 _ICR, address _prevId, address _nextId) external view returns (address, address)", - "function getLast() external view returns (address)", -]; +// const SORTED_TROVES_ADDRESS = "0x8FdD3fbFEb32b28fb73555518f8b361bCeA741A6"; +// const SORTED_TROVES_ABI = [ +// "function findInsertPosition(uint256 _ICR, address _prevId, address _nextId) external view returns (address, address)", +// "function getLast() external view returns (address)", +// ]; -const STABILITY_POOL_ADDRESS = "0x66017D22b0f8556afDd19FC67041899Eb65a21bb"; -const STABILITY_POOL_ABI = [ - "function getCompoundedLUSDDeposit(address _depositor) external view returns (uint)", - "function getDepositorETHGain(address _depositor) external view returns (uint)", - "function getDepositorLQTYGain(address _depositor) external view returns (uint)", -]; +// const STABILITY_POOL_ADDRESS = "0x66017D22b0f8556afDd19FC67041899Eb65a21bb"; +// const STABILITY_POOL_ABI = [ +// "function getCompoundedLUSDDeposit(address _depositor) external view returns (uint)", +// "function getDepositorETHGain(address _depositor) external view returns (uint)", +// "function getDepositorLQTYGain(address _depositor) external view returns (uint)", +// ]; -const STAKING_ADDRESS = "0x4f9Fbb3f1E99B56e0Fe2892e623Ed36A76Fc605d"; -const STAKING_ABI = [ - "function stake(uint _LQTYamount) external", - "function unstake(uint _LQTYamount) external", - "function getPendingETHGain(address _user) external view returns (uint)", - "function getPendingLUSDGain(address _user) external view returns (uint)", -]; +// const STAKING_ADDRESS = "0x4f9Fbb3f1E99B56e0Fe2892e623Ed36A76Fc605d"; +// const STAKING_ABI = [ +// "function stake(uint _LQTYamount) external", +// "function unstake(uint _LQTYamount) external", +// "function getPendingETHGain(address _user) external view returns (uint)", +// "function getPendingLUSDGain(address _user) external view returns (uint)", +// ]; -const LQTY_TOKEN_ADDRESS = "0x6DEA81C8171D0bA574754EF6F8b412F2Ed88c54D"; -const LQTY_TOKEN_ABI = [ - "function balanceOf(address account) external view returns (uint256)", - "function transfer(address _to, uint256 _value) public returns (bool success)", - "function approve(address spender, uint256 amount) external returns (bool)", -]; +// const LQTY_TOKEN_ADDRESS = "0x6DEA81C8171D0bA574754EF6F8b412F2Ed88c54D"; +// const LQTY_TOKEN_ABI = [ +// "function balanceOf(address account) external view returns (uint256)", +// "function transfer(address _to, uint256 _value) public returns (bool success)", +// "function approve(address spender, uint256 amount) external returns (bool)", +// ]; -const COLL_SURPLUS_ADDRESS = "0x3D32e8b97Ed5881324241Cf03b2DA5E2EBcE5521"; -const COLL_SURPLUS_ABI = [ - "function getCollateral(address _account) external view returns (uint)", -]; +// const COLL_SURPLUS_ADDRESS = "0x3D32e8b97Ed5881324241Cf03b2DA5E2EBcE5521"; +// const COLL_SURPLUS_ABI = [ +// "function getCollateral(address _account) external view returns (uint)", +// ]; -module.exports = { - TROVE_MANAGER_ADDRESS, - TROVE_MANAGER_ABI, - BORROWER_OPERATIONS_ADDRESS, - BORROWER_OPERATIONS_ABI, - LUSD_TOKEN_ADDRESS, - LUSD_TOKEN_ABI, - STABILITY_POOL_ADDRESS, - STABILITY_POOL_ABI, - ACTIVE_POOL_ADDRESS, - ACTIVE_POOL_ABI, - PRICE_FEED_ADDRESS, - PRICE_FEED_ABI, - HINT_HELPERS_ADDRESS, - HINT_HELPERS_ABI, - SORTED_TROVES_ADDRESS, - SORTED_TROVES_ABI, - STAKING_ADDRESS, - STAKING_ABI, - LQTY_TOKEN_ADDRESS, - LQTY_TOKEN_ABI, - COLL_SURPLUS_ADDRESS, - COLL_SURPLUS_ABI, -}; +// module.exports = { +// TROVE_MANAGER_ADDRESS, +// TROVE_MANAGER_ABI, +// BORROWER_OPERATIONS_ADDRESS, +// BORROWER_OPERATIONS_ABI, +// LUSD_TOKEN_ADDRESS, +// LUSD_TOKEN_ABI, +// STABILITY_POOL_ADDRESS, +// STABILITY_POOL_ABI, +// ACTIVE_POOL_ADDRESS, +// ACTIVE_POOL_ABI, +// PRICE_FEED_ADDRESS, +// PRICE_FEED_ABI, +// HINT_HELPERS_ADDRESS, +// HINT_HELPERS_ABI, +// SORTED_TROVES_ADDRESS, +// SORTED_TROVES_ABI, +// STAKING_ADDRESS, +// STAKING_ABI, +// LQTY_TOKEN_ADDRESS, +// LQTY_TOKEN_ABI, +// COLL_SURPLUS_ADDRESS, +// COLL_SURPLUS_ABI, +// }; diff --git a/test/mainnet/liquity/liquity.helpers.ts b/test/mainnet/liquity/liquity.helpers.ts index bab90124..26ff0851 100644 --- a/test/mainnet/liquity/liquity.helpers.ts +++ b/test/mainnet/liquity/liquity.helpers.ts @@ -1,343 +1,343 @@ -import hre from "hardhat"; -import { ethers } from "hardhat"; -import hardhatConfig from "../../../hardhat.config"; +// import hre from "hardhat"; +// import { ethers } from "hardhat"; +// import hardhatConfig from "../../../hardhat.config"; -// Instadapp deployment and testing helpers -import { deployAndEnableConnector } from "../../../scripts/tests/deployAndEnableConnector.js" -import { buildDSAv2 } from "../../../scripts/tests/buildDSAv2" -import { encodeSpells } from "../../../scripts/tests/encodeSpells.js" -import { getMasterSigner } from "../../../scripts/tests/getMasterSigner" +// // Instadapp deployment and testing helpers +// import { deployAndEnableConnector } from "../../../scripts/tests/deployAndEnableConnector.js" +// import { buildDSAv2 } from "../../../scripts/tests/buildDSAv2" +// import { encodeSpells } from "../../../scripts/tests/encodeSpells.js" +// import { getMasterSigner } from "../../../scripts/tests/getMasterSigner" -// Instadapp instadappAddresses/ABIs -import { instadappAddresses } from "../../../scripts/important/addresses"; -import { instadappAbi } from "../../../scripts/constant/abis"; +// // Instadapp instadappAddresses/ABIs +// import { instadappAddresses } from "../../../scripts/important/addresses"; +// import { instadappAbi } from "../../../scripts/constant/abis"; -// Instadapp Liquity Connector artifacts -import { ConnectV2Liquity__factory, ConnectV2Basic__factory } from "../../../typechain"; +// // Instadapp Liquity Connector artifacts +// import { ConnectV2Liquity__factory, ConnectV2Basic__factory } from "../../../typechain"; -// Instadapp uses a fake address to represent native ETH -import { constants } from "../../../scripts/constant/constant.js"; -import type { Signer, Contract } from "ethers"; +// // Instadapp uses a fake address to represent native ETH +// import { constants } from "../../../scripts/constant/constant.js"; +// import type { Signer, Contract } from "ethers"; -const LIQUITY_CONNECTOR = "LIQUITY-v1-TEST"; -const LUSD_GAS_COMPENSATION = hre.ethers.utils.parseUnits("200", 18); // 200 LUSD gas compensation repaid after loan repayment -const LIQUIDATABLE_TROVES_BLOCK_NUMBER = 12478159; // Deterministic block number for tests to run against, if you change this, tests will break. -const JUSTIN_SUN_ADDRESS = "0x903d12bf2c57a29f32365917c706ce0e1a84cce3"; // LQTY whale address -const LIQUIDATABLE_TROVE_ADDRESS = "0xafbeb4cb97f3b08ec2fe07ef0dac15d37013a347"; // Trove which is liquidatable at blockNumber: LIQUIDATABLE_TROVES_BLOCK_NUMBER -// const MAX_GAS = hardhatConfig.networks.hardhat.blockGasLimit; // Maximum gas limit (12000000) -const INSTADAPP_BASIC_V1_CONNECTOR = "Basic-v1"; +// const LIQUITY_CONNECTOR = "LIQUITY-v1-TEST"; +// const LUSD_GAS_COMPENSATION = hre.ethers.utils.parseUnits("200", 18); // 200 LUSD gas compensation repaid after loan repayment +// const LIQUIDATABLE_TROVES_BLOCK_NUMBER = 12478159; // Deterministic block number for tests to run against, if you change this, tests will break. +// const JUSTIN_SUN_ADDRESS = "0x903d12bf2c57a29f32365917c706ce0e1a84cce3"; // LQTY whale address +// const LIQUIDATABLE_TROVE_ADDRESS = "0xafbeb4cb97f3b08ec2fe07ef0dac15d37013a347"; // Trove which is liquidatable at blockNumber: LIQUIDATABLE_TROVES_BLOCK_NUMBER +// // const MAX_GAS = hardhatConfig.networks.hardhat.blockGasLimit; // Maximum gas limit (12000000) +// const INSTADAPP_BASIC_V1_CONNECTOR = "Basic-v1"; -const openTroveSpell = async ( - dsa: any, - signer: Signer, - depositAmount: any, - borrowAmount: any, - upperHint: any, - lowerHint: any, - maxFeePercentage: any -) => { - let address = await signer.getAddress(); +// const openTroveSpell = async ( +// dsa: any, +// signer: Signer, +// depositAmount: any, +// borrowAmount: any, +// upperHint: any, +// lowerHint: any, +// maxFeePercentage: any +// ) => { +// let address = await signer.getAddress(); - const openTroveSpell = { - connector: LIQUITY_CONNECTOR, - method: "open", - args: [ - depositAmount, - maxFeePercentage, - borrowAmount, - upperHint, - lowerHint, - [0, 0], - [0, 0], - ], - }; +// const openTroveSpell = { +// connector: LIQUITY_CONNECTOR, +// method: "open", +// args: [ +// depositAmount, +// maxFeePercentage, +// borrowAmount, +// upperHint, +// lowerHint, +// [0, 0], +// [0, 0], +// ], +// }; - return await dsa - .connect(signer) - .cast(...encodeSpells([openTroveSpell]), address, { - value: depositAmount, - }); -}; +// return await dsa +// .connect(signer) +// .cast(...encodeSpells([openTroveSpell]), address, { +// value: depositAmount, +// }); +// }; -const createDsaTrove = async ( - dsa: any, - signer: any, - liquity: any, - depositAmount = hre.ethers.utils.parseEther("5"), - borrowAmount = hre.ethers.utils.parseUnits("2000", 18) -) => { - const maxFeePercentage = hre.ethers.utils.parseUnits("0.5", 18); // 0.5% max fee - const { upperHint, lowerHint } = await getTroveInsertionHints( - depositAmount, - borrowAmount, - liquity - ); - return await openTroveSpell( - dsa, - signer, - depositAmount, - borrowAmount, - upperHint, - lowerHint, - maxFeePercentage - ); -}; +// const createDsaTrove = async ( +// dsa: any, +// signer: any, +// liquity: any, +// depositAmount = hre.ethers.utils.parseEther("5"), +// borrowAmount = hre.ethers.utils.parseUnits("2000", 18) +// ) => { +// const maxFeePercentage = hre.ethers.utils.parseUnits("0.5", 18); // 0.5% max fee +// const { upperHint, lowerHint } = await getTroveInsertionHints( +// depositAmount, +// borrowAmount, +// liquity +// ); +// return await openTroveSpell( +// dsa, +// signer, +// depositAmount, +// borrowAmount, +// upperHint, +// lowerHint, +// maxFeePercentage +// ); +// }; -const sendToken = async (token: any, amount: any, from: any, to: any) => { - await hre.network.provider.request({ - method: "hardhat_impersonateAccount", - params: [from], - }); - const signer = hre.ethers.provider.getSigner(from); +// const sendToken = async (token: any, amount: any, from: any, to: any) => { +// await hre.network.provider.request({ +// method: "hardhat_impersonateAccount", +// params: [from], +// }); +// const signer = hre.ethers.provider.getSigner(from); - return await token.connect(signer).transfer(to, amount, { - gasPrice: 0, - }); -}; +// return await token.connect(signer).transfer(to, amount, { +// gasPrice: 0, +// }); +// }; -const resetInitialState = async (walletAddress: any, contracts: any, isDebug = false) => { - const liquity = await deployAndConnect(contracts, isDebug); - const dsa = await buildDSAv2(walletAddress); +// const resetInitialState = async (walletAddress: any, contracts: any, isDebug = false) => { +// const liquity = await deployAndConnect(contracts, isDebug); +// const dsa = await buildDSAv2(walletAddress); - return [liquity, dsa]; -}; +// return [liquity, dsa]; +// }; -const resetHardhatBlockNumber = async (blockNumber: number) => { - return await hre.network.provider.request({ - method: "hardhat_reset", - params: [ - { - forking: { - // @ts-ignore - jsonRpcUrl: hre.config.networks.hardhat.forking.url, - blockNumber, - }, - }, - ], - }); -}; +// const resetHardhatBlockNumber = async (blockNumber: number) => { +// return await hre.network.provider.request({ +// method: "hardhat_reset", +// params: [ +// { +// forking: { +// // @ts-ignore +// jsonRpcUrl: hre.config.networks.hardhat.forking.url, +// blockNumber, +// }, +// }, +// ], +// }); +// }; -const deployAndConnect = async (contracts: any, isDebug = false) => { - // Pin Liquity tests to a particular block number to create deterministic state (Ether price etc.) - await resetHardhatBlockNumber(LIQUIDATABLE_TROVES_BLOCK_NUMBER); - let liquity = { - troveManager: Contract, - borrowerOperations: null, - stabilityPool: null, - lusdToken: null, - lqtyToken: null, - activePool: null, - priceFeed: null, - hintHelpers: null, - sortedTroves: null, - staking: null, - collSurplus: null, - }; +// const deployAndConnect = async (contracts: any, isDebug = false) => { +// // Pin Liquity tests to a particular block number to create deterministic state (Ether price etc.) +// await resetHardhatBlockNumber(LIQUIDATABLE_TROVES_BLOCK_NUMBER); +// let liquity = { +// troveManager: Contract, +// borrowerOperations: null, +// stabilityPool: null, +// lusdToken: null, +// lqtyToken: null, +// activePool: null, +// priceFeed: null, +// hintHelpers: null, +// sortedTroves: null, +// staking: null, +// collSurplus: null, +// }; - const masterSigner = await getMasterSigner(); - const instaConnectorsV2 = await ethers.getContractAt( - instadappAbi.core.connectorsV2, - instadappAddresses.core.connectorsV2 - ); - const connector = await deployAndEnableConnector({ - connectorName: LIQUITY_CONNECTOR, - contractArtifact: ConnectV2Liquity__factory, - signer: masterSigner, - connectors: instaConnectorsV2, - }); - isDebug && - console.log(`${LIQUITY_CONNECTOR} Connector address`, connector.address); +// const masterSigner = await getMasterSigner(); +// const instaConnectorsV2 = await ethers.getContractAt( +// instadappAbi.core.connectorsV2, +// instadappAddresses.core.connectorsV2 +// ); +// const connector = await deployAndEnableConnector({ +// connectorName: LIQUITY_CONNECTOR, +// contractArtifact: ConnectV2Liquity__factory, +// signer: masterSigner, +// connectors: instaConnectorsV2, +// }); +// isDebug && +// console.log(`${LIQUITY_CONNECTOR} Connector address`, connector.address); - const basicConnector = await deployAndEnableConnector({ - connectorName: "Basic-v1", - contractArtifact: ConnectV2Basic__factory, - signer: masterSigner, - connectors: instaConnectorsV2, - }); - isDebug && console.log("Basic-v1 Connector address", basicConnector.address); +// const basicConnector = await deployAndEnableConnector({ +// connectorName: "Basic-v1", +// contractArtifact: ConnectV2Basic__factory, +// signer: masterSigner, +// connectors: instaConnectorsV2, +// }); +// isDebug && console.log("Basic-v1 Connector address", basicConnector.address); - liquity.troveManager = new ethers.Contract( - contracts.TROVE_MANAGER_ADDRESS, - contracts.TROVE_MANAGER_ABI, - ethers.provider - ); +// liquity.troveManager = new ethers.Contract( +// contracts.TROVE_MANAGER_ADDRESS, +// contracts.TROVE_MANAGER_ABI, +// ethers.provider +// ); - liquity.borrowerOperations = new ethers.Contract( - contracts.BORROWER_OPERATIONS_ADDRESS, - contracts.BORROWER_OPERATIONS_ABI, - ethers.provider - ); +// liquity.borrowerOperations = new ethers.Contract( +// contracts.BORROWER_OPERATIONS_ADDRESS, +// contracts.BORROWER_OPERATIONS_ABI, +// ethers.provider +// ); - liquity.stabilityPool = new ethers.Contract( - contracts.STABILITY_POOL_ADDRESS, - contracts.STABILITY_POOL_ABI, - ethers.provider - ); +// liquity.stabilityPool = new ethers.Contract( +// contracts.STABILITY_POOL_ADDRESS, +// contracts.STABILITY_POOL_ABI, +// ethers.provider +// ); - liquity.lusdToken = new ethers.Contract( - contracts.LUSD_TOKEN_ADDRESS, - contracts.LUSD_TOKEN_ABI, - ethers.provider - ); +// liquity.lusdToken = new ethers.Contract( +// contracts.LUSD_TOKEN_ADDRESS, +// contracts.LUSD_TOKEN_ABI, +// ethers.provider +// ); - liquity.lqtyToken = new ethers.Contract( - contracts.LQTY_TOKEN_ADDRESS, - contracts.LQTY_TOKEN_ABI, - ethers.provider - ); +// liquity.lqtyToken = new ethers.Contract( +// contracts.LQTY_TOKEN_ADDRESS, +// contracts.LQTY_TOKEN_ABI, +// ethers.provider +// ); - liquity.activePool = new ethers.Contract( - contracts.ACTIVE_POOL_ADDRESS, - contracts.ACTIVE_POOL_ABI, - ethers.provider - ); +// liquity.activePool = new ethers.Contract( +// contracts.ACTIVE_POOL_ADDRESS, +// contracts.ACTIVE_POOL_ABI, +// ethers.provider +// ); - liquity.priceFeed = new ethers.Contract( - contracts.PRICE_FEED_ADDRESS, - contracts.PRICE_FEED_ABI, - ethers.provider - ); +// liquity.priceFeed = new ethers.Contract( +// contracts.PRICE_FEED_ADDRESS, +// contracts.PRICE_FEED_ABI, +// ethers.provider +// ); - liquity.hintHelpers = new ethers.Contract( - contracts.HINT_HELPERS_ADDRESS, - contracts.HINT_HELPERS_ABI, - ethers.provider - ); +// liquity.hintHelpers = new ethers.Contract( +// contracts.HINT_HELPERS_ADDRESS, +// contracts.HINT_HELPERS_ABI, +// ethers.provider +// ); - liquity.sortedTroves = new ethers.Contract( - contracts.SORTED_TROVES_ADDRESS, - contracts.SORTED_TROVES_ABI, - ethers.provider - ); +// liquity.sortedTroves = new ethers.Contract( +// contracts.SORTED_TROVES_ADDRESS, +// contracts.SORTED_TROVES_ABI, +// ethers.provider +// ); - liquity.staking = new ethers.Contract( - contracts.STAKING_ADDRESS, - contracts.STAKING_ABI, - ethers.provider - ); - liquity.collSurplus = new ethers.Contract( - contracts.COLL_SURPLUS_ADDRESS, - contracts.COLL_SURPLUS_ABI, - ethers.provider - ); +// liquity.staking = new ethers.Contract( +// contracts.STAKING_ADDRESS, +// contracts.STAKING_ABI, +// ethers.provider +// ); +// liquity.collSurplus = new ethers.Contract( +// contracts.COLL_SURPLUS_ADDRESS, +// contracts.COLL_SURPLUS_ABI, +// ethers.provider +// ); - return liquity; -}; +// return liquity; +// }; -const getTroveInsertionHints = async (depositAmount, borrowAmount, liquity: any) => { - const nominalCR = await liquity.hintHelpers.computeNominalCR( - depositAmount, - borrowAmount - ); +// const getTroveInsertionHints = async (depositAmount, borrowAmount, liquity: any) => { +// const nominalCR = await liquity.hintHelpers.computeNominalCR( +// depositAmount, +// borrowAmount +// ); - const { - hintAddress, - latestRandomSeed, - } = await liquity.hintHelpers.getApproxHint(nominalCR, 50, 1298379, { - gasLimit: MAX_GAS, - }); - randomSeed = latestRandomSeed; +// const { +// hintAddress, +// latestRandomSeed, +// } = await liquity.hintHelpers.getApproxHint(nominalCR, 50, 1298379, { +// gasLimit: MAX_GAS, +// }); +// randomSeed = latestRandomSeed; - const { - 0: upperHint, - 1: lowerHint, - } = await liquity.sortedTroves.findInsertPosition( - nominalCR, - hintAddress, - hintAddress, - { - gasLimit: MAX_GAS, - } - ); +// const { +// 0: upperHint, +// 1: lowerHint, +// } = await liquity.sortedTroves.findInsertPosition( +// nominalCR, +// hintAddress, +// hintAddress, +// { +// gasLimit: MAX_GAS, +// } +// ); - return { - upperHint, - lowerHint, - }; -}; +// return { +// upperHint, +// lowerHint, +// }; +// }; -let randomSeed = 4223; +// let randomSeed = 4223; -const getRedemptionHints = async (amount, liquity) => { - const ethPrice = await liquity.priceFeed.callStatic.fetchPrice(); - const [ - firstRedemptionHint, - partialRedemptionHintNicr, - ] = await liquity.hintHelpers.getRedemptionHints(amount, ethPrice, 0); +// const getRedemptionHints = async (amount, liquity) => { +// const ethPrice = await liquity.priceFeed.callStatic.fetchPrice(); +// const [ +// firstRedemptionHint, +// partialRedemptionHintNicr, +// ] = await liquity.hintHelpers.getRedemptionHints(amount, ethPrice, 0); - const { - hintAddress, - latestRandomSeed, - } = await liquity.hintHelpers.getApproxHint( - partialRedemptionHintNicr, - 50, - randomSeed, - { - gasLimit: MAX_GAS, - } - ); - randomSeed = latestRandomSeed; +// const { +// hintAddress, +// latestRandomSeed, +// } = await liquity.hintHelpers.getApproxHint( +// partialRedemptionHintNicr, +// 50, +// randomSeed, +// { +// gasLimit: MAX_GAS, +// } +// ); +// randomSeed = latestRandomSeed; - const { - 0: upperHint, - 1: lowerHint, - } = await liquity.sortedTroves.findInsertPosition( - partialRedemptionHintNicr, - hintAddress, - hintAddress, - { - gasLimit: MAX_GAS, - } - ); +// const { +// 0: upperHint, +// 1: lowerHint, +// } = await liquity.sortedTroves.findInsertPosition( +// partialRedemptionHintNicr, +// hintAddress, +// hintAddress, +// { +// gasLimit: MAX_GAS, +// } +// ); - return { - partialRedemptionHintNicr, - firstRedemptionHint, - upperHint, - lowerHint, - }; -}; +// return { +// partialRedemptionHintNicr, +// firstRedemptionHint, +// upperHint, +// lowerHint, +// }; +// }; -const redeem = async (amount, from, wallet, liquity) => { - await sendToken(liquity.lusdToken, amount, from, wallet.address); - const { - partialRedemptionHintNicr, - firstRedemptionHint, - upperHint, - lowerHint, - } = await getRedemptionHints(amount, liquity); - const maxFeePercentage = ethers.utils.parseUnits("0.5", 18); // 0.5% max fee +// const redeem = async (amount, from, wallet, liquity) => { +// await sendToken(liquity.lusdToken, amount, from, wallet.address); +// const { +// partialRedemptionHintNicr, +// firstRedemptionHint, +// upperHint, +// lowerHint, +// } = await getRedemptionHints(amount, liquity); +// const maxFeePercentage = ethers.utils.parseUnits("0.5", 18); // 0.5% max fee - return await liquity.troveManager - .connect(wallet) - .redeemCollateral( - amount, - firstRedemptionHint, - upperHint, - lowerHint, - partialRedemptionHintNicr, - 0, - maxFeePercentage, - { - gasLimit: MAX_GAS, // permit max gas - } - ); -}; +// return await liquity.troveManager +// .connect(wallet) +// .redeemCollateral( +// amount, +// firstRedemptionHint, +// upperHint, +// lowerHint, +// partialRedemptionHintNicr, +// 0, +// maxFeePercentage, +// { +// gasLimit: MAX_GAS, // permit max gas +// } +// ); +// }; -module.exports = { - deployAndConnect, - resetInitialState, - createDsaTrove, - sendToken, - getTroveInsertionHints, - getRedemptionHints, - redeem, - LIQUITY_CONNECTOR, - LUSD_GAS_COMPENSATION, - JUSTIN_SUN_ADDRESS, - LIQUIDATABLE_TROVE_ADDRESS, - MAX_GAS, - INSTADAPP_BASIC_V1_CONNECTOR, - ETH_ADDRESS, -}; +// module.exports = { +// deployAndConnect, +// resetInitialState, +// createDsaTrove, +// sendToken, +// getTroveInsertionHints, +// getRedemptionHints, +// redeem, +// LIQUITY_CONNECTOR, +// LUSD_GAS_COMPENSATION, +// JUSTIN_SUN_ADDRESS, +// LIQUIDATABLE_TROVE_ADDRESS, +// MAX_GAS, +// INSTADAPP_BASIC_V1_CONNECTOR, +// ETH_ADDRESS, +// }; diff --git a/test/mainnet/liquity/liquity.test.ts b/test/mainnet/liquity/liquity.test.ts index fd5ccd69..151c1881 100644 --- a/test/mainnet/liquity/liquity.test.ts +++ b/test/mainnet/liquity/liquity.test.ts @@ -1,2719 +1,2719 @@ -import hre from "hardhat"; -import { expect } from "chai"; - -// Instadapp deployment and testing helpers -import { buildDSAv2 } from "../../../scripts/tests/buildDSAv2"; -import { encodeSpells } from "../../../scripts/tests/encodeSpells.js"; - -// Liquity smart contracts -import contracts from "./liquity.contracts"; - -// Liquity helpers -import helpers from "./liquity.helpers"; - -describe("Liquity", () => { - const { waffle, ethers } = hre; - const { provider } = waffle; - - // Waffle test account 0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266 (holds 1000 ETH) - const userWallet = provider.getWallets()[0]; - let dsa = null; - let liquity = null; - - before(async () => { - await hre.network.provider.request({ - method: "hardhat_reset", - params: [ - { - forking: { - jsonRpcUrl: hre.config.networks.hardhat.forking.url, - blockNumber: 13300000, - }, - }, - ], - }); - liquity = await helpers.deployAndConnect(contracts, true); - expect(liquity.troveManager.address).to.exist; - expect(liquity.borrowerOperations.address).to.exist; - expect(liquity.stabilityPool.address).to.exist; - expect(liquity.lusdToken.address).to.exist; - expect(liquity.lqtyToken.address).to.exist; - expect(liquity.activePool.address).to.exist; - expect(liquity.priceFeed.address).to.exist; - expect(liquity.hintHelpers.address).to.exist; - expect(liquity.sortedTroves.address).to.exist; - expect(liquity.staking.address).to.exist; - }); - - beforeEach(async () => { - // Build a new DSA before each test so we start each test from the same default state - dsa = await buildDSAv2(userWallet.address); - expect(dsa.address).to.exist; - }); - - describe("Main (Connector)", () => { - describe("Trove", () => { - describe("open()", () => { - it("opens a Trove", async () => { - const depositAmount = ethers.utils.parseEther("5"); // 5 ETH - const borrowAmount = ethers.utils.parseUnits("2000", 18); // 2000 LUSD - const maxFeePercentage = ethers.utils.parseUnits("0.5", 18); // 0.5% max fee - const upperHint = ethers.constants.AddressZero; - const lowerHint = ethers.constants.AddressZero; - const originalUserBalance = await ethers.provider.getBalance( - userWallet.address - ); - const originalDsaBalance = await ethers.provider.getBalance( - dsa.address - ); - - const openTroveSpell = { - connector: helpers.LIQUITY_CONNECTOR, - method: "open", - args: [ - depositAmount, - maxFeePercentage, - borrowAmount, - upperHint, - lowerHint, - [0, 0], - [0, 0], - ], - }; - - await dsa - .connect(userWallet) - .cast(...encodeSpells([openTroveSpell]), userWallet.address, { - value: depositAmount, - gasPrice: 0, - }); - - const userBalance = await ethers.provider.getBalance( - userWallet.address - ); - const dsaEthBalance = await ethers.provider.getBalance(dsa.address); - const dsaLusdBalance = await liquity.lusdToken.balanceOf(dsa.address); - const troveDebt = await liquity.troveManager.getTroveDebt( - dsa.address - ); - const troveCollateral = await liquity.troveManager.getTroveColl( - dsa.address - ); - - expect(userBalance).eq( - originalUserBalance.sub(depositAmount), - "User's Ether balance should decrease by the amount they deposited" - ); - - expect(dsaEthBalance).to.eq( - originalDsaBalance, - "User's DSA account Ether should not change after borrowing" - ); - - expect( - dsaLusdBalance, - "DSA account should now hold the amount the user borrowed" - ).to.eq(borrowAmount); - - expect(troveDebt).to.gt( - borrowAmount, - "Trove debt should equal the borrowed amount plus fee" - ); - - expect(troveCollateral).to.eq( - depositAmount, - "Trove collateral should equal the deposited amount" - ); - }); - - it("opens a Trove using ETH collected from a previous spell", async () => { - const depositAmount = ethers.utils.parseEther("5"); // 5 ETH - const borrowAmount = ethers.utils.parseUnits("2000", 18); // 2000 LUSD - const maxFeePercentage = ethers.utils.parseUnits("0.5", 18); // 0.5% max fee - const upperHint = ethers.constants.AddressZero; - const lowerHint = ethers.constants.AddressZero; - const originalUserBalance = await ethers.provider.getBalance( - userWallet.address - ); - const originalDsaBalance = await ethers.provider.getBalance( - dsa.address - ); - const depositId = 1; // Choose an ID to store and retrieve the deposited ETH - - const depositEthSpell = { - connector: helpers.INSTADAPP_BASIC_V1_CONNECTOR, - method: "deposit", - args: [helpers.ETH_ADDRESS, depositAmount, 0, depositId], - }; - - const openTroveSpell = { - connector: helpers.LIQUITY_CONNECTOR, - method: "open", - args: [ - 0, // When pulling ETH from a previous spell it doesn't matter what deposit value we put in this param - maxFeePercentage, - borrowAmount, - upperHint, - lowerHint, - [depositId, 0], - [0, 0], - ], - }; - - const spells = [depositEthSpell, openTroveSpell]; - await dsa - .connect(userWallet) - .cast(...encodeSpells(spells), userWallet.address, { - value: depositAmount, - gasPrice: 0, - }); - - const userBalance = await ethers.provider.getBalance( - userWallet.address - ); - const dsaEthBalance = await ethers.provider.getBalance(dsa.address); - const dsaLusdBalance = await liquity.lusdToken.balanceOf(dsa.address); - const troveDebt = await liquity.troveManager.getTroveDebt( - dsa.address - ); - const troveCollateral = await liquity.troveManager.getTroveColl( - dsa.address - ); - - expect(userBalance).eq( - originalUserBalance.sub(depositAmount), - "User's Ether balance should decrease by the amount they deposited" - ); - - expect(dsaEthBalance).to.eq( - originalDsaBalance, - "DSA balance should not change" - ); - - expect( - dsaLusdBalance, - "DSA account should now hold the amount the user borrowed" - ).to.eq(borrowAmount); - - expect(troveDebt).to.gt( - borrowAmount, - "Trove debt should equal the borrowed amount plus fee" - ); - - expect(troveCollateral).to.eq( - depositAmount, - "Trove collateral should equal the deposited amount" - ); - }); - - it("opens a Trove and stores the debt for other spells to use", async () => { - const depositAmount = ethers.utils.parseEther("5"); // 5 ETH - const borrowAmount = ethers.utils.parseUnits("2000", 18); // 2000 LUSD - const maxFeePercentage = ethers.utils.parseUnits("0.5", 18); // 0.5% max fee - const upperHint = ethers.constants.AddressZero; - const lowerHint = ethers.constants.AddressZero; - const originalUserBalance = await ethers.provider.getBalance( - userWallet.address - ); - const originalDsaBalance = await ethers.provider.getBalance( - dsa.address - ); - const borrowId = 1; - - const openTroveSpell = { - connector: helpers.LIQUITY_CONNECTOR, - method: "open", - args: [ - depositAmount, - maxFeePercentage, - borrowAmount, - upperHint, - lowerHint, - [0, 0], - [borrowId, 0], - ], - }; - - const withdrawLusdSpell = { - connector: helpers.INSTADAPP_BASIC_V1_CONNECTOR, - method: "withdraw", - args: [ - contracts.LUSD_TOKEN_ADDRESS, - 0, // Amount comes from the previous spell's setId - dsa.address, - borrowId, - 0, - ], - }; - - const spells = [openTroveSpell, withdrawLusdSpell]; - await dsa - .connect(userWallet) - .cast(...encodeSpells(spells), userWallet.address, { - value: depositAmount, - gasPrice: 0, - }); - - const userBalance = await ethers.provider.getBalance( - userWallet.address - ); - const dsaEthBalance = await ethers.provider.getBalance(dsa.address); - const dsaLusdBalance = await liquity.lusdToken.balanceOf(dsa.address); - const troveDebt = await liquity.troveManager.getTroveDebt( - dsa.address - ); - const troveCollateral = await liquity.troveManager.getTroveColl( - dsa.address - ); - - expect(userBalance).eq( - originalUserBalance.sub(depositAmount), - "User's Ether balance should decrease by the amount they deposited" - ); - - expect(dsaEthBalance).to.eq( - originalDsaBalance, - "User's DSA account Ether should not change after borrowing" - ); - - expect( - dsaLusdBalance, - "DSA account should now hold the amount the user borrowed" - ).to.eq(borrowAmount); - - expect(troveDebt).to.gt( - borrowAmount, - "Trove debt should equal the borrowed amount plus fee" - ); - - expect(troveCollateral).to.eq( - depositAmount, - "Trove collateral should equal the deposited amount" - ); - }); - - it("returns Instadapp event name and data", async () => { - const depositAmount = ethers.utils.parseEther("5"); - const borrowAmount = ethers.utils.parseUnits("2000", 18); - const maxFeePercentage = ethers.utils.parseUnits("0.5", 18); - const upperHint = ethers.constants.AddressZero; - const lowerHint = ethers.constants.AddressZero; - - const openTroveSpell = { - connector: helpers.LIQUITY_CONNECTOR, - method: "open", - args: [ - depositAmount, - maxFeePercentage, - borrowAmount, - upperHint, - lowerHint, - [0, 0], - [0, 0], - ], - }; - - const openTx = await dsa.cast( - ...encodeSpells([openTroveSpell]), - userWallet.address, - { - value: depositAmount, - } - ); - const receipt = await openTx.wait(); - const castLogEvent = receipt.events.find((e) => e.event === "LogCast") - .args; - expect(castLogEvent.eventNames[0]).eq( - "LogOpen(address,uint256,uint256,uint256,uint256[],uint256[])" - ); - const expectedEventParams = ethers.utils.defaultAbiCoder.encode( - [ - "address", - "uint256", - "uint256", - "uint256", - "uint256[]", - "uint256[]", - ], - [ - dsa.address, - maxFeePercentage, - depositAmount, - borrowAmount, - [0, 0], - [0, 0], - ] - ); - expect(castLogEvent.eventParams[0]).eq(expectedEventParams); - }); - }); - - describe("close()", () => { - it("closes a Trove", async () => { - const depositAmount = ethers.utils.parseEther("5"); - const borrowAmount = ethers.utils.parseUnits("2000", 18); - // Create a dummy Trove - await helpers.createDsaTrove( - dsa, - userWallet, - liquity, - depositAmount, - borrowAmount - ); - - const troveDebtBefore = await liquity.troveManager.getTroveDebt( - dsa.address - ); - - const troveCollateralBefore = await liquity.troveManager.getTroveColl( - dsa.address - ); - - // Send DSA account enough LUSD (from Stability Pool) to close their Trove - const extraLusdRequiredToCloseTrove = troveDebtBefore.sub( - borrowAmount - ); - - await helpers.sendToken( - liquity.lusdToken, - extraLusdRequiredToCloseTrove, - contracts.STABILITY_POOL_ADDRESS, - dsa.address - ); - - const originalDsaLusdBalance = await liquity.lusdToken.balanceOf( - dsa.address - ); - - expect( - originalDsaLusdBalance, - "DSA account should now hold the LUSD amount required to pay off the Trove debt" - ).to.eq(troveDebtBefore); - - const closeTroveSpell = { - connector: helpers.LIQUITY_CONNECTOR, - method: "close", - args: [0], - }; - - await dsa - .connect(userWallet) - .cast(...encodeSpells([closeTroveSpell]), userWallet.address); - - const dsaEthBalance = await ethers.provider.getBalance(dsa.address); - const dsaLusdBalance = await liquity.lusdToken.balanceOf(dsa.address); - const troveDebt = await liquity.troveManager.getTroveDebt( - dsa.address - ); - const troveCollateral = await liquity.troveManager.getTroveColl( - dsa.address - ); - - expect(troveDebt, "Trove debt should equal 0 after close").to.eq(0); - - expect( - troveCollateral, - "Trove collateral should equal 0 after close" - ).to.eq(0); - - expect( - dsaEthBalance, - "DSA account should now hold the Trove's ETH collateral" - ).to.eq(troveCollateralBefore); - - expect( - dsaLusdBalance, - "DSA account should now hold the gas compensation amount of LUSD as it paid off the Trove debt" - ).to.eq(helpers.LUSD_GAS_COMPENSATION); - }); - - it("closes a Trove using LUSD obtained from a previous spell", async () => { - // Create a dummy Trove - await helpers.createDsaTrove(dsa, userWallet, liquity); - - const troveDebtBefore = await liquity.troveManager.getTroveDebt( - dsa.address - ); - const troveCollateralBefore = await liquity.troveManager.getTroveColl( - dsa.address - ); - - // Send user enough LUSD to repay the loan, we'll use a deposit and withdraw spell to obtain it - await helpers.sendToken( - liquity.lusdToken, - troveDebtBefore, - contracts.STABILITY_POOL_ADDRESS, - userWallet.address - ); - - // Allow DSA to spend user's LUSD - await liquity.lusdToken - .connect(userWallet) - .approve(dsa.address, troveDebtBefore); - - // Simulate a spell which would have pulled LUSD from somewhere (e.g. Uniswap) into InstaMemory - // In this case we're simply running a deposit spell from the user's EOA - const depositLusdSpell = { - connector: helpers.INSTADAPP_BASIC_V1_CONNECTOR, - method: "deposit", - args: [contracts.LUSD_TOKEN_ADDRESS, troveDebtBefore, 0, 0], - }; - - const closeTroveSpell = { - connector: helpers.LIQUITY_CONNECTOR, - method: "close", - args: [0], - }; - const spells = [depositLusdSpell, closeTroveSpell]; - - await dsa - .connect(userWallet) - .cast(...encodeSpells(spells), userWallet.address); - - const dsaEthBalance = await ethers.provider.getBalance(dsa.address); - const troveDebt = await liquity.troveManager.getTroveDebt( - dsa.address - ); - const troveCollateral = await liquity.troveManager.getTroveColl( - dsa.address - ); - - expect(troveDebt, "Trove debt should equal 0 after close").to.eq(0); - - expect( - troveCollateral, - "Trove collateral should equal 0 after close" - ).to.eq(0); - - expect( - dsaEthBalance, - "DSA account should now hold the Trove's ETH collateral" - ).to.eq(troveCollateralBefore); - }); - - it("closes a Trove and stores the released collateral for other spells to use", async () => { - const depositAmount = ethers.utils.parseEther("5"); - const borrowAmount = ethers.utils.parseUnits("2000", 18); - // Create a dummy Trove - await helpers.createDsaTrove( - dsa, - userWallet, - liquity, - depositAmount, - borrowAmount - ); - - const troveDebtBefore = await liquity.troveManager.getTroveDebt( - dsa.address - ); - const troveCollateralBefore = await liquity.troveManager.getTroveColl( - dsa.address - ); - - // Send DSA account enough LUSD (from Stability Pool) to close their Trove - const extraLusdRequiredToCloseTrove = troveDebtBefore.sub( - borrowAmount - ); - await helpers.sendToken( - liquity.lusdToken, - extraLusdRequiredToCloseTrove, - contracts.STABILITY_POOL_ADDRESS, - dsa.address - ); - const originalDsaLusdBalance = await liquity.lusdToken.balanceOf( - dsa.address - ); - - expect( - originalDsaLusdBalance, - "DSA account should now hold the LUSD amount required to pay off the Trove debt" - ).to.eq(troveDebtBefore); - - const collateralWithdrawId = 1; - - const closeTroveSpell = { - connector: helpers.LIQUITY_CONNECTOR, - method: "close", - args: [collateralWithdrawId], - }; - - const withdrawEthSpell = { - connector: helpers.INSTADAPP_BASIC_V1_CONNECTOR, - method: "withdraw", - args: [ - helpers.ETH_ADDRESS, - 0, // amount comes from the previous spell's setId - dsa.address, - collateralWithdrawId, - 0, - ], - }; - - await dsa - .connect(userWallet) - .cast( - ...encodeSpells([closeTroveSpell, withdrawEthSpell]), - userWallet.address - ); - - const dsaEthBalance = await ethers.provider.getBalance(dsa.address); - const dsaLusdBalance = await liquity.lusdToken.balanceOf(dsa.address); - const troveDebt = await liquity.troveManager.getTroveDebt( - dsa.address - ); - const troveCollateral = await liquity.troveManager.getTroveColl( - dsa.address - ); - - expect(troveDebt, "Trove debt should equal 0 after close").to.eq(0); - - expect( - troveCollateral, - "Trove collateral should equal 0 after close" - ).to.eq(0); - - expect( - dsaEthBalance, - "DSA account should now hold the Trove's ETH collateral" - ).to.eq(troveCollateralBefore); - - expect( - dsaLusdBalance, - "DSA account should now hold the gas compensation amount of LUSD as it paid off the Trove debt" - ).to.eq(helpers.LUSD_GAS_COMPENSATION); - }); - - it("returns Instadapp event name and data", async () => { - const depositAmount = ethers.utils.parseEther("5"); - const borrowAmount = ethers.utils.parseUnits("2000", 18); - // Create a dummy Trove - await helpers.createDsaTrove( - dsa, - userWallet, - liquity, - depositAmount, - borrowAmount - ); - await helpers.sendToken( - liquity.lusdToken, - ethers.utils.parseUnits("2500", 18), - contracts.STABILITY_POOL_ADDRESS, - dsa.address - ); - - const closeTroveSpell = { - connector: helpers.LIQUITY_CONNECTOR, - method: "close", - args: [0], - }; - - const closeTx = await dsa - .connect(userWallet) - .cast(...encodeSpells([closeTroveSpell]), userWallet.address); - - const receipt = await closeTx.wait(); - const castLogEvent = receipt.events.find((e) => e.event === "LogCast") - .args; - const expectedEventParams = ethers.utils.defaultAbiCoder.encode( - ["address", "uint256"], - [dsa.address, 0] - ); - expect(castLogEvent.eventNames[0]).eq("LogClose(address,uint256)"); - expect(castLogEvent.eventParams[0]).eq(expectedEventParams); - }); - }); - - describe("deposit()", () => { - it("deposits ETH into a Trove", async () => { - // Create a dummy Trove - await helpers.createDsaTrove(dsa, userWallet, liquity); - - const troveCollateralBefore = await liquity.troveManager.getTroveColl( - dsa.address - ); - - const topupAmount = ethers.utils.parseEther("1"); - const upperHint = ethers.constants.AddressZero; - const lowerHint = ethers.constants.AddressZero; - const depositEthSpell = { - connector: helpers.LIQUITY_CONNECTOR, - method: "deposit", - args: [topupAmount, upperHint, lowerHint, 0, 0], - }; - - await dsa - .connect(userWallet) - .cast(...encodeSpells([depositEthSpell]), userWallet.address, { - value: topupAmount, - }); - - const troveCollateral = await liquity.troveManager.getTroveColl( - dsa.address - ); - - const expectedTroveCollateral = troveCollateralBefore.add( - topupAmount - ); - - expect( - troveCollateral, - `Trove collateral should have increased by ${topupAmount} ETH` - ).to.eq(expectedTroveCollateral); - }); - - it("deposits using ETH gained from a previous spell", async () => { - // Create a dummy Trove - await helpers.createDsaTrove(dsa, userWallet, liquity); - const troveCollateralBefore = await liquity.troveManager.getTroveColl( - dsa.address - ); - - const topupAmount = ethers.utils.parseEther("1"); - const depositId = 1; - const depositEthSpell = { - connector: helpers.INSTADAPP_BASIC_V1_CONNECTOR, - method: "deposit", - args: [helpers.ETH_ADDRESS, topupAmount, 0, depositId], - }; - - const upperHint = ethers.constants.AddressZero; - const lowerHint = ethers.constants.AddressZero; - const depositEthToTroveSpell = { - connector: helpers.LIQUITY_CONNECTOR, - method: "deposit", - args: [0, upperHint, lowerHint, depositId, 0], - }; - const spells = [depositEthSpell, depositEthToTroveSpell]; - - await dsa - .connect(userWallet) - .cast(...encodeSpells(spells), userWallet.address, { - value: topupAmount, - }); - - const troveCollateral = await liquity.troveManager.getTroveColl( - dsa.address - ); - - const expectedTroveCollateral = troveCollateralBefore.add( - topupAmount - ); - - expect( - troveCollateral, - `Trove collateral should have increased by ${topupAmount} ETH` - ).to.eq(expectedTroveCollateral); - }); - - it("returns Instadapp event name and data", async () => { - // Create a dummy Trove - await helpers.createDsaTrove(dsa, userWallet, liquity); - - const topupAmount = ethers.utils.parseEther("1"); - const upperHint = ethers.constants.AddressZero; - const lowerHint = ethers.constants.AddressZero; - const depositEthSpell = { - connector: helpers.LIQUITY_CONNECTOR, - method: "deposit", - args: [topupAmount, upperHint, lowerHint, 0, 0], - }; - - const depositTx = await dsa - .connect(userWallet) - .cast(...encodeSpells([depositEthSpell]), userWallet.address, { - value: topupAmount, - }); - - const receipt = await depositTx.wait(); - const castLogEvent = receipt.events.find((e) => e.event === "LogCast") - .args; - const expectedEventParams = ethers.utils.defaultAbiCoder.encode( - ["address", "uint256", "uint256", "uint256"], - [dsa.address, topupAmount, 0, 0] - ); - expect(castLogEvent.eventNames[0]).eq( - "LogDeposit(address,uint256,uint256,uint256)" - ); - expect(castLogEvent.eventParams[0]).eq(expectedEventParams); - }); - }); - - describe("withdraw()", () => { - it("withdraws ETH from a Trove", async () => { - // Create a dummy Trove - await helpers.createDsaTrove(dsa, userWallet, liquity); - - const troveCollateralBefore = await liquity.troveManager.getTroveColl( - dsa.address - ); - const withdrawAmount = ethers.utils.parseEther("1"); - const upperHint = ethers.constants.AddressZero; - const lowerHint = ethers.constants.AddressZero; - const withdrawEthSpell = { - connector: helpers.LIQUITY_CONNECTOR, - method: "withdraw", - args: [withdrawAmount, upperHint, lowerHint, 0, 0], - }; - - await dsa - .connect(userWallet) - .cast(...encodeSpells([withdrawEthSpell]), userWallet.address); - - const troveCollateral = await liquity.troveManager.getTroveColl( - dsa.address - ); - const expectedTroveCollateral = troveCollateralBefore.sub( - withdrawAmount - ); - - expect( - troveCollateral, - `Trove collateral should have decreased by ${withdrawAmount} ETH` - ).to.eq(expectedTroveCollateral); - }); - - it("withdraws ETH from a Trove and stores the ETH for other spells to use", async () => { - // Create a dummy Trove - await helpers.createDsaTrove(dsa, userWallet, liquity); - - const troveCollateralBefore = await liquity.troveManager.getTroveColl( - dsa.address - ); - const originalUserEthBalance = await ethers.provider.getBalance( - userWallet.address - ); - - const withdrawAmount = ethers.utils.parseEther("1"); - const upperHint = ethers.constants.AddressZero; - const lowerHint = ethers.constants.AddressZero; - const withdrawId = 1; - const withdrawEthFromTroveSpell = { - connector: helpers.LIQUITY_CONNECTOR, - method: "withdraw", - args: [withdrawAmount, upperHint, lowerHint, 0, withdrawId], - }; - - const withdrawEthSpell = { - connector: helpers.INSTADAPP_BASIC_V1_CONNECTOR, - method: "withdraw", - args: [helpers.ETH_ADDRESS, 0, userWallet.address, withdrawId, 0], - }; - const spells = [withdrawEthFromTroveSpell, withdrawEthSpell]; - await dsa - .connect(userWallet) - .cast(...encodeSpells(spells), userWallet.address, { - gasPrice: 0, // Remove gas costs so we can check balances have changed correctly - }); - - const troveCollateral = await liquity.troveManager.getTroveColl( - dsa.address - ); - const expectedTroveCollateral = troveCollateralBefore.sub( - withdrawAmount - ); - const userEthBalance = await ethers.provider.getBalance( - userWallet.address - ); - - expect( - troveCollateral, - `Trove collateral should have decreased by ${withdrawAmount} ETH` - ).to.eq(expectedTroveCollateral); - - expect( - userEthBalance, - `User ETH balance should have increased by ${withdrawAmount} ETH` - ).to.eq(originalUserEthBalance.add(withdrawAmount)); - }); - - it("returns Instadapp event name and data", async () => { - // Create a dummy Trove - await helpers.createDsaTrove(dsa, userWallet, liquity); - - const withdrawAmount = ethers.utils.parseEther("1"); - const upperHint = ethers.constants.AddressZero; - const lowerHint = ethers.constants.AddressZero; - const withdrawEthSpell = { - connector: helpers.LIQUITY_CONNECTOR, - method: "withdraw", - args: [withdrawAmount, upperHint, lowerHint, 0, 0], - }; - - const withdrawTx = await dsa - .connect(userWallet) - .cast(...encodeSpells([withdrawEthSpell]), userWallet.address); - - const receipt = await withdrawTx.wait(); - const castLogEvent = receipt.events.find((e) => e.event === "LogCast") - .args; - const expectedEventParams = ethers.utils.defaultAbiCoder.encode( - ["address", "uint256", "uint256", "uint256"], - [dsa.address, withdrawAmount, 0, 0] - ); - expect(castLogEvent.eventNames[0]).eq( - "LogWithdraw(address,uint256,uint256,uint256)" - ); - expect(castLogEvent.eventParams[0]).eq(expectedEventParams); - }); - }); - - describe("borrow()", () => { - it("borrows LUSD from a Trove", async () => { - // Create a dummy Trove - await helpers.createDsaTrove(dsa, userWallet, liquity); - - const troveDebtBefore = await liquity.troveManager.getTroveDebt( - dsa.address - ); - - const borrowAmount = ethers.utils.parseUnits("1000", 18); // 1000 LUSD - const upperHint = ethers.constants.AddressZero; - const lowerHint = ethers.constants.AddressZero; - const maxFeePercentage = ethers.utils.parseUnits("0.5", 18); // 0.5% max fee - const borrowSpell = { - connector: helpers.LIQUITY_CONNECTOR, - method: "borrow", - args: [maxFeePercentage, borrowAmount, upperHint, lowerHint, 0, 0], - }; - - // Borrow more LUSD from the Trove - await dsa - .connect(userWallet) - .cast(...encodeSpells([borrowSpell]), userWallet.address); - - const troveDebt = await liquity.troveManager.getTroveDebt( - dsa.address - ); - const expectedTroveDebt = troveDebtBefore.add(borrowAmount); - - expect( - troveDebt, - `Trove debt should have increased by at least ${borrowAmount} ETH` - ).to.gte(expectedTroveDebt); - }); - - it("borrows LUSD from a Trove and stores the LUSD for other spells to use", async () => { - // Create a dummy Trove - await helpers.createDsaTrove(dsa, userWallet, liquity); - - const troveDebtBefore = await liquity.troveManager.getTroveDebt( - dsa.address - ); - - const borrowAmount = ethers.utils.parseUnits("1000", 18); // 1000 LUSD - const upperHint = ethers.constants.AddressZero; - const lowerHint = ethers.constants.AddressZero; - const maxFeePercentage = ethers.utils.parseUnits("0.5", 18); // 0.5% max fee - const borrowId = 1; - const borrowSpell = { - connector: helpers.LIQUITY_CONNECTOR, - method: "borrow", - args: [ - maxFeePercentage, - borrowAmount, - upperHint, - lowerHint, - 0, - borrowId, - ], - }; - const withdrawSpell = { - connector: helpers.INSTADAPP_BASIC_V1_CONNECTOR, - method: "withdraw", - args: [ - liquity.lusdToken.address, - 0, - userWallet.address, - borrowId, - 0, - ], - }; - const spells = [borrowSpell, withdrawSpell]; - - // Borrow more LUSD from the Trove - await dsa - .connect(userWallet) - .cast(...encodeSpells(spells), userWallet.address); - - const troveDebt = await liquity.troveManager.getTroveDebt( - dsa.address - ); - const expectedTroveDebt = troveDebtBefore.add(borrowAmount); - const userLusdBalance = await liquity.lusdToken.balanceOf( - userWallet.address - ); - - expect( - troveDebt, - `Trove debt should have increased by at least ${borrowAmount} ETH` - ).to.gte(expectedTroveDebt); - - expect( - userLusdBalance, - `User LUSD balance should equal the borrowed LUSD due to the second withdraw spell` - ).eq(borrowAmount); - }); - - it("returns Instadapp event name and data", async () => { - // Create a dummy Trove - await helpers.createDsaTrove(dsa, userWallet, liquity); - - const borrowAmount = ethers.utils.parseUnits("1000", 18); // 1000 LUSD - const upperHint = ethers.constants.AddressZero; - const lowerHint = ethers.constants.AddressZero; - const maxFeePercentage = ethers.utils.parseUnits("0.5", 18); // 0.5% max fee - const borrowSpell = { - connector: helpers.LIQUITY_CONNECTOR, - method: "borrow", - args: [maxFeePercentage, borrowAmount, upperHint, lowerHint, 0, 0], - }; - - const borrowTx = await dsa - .connect(userWallet) - .cast(...encodeSpells([borrowSpell]), userWallet.address); - - const receipt = await borrowTx.wait(); - const castLogEvent = receipt.events.find((e) => e.event === "LogCast") - .args; - const expectedEventParams = ethers.utils.defaultAbiCoder.encode( - ["address", "uint256", "uint256", "uint256"], - [dsa.address, borrowAmount, 0, 0] - ); - expect(castLogEvent.eventNames[0]).eq( - "LogBorrow(address,uint256,uint256,uint256)" - ); - expect(castLogEvent.eventParams[0]).eq(expectedEventParams); - }); - }); - - describe("repay()", () => { - it("repays LUSD to a Trove", async () => { - const depositAmount = ethers.utils.parseEther("5"); - const borrowAmount = ethers.utils.parseUnits("2500", 18); - - // Create a dummy Trove - await helpers.createDsaTrove( - dsa, - userWallet, - liquity, - depositAmount, - borrowAmount - ); - - const troveDebtBefore = await liquity.troveManager.getTroveDebt( - dsa.address - ); - // DSA account is holding 2500 LUSD from opening a Trove, so we use some of that to repay - const repayAmount = ethers.utils.parseUnits("100", 18); // 100 LUSD - - const { upperHint, lowerHint } = await helpers.getTroveInsertionHints( - depositAmount, - borrowAmount, - liquity - ); - const repaySpell = { - connector: helpers.LIQUITY_CONNECTOR, - method: "repay", - args: [repayAmount, upperHint, lowerHint, 0, 0], - }; - - await dsa - .connect(userWallet) - .cast(...encodeSpells([repaySpell]), userWallet.address); - - const troveDebt = await liquity.troveManager.getTroveDebt( - dsa.address - ); - const expectedTroveDebt = troveDebtBefore.sub(repayAmount); - - expect( - troveDebt, - `Trove debt should have decreased by ${repayAmount} ETH` - ).to.eq(expectedTroveDebt); - }); - - it("repays LUSD to a Trove using LUSD collected from a previous spell", async () => { - const depositAmount = ethers.utils.parseEther("5"); - const borrowAmount = ethers.utils.parseUnits("2500", 18); - - // Create a dummy Trove - await helpers.createDsaTrove( - dsa, - userWallet, - liquity, - depositAmount, - borrowAmount - ); - - const troveDebtBefore = await liquity.troveManager.getTroveDebt( - dsa.address - ); - - const repayAmount = ethers.utils.parseUnits("100", 18); // 100 LUSD - const { upperHint, lowerHint } = await helpers.getTroveInsertionHints( - depositAmount, - borrowAmount, - liquity - ); - - // Drain the DSA's LUSD balance so that we ensure we are repaying using LUSD from a previous spell - await helpers.sendToken( - liquity.lusdToken, - borrowAmount, - dsa.address, - userWallet.address - ); - - // Allow DSA to spend user's LUSD - await liquity.lusdToken - .connect(userWallet) - .approve(dsa.address, repayAmount); - - const lusdDepositId = 1; - const depositSpell = { - connector: helpers.INSTADAPP_BASIC_V1_CONNECTOR, - method: "deposit", - args: [liquity.lusdToken.address, repayAmount, 0, lusdDepositId], - }; - const borrowSpell = { - connector: helpers.LIQUITY_CONNECTOR, - method: "repay", - args: [0, upperHint, lowerHint, lusdDepositId, 0], - }; - - const spells = [depositSpell, borrowSpell]; - - await dsa - .connect(userWallet) - .cast(...encodeSpells(spells), userWallet.address); - - const troveDebt = await liquity.troveManager.getTroveDebt( - dsa.address - ); - const expectedTroveDebt = troveDebtBefore.sub(repayAmount); - - expect( - troveDebt, - `Trove debt should have decreased by ${repayAmount} ETH` - ).to.eq(expectedTroveDebt); - }); - - it("returns Instadapp event name and data", async () => { - // Create a dummy Trove - const depositAmount = ethers.utils.parseEther("5"); - const borrowAmount = ethers.utils.parseUnits("2500", 18); - await helpers.createDsaTrove( - dsa, - userWallet, - liquity, - depositAmount, - borrowAmount - ); - - const repayAmount = ethers.utils.parseUnits("100", 18); // 100 LUSD - const { upperHint, lowerHint } = await helpers.getTroveInsertionHints( - depositAmount, - borrowAmount, - liquity - ); - - const borrowSpell = { - connector: helpers.LIQUITY_CONNECTOR, - method: "repay", - args: [repayAmount, upperHint, lowerHint, 0, 0], - }; - - const repayTx = await dsa - .connect(userWallet) - .cast(...encodeSpells([borrowSpell]), userWallet.address, { - value: repayAmount, - }); - - const receipt = await repayTx.wait(); - const castLogEvent = receipt.events.find((e) => e.event === "LogCast") - .args; - const expectedEventParams = ethers.utils.defaultAbiCoder.encode( - ["address", "uint256", "uint256", "uint256"], - [dsa.address, repayAmount, 0, 0] - ); - expect(castLogEvent.eventNames[0]).eq( - "LogRepay(address,uint256,uint256,uint256)" - ); - expect(castLogEvent.eventParams[0]).eq(expectedEventParams); - }); - }); - - describe("adjust()", () => { - it("adjusts a Trove: deposit ETH and borrow LUSD", async () => { - // Create a dummy Trove - await helpers.createDsaTrove(dsa, userWallet, liquity); - - const troveCollateralBefore = await liquity.troveManager.getTroveColl( - dsa.address - ); - const troveDebtBefore = await liquity.troveManager.getTroveDebt( - dsa.address - ); - const depositAmount = ethers.utils.parseEther("1"); // 1 ETH - const borrowAmount = ethers.utils.parseUnits("500", 18); // 500 LUSD - const withdrawAmount = 0; - const repayAmount = 0; - const upperHint = ethers.constants.AddressZero; - const lowerHint = ethers.constants.AddressZero; - const maxFeePercentage = ethers.utils.parseUnits("0.5", 18); // 0.5% max fee - - const adjustSpell = { - connector: helpers.LIQUITY_CONNECTOR, - method: "adjust", - args: [ - maxFeePercentage, - depositAmount, - withdrawAmount, - borrowAmount, - repayAmount, - upperHint, - lowerHint, - [0, 0, 0, 0], - [0, 0, 0, 0], - ], - }; - - // Adjust Trove by depositing ETH and borrowing LUSD - await dsa - .connect(userWallet) - .cast(...encodeSpells([adjustSpell]), userWallet.address, { - value: depositAmount, - gasLimit: helpers.MAX_GAS, - }); - - const troveCollateral = await liquity.troveManager.getTroveColl( - dsa.address - ); - const troveDebt = await liquity.troveManager.getTroveDebt( - dsa.address - ); - const expectedTroveColl = troveCollateralBefore.add(depositAmount); - const expectedTroveDebt = troveDebtBefore.add(borrowAmount); - - expect( - troveCollateral, - `Trove collateral should have increased by ${depositAmount} ETH` - ).to.eq(expectedTroveColl); - - expect( - troveDebt, - `Trove debt should have increased by at least ${borrowAmount} ETH` - ).to.gte(expectedTroveDebt); - }); - - it("adjusts a Trove: withdraw ETH and repay LUSD", async () => { - // Create a dummy Trove - await helpers.createDsaTrove(dsa, userWallet, liquity); - - const troveCollateralBefore = await liquity.troveManager.getTroveColl( - dsa.address - ); - const troveDebtBefore = await liquity.troveManager.getTroveDebt( - dsa.address - ); - const depositAmount = 0; - const borrowAmount = 0; - const withdrawAmount = ethers.utils.parseEther("1"); // 1 ETH; - const repayAmount = ethers.utils.parseUnits("10", 18); // 10 LUSD; - const { upperHint, lowerHint } = await helpers.getTroveInsertionHints( - troveCollateralBefore.sub(withdrawAmount), - troveDebtBefore.sub(repayAmount), - liquity - ); - const maxFeePercentage = ethers.utils.parseUnits("0.5", 18); // 0.5% max fee - - const adjustSpell = { - connector: helpers.LIQUITY_CONNECTOR, - method: "adjust", - args: [ - maxFeePercentage, - depositAmount, - withdrawAmount, - borrowAmount, - repayAmount, - upperHint, - lowerHint, - [0, 0, 0, 0], - [0, 0, 0, 0], - ], - }; - - // Adjust Trove by withdrawing ETH and repaying LUSD - await dsa - .connect(userWallet) - .cast(...encodeSpells([adjustSpell]), userWallet.address, { - value: depositAmount, - gasLimit: helpers.MAX_GAS, - }); - - const troveCollateral = await liquity.troveManager.getTroveColl( - dsa.address - ); - const troveDebt = await liquity.troveManager.getTroveDebt( - dsa.address - ); - const expectedTroveColl = troveCollateralBefore.sub(withdrawAmount); - const expectedTroveDebt = troveDebtBefore.sub(repayAmount); - - expect( - troveCollateral, - `Trove collateral should have increased by ${depositAmount} ETH` - ).to.eq(expectedTroveColl); - - expect( - troveDebt, - `Trove debt should have decreased by at least ${repayAmount} LUSD` - ).to.gte(expectedTroveDebt); - }); - - it("adjusts a Trove: deposit ETH and repay LUSD using previous spells", async () => { - // Create a dummy Trove - await helpers.createDsaTrove(dsa, userWallet, liquity); - - const troveCollateralBefore = await liquity.troveManager.getTroveColl( - dsa.address - ); - const troveDebtBefore = await liquity.troveManager.getTroveDebt( - dsa.address - ); - const depositAmount = ethers.utils.parseEther("1"); // 1 ETH - const borrowAmount = 0; - const withdrawAmount = 0; - const repayAmount = ethers.utils.parseUnits("10", 18); // 10 lUSD - const upperHint = ethers.constants.AddressZero; - const lowerHint = ethers.constants.AddressZero; - const maxFeePercentage = ethers.utils.parseUnits("0.5", 18); // 0.5% max fee - - const ethDepositId = 1; - const lusdRepayId = 2; - - const depositEthSpell = { - connector: helpers.INSTADAPP_BASIC_V1_CONNECTOR, - method: "deposit", - args: [helpers.ETH_ADDRESS, depositAmount, 0, ethDepositId], - }; - - const depositLusdSpell = { - connector: helpers.INSTADAPP_BASIC_V1_CONNECTOR, - method: "deposit", - args: [liquity.lusdToken.address, repayAmount, 0, lusdRepayId], - }; - - const adjustSpell = { - connector: helpers.LIQUITY_CONNECTOR, - method: "adjust", - args: [ - maxFeePercentage, - 0, // Deposit amount comes from a previous spell's storage slot - withdrawAmount, - borrowAmount, - 0, // Repay amount comes from a previous spell's storage slot - upperHint, - lowerHint, - [ethDepositId, 0, 0, lusdRepayId], - [0, 0, 0, 0], - ], - }; - const spells = [depositEthSpell, depositLusdSpell, adjustSpell]; - - // Send user some LUSD so they can repay - await helpers.sendToken( - liquity.lusdToken, - repayAmount, - helpers.JUSTIN_SUN_ADDRESS, - userWallet.address - ); - - // Allow DSA to spend user's LUSD - await liquity.lusdToken - .connect(userWallet) - .approve(dsa.address, repayAmount); - - // Adjust Trove by depositing ETH and repaying LUSD - await dsa - .connect(userWallet) - .cast(...encodeSpells(spells), userWallet.address, { - value: depositAmount, - gasLimit: helpers.MAX_GAS, - }); - - const troveCollateral = await liquity.troveManager.getTroveColl( - dsa.address - ); - const troveDebt = await liquity.troveManager.getTroveDebt( - dsa.address - ); - const expectedTroveColl = troveCollateralBefore.add(depositAmount); - const expectedTroveDebt = troveDebtBefore.sub(repayAmount); - - expect( - troveCollateral, - `Trove collateral should have increased by ${depositAmount} ETH` - ).to.eq(expectedTroveColl); - - expect( - troveDebt, - `Trove debt (${troveDebtBefore}) should have decreased by at least ${repayAmount} LUSD` - ).to.eq(expectedTroveDebt); - }); - - it("adjusts a Trove: withdraw ETH, borrow LUSD, and store the amounts for other spells", async () => { - // Create a dummy Trove - await helpers.createDsaTrove(dsa, userWallet, liquity); - - const userEthBalanceBefore = await ethers.provider.getBalance( - userWallet.address - ); - const userLusdBalanceBefore = await liquity.lusdToken.balanceOf( - userWallet.address - ); - - const depositAmount = 0; - const borrowAmount = ethers.utils.parseUnits("100", 18); // 100 LUSD - const withdrawAmount = ethers.utils.parseEther("1"); // 1 ETH - const repayAmount = 0; - const upperHint = ethers.constants.AddressZero; - const lowerHint = ethers.constants.AddressZero; - const maxFeePercentage = ethers.utils.parseUnits("0.5", 18); // 0.5% max fee - - const ethWithdrawId = 1; - const lusdBorrowId = 2; - - const adjustSpell = { - connector: helpers.LIQUITY_CONNECTOR, - method: "adjust", - args: [ - maxFeePercentage, - depositAmount, - withdrawAmount, - borrowAmount, - repayAmount, - upperHint, - lowerHint, - [0, 0, 0, 0], - [0, ethWithdrawId, lusdBorrowId, 0], - ], - }; - - const withdrawEthSpell = { - connector: helpers.INSTADAPP_BASIC_V1_CONNECTOR, - method: "withdraw", - args: [ - helpers.ETH_ADDRESS, - 0, - userWallet.address, - ethWithdrawId, - 0, - ], - }; - - const withdrawLusdSpell = { - connector: helpers.INSTADAPP_BASIC_V1_CONNECTOR, - method: "withdraw", - args: [ - liquity.lusdToken.address, - 0, - userWallet.address, - lusdBorrowId, - 0, - ], - }; - - const spells = [adjustSpell, withdrawEthSpell, withdrawLusdSpell]; - - // Adjust Trove by withdrawing ETH and borrowing LUSD - await dsa - .connect(userWallet) - .cast(...encodeSpells(spells), userWallet.address, { - gasLimit: helpers.MAX_GAS, - gasPrice: 0, - }); - - const userEthBalanceAfter = await ethers.provider.getBalance( - userWallet.address - ); - const userLusdBalanceAfter = await liquity.lusdToken.balanceOf( - userWallet.address - ); - expect(userEthBalanceAfter).eq( - userEthBalanceBefore.add(withdrawAmount) - ); - expect(userLusdBalanceAfter).eq( - userLusdBalanceBefore.add(borrowAmount) - ); - }); - - it("returns Instadapp event name and data", async () => { - // Create a dummy Trove - await helpers.createDsaTrove(dsa, userWallet, liquity); - - const depositAmount = ethers.utils.parseEther("1"); // 1 ETH - const borrowAmount = ethers.utils.parseUnits("500", 18); // 500 LUSD - const withdrawAmount = 0; - const repayAmount = 0; - const upperHint = ethers.constants.AddressZero; - const lowerHint = ethers.constants.AddressZero; - const maxFeePercentage = ethers.utils.parseUnits("0.5", 18); // 0.5% max fee - - const adjustSpell = { - connector: helpers.LIQUITY_CONNECTOR, - method: "adjust", - args: [ - maxFeePercentage, - depositAmount, - withdrawAmount, - borrowAmount, - repayAmount, - upperHint, - lowerHint, - [0, 0, 0, 0], - [0, 0, 0, 0], - ], - }; - - const adjustTx = await dsa - .connect(userWallet) - .cast(...encodeSpells([adjustSpell]), userWallet.address, { - value: depositAmount, - gasLimit: helpers.MAX_GAS, - }); - - const receipt = await adjustTx.wait(); - const castLogEvent = receipt.events.find((e) => e.event === "LogCast") - .args; - const expectedEventParams = ethers.utils.defaultAbiCoder.encode( - [ - "address", - "uint256", - "uint256", - "uint256", - "uint256", - "uint256", - "uint256[]", - "uint256[]", - ], - [ - dsa.address, - maxFeePercentage, - depositAmount, - withdrawAmount, - borrowAmount, - repayAmount, - [0, 0, 0, 0], - [0, 0, 0, 0], - ] - ); - expect(castLogEvent.eventNames[0]).eq( - "LogAdjust(address,uint256,uint256,uint256,uint256,uint256,uint256[],uint256[])" - ); - expect(castLogEvent.eventParams[0]).eq(expectedEventParams); - }); - }); - - describe("claimCollateralFromRedemption()", () => { - it("claims collateral from a redeemed Trove", async () => { - // Create a low collateralized Trove - const depositAmount = ethers.utils.parseEther("1.5"); - const borrowAmount = ethers.utils.parseUnits("2500", 18); - - await helpers.createDsaTrove( - dsa, - userWallet, - liquity, - depositAmount, - borrowAmount - ); - - // Redeem lots of LUSD to cause the Trove to become redeemed - const redeemAmount = ethers.utils.parseUnits("10000000", 18); - await helpers.sendToken( - liquity.lusdToken, - redeemAmount, - contracts.STABILITY_POOL_ADDRESS, - userWallet.address - ); - const { - partialRedemptionHintNicr, - firstRedemptionHint, - upperHint, - lowerHint, - } = await helpers.getRedemptionHints(redeemAmount, liquity); - const maxFeePercentage = ethers.utils.parseUnits("0.5", 18); // 0.5% max fee - - await liquity.troveManager - .connect(userWallet) - .redeemCollateral( - redeemAmount, - firstRedemptionHint, - upperHint, - lowerHint, - partialRedemptionHintNicr, - 0, - maxFeePercentage, - { - gasLimit: helpers.MAX_GAS, // permit max gas - } - ); - - const remainingEthCollateral = await liquity.collSurplus.getCollateral( - dsa.address - ); - - // Claim the remaining collateral from the redeemed Trove - const claimCollateralFromRedemptionSpell = { - connector: helpers.LIQUITY_CONNECTOR, - method: "claimCollateralFromRedemption", - args: [0], - }; - - await dsa - .connect(userWallet) - .cast( - ...encodeSpells([claimCollateralFromRedemptionSpell]), - userWallet.address - ); - - const ethBalance = await ethers.provider.getBalance(dsa.address); - - expect(ethBalance).to.eq(remainingEthCollateral); - }); - - it("returns Instadapp event name and data", async () => { - // Create a low collateralized Trove - const depositAmount = ethers.utils.parseEther("1.5"); - const borrowAmount = ethers.utils.parseUnits("2500", 18); - - await helpers.createDsaTrove( - dsa, - userWallet, - liquity, - depositAmount, - borrowAmount - ); - - // Redeem lots of LUSD to cause the Trove to become redeemed - const redeemAmount = ethers.utils.parseUnits("10000000", 18); - const setId = 0; - await helpers.sendToken( - liquity.lusdToken, - redeemAmount, - contracts.STABILITY_POOL_ADDRESS, - userWallet.address - ); - const { - partialRedemptionHintNicr, - firstRedemptionHint, - upperHint, - lowerHint, - } = await helpers.getRedemptionHints(redeemAmount, liquity); - const maxFeePercentage = ethers.utils.parseUnits("0.5", 18); // 0.5% max fee - - await liquity.troveManager - .connect(userWallet) - .redeemCollateral( - redeemAmount, - firstRedemptionHint, - upperHint, - lowerHint, - partialRedemptionHintNicr, - 0, - maxFeePercentage, - { - gasLimit: helpers.MAX_GAS, // permit max gas - } - ); - const claimAmount = await liquity.collSurplus.getCollateral( - dsa.address - ); - - const claimCollateralFromRedemptionSpell = { - connector: helpers.LIQUITY_CONNECTOR, - method: "claimCollateralFromRedemption", - args: [setId], - }; - - const claimTx = await dsa - .connect(userWallet) - .cast( - ...encodeSpells([claimCollateralFromRedemptionSpell]), - userWallet.address - ); - - const receipt = await claimTx.wait(); - const castLogEvent = receipt.events.find((e) => e.event === "LogCast") - .args; - const expectedEventParams = ethers.utils.defaultAbiCoder.encode( - ["address", "uint256", "uint256"], - [dsa.address, claimAmount, setId] - ); - expect(castLogEvent.eventNames[0]).eq( - "LogClaimCollateralFromRedemption(address,uint256,uint256)" - ); - expect(castLogEvent.eventParams[0]).eq(expectedEventParams); - }); - }); - }); - - describe("Stability Pool", () => { - describe("stabilityDeposit()", () => { - it("deposits into Stability Pool", async () => { - const amount = ethers.utils.parseUnits("100", 18); - const frontendTag = ethers.constants.AddressZero; - - await helpers.sendToken( - liquity.lusdToken, - amount, - contracts.STABILITY_POOL_ADDRESS, - dsa.address - ); - - const stabilityDepositSpell = { - connector: helpers.LIQUITY_CONNECTOR, - method: "stabilityDeposit", - args: [amount, frontendTag, 0, 0, 0, 0], - }; - - await dsa - .connect(userWallet) - .cast(...encodeSpells([stabilityDepositSpell]), userWallet.address); - - const depositedAmount = await liquity.stabilityPool.getCompoundedLUSDDeposit( - dsa.address - ); - expect(depositedAmount).to.eq(amount); - }); - - it("deposits into Stability Pool using LUSD collected from a previous spell", async () => { - const amount = ethers.utils.parseUnits("100", 18); - const frontendTag = ethers.constants.AddressZero; - - await helpers.sendToken( - liquity.lusdToken, - amount, - contracts.STABILITY_POOL_ADDRESS, - userWallet.address - ); - const lusdDepositId = 1; - - const depositLusdSpell = { - connector: helpers.INSTADAPP_BASIC_V1_CONNECTOR, - method: "deposit", - args: [liquity.lusdToken.address, amount, 0, lusdDepositId], - }; - const stabilityDepositSpell = { - connector: helpers.LIQUITY_CONNECTOR, - method: "stabilityDeposit", - args: [0, frontendTag, lusdDepositId, 0, 0, 0], - }; - const spells = [depositLusdSpell, stabilityDepositSpell]; - - // Allow DSA to spend user's LUSD - await liquity.lusdToken - .connect(userWallet) - .approve(dsa.address, amount); - - await dsa - .connect(userWallet) - .cast(...encodeSpells(spells), userWallet.address); - - const depositedAmount = await liquity.stabilityPool.getCompoundedLUSDDeposit( - dsa.address - ); - expect(depositedAmount).to.eq(amount); - }); - - it("returns Instadapp event name and data", async () => { - const amount = ethers.utils.parseUnits("100", 18); - const halfAmount = amount.div(2); - const frontendTag = ethers.constants.AddressZero; - const getDepositId = 0; - const setDepositId = 0; - const setEthGainId = 0; - const setLqtyGainId = 0; - - await helpers.sendToken( - liquity.lusdToken, - amount, - contracts.STABILITY_POOL_ADDRESS, - dsa.address - ); - - const stabilityDepositSpell = { - connector: helpers.LIQUITY_CONNECTOR, - method: "stabilityDeposit", - args: [ - halfAmount, - frontendTag, - getDepositId, - setDepositId, - setEthGainId, - setLqtyGainId, - ], - }; - - // Create a Stability deposit for this DSA - await dsa - .connect(userWallet) - .cast(...encodeSpells([stabilityDepositSpell]), userWallet.address); - - // Liquidate a Trove to cause an ETH gain - await liquity.troveManager.connect(userWallet).liquidateTroves(1, { - gasLimit: helpers.MAX_GAS, - }); - - // Fast forward in time so we have an LQTY gain - await provider.send("evm_increaseTime", [600]); - await provider.send("evm_mine"); - - // Create a Stability Pool deposit with a differen DSA so that LQTY gains can be calculated - // See: https://github.com/liquity/dev/#lqty-reward-events-and-payouts - const tempDsa = await buildDSAv2(userWallet.address); - await helpers.sendToken( - liquity.lusdToken, - amount, - contracts.STABILITY_POOL_ADDRESS, - tempDsa.address - ); - await tempDsa - .connect(userWallet) - .cast(...encodeSpells([stabilityDepositSpell]), userWallet.address); - - const ethGain = await liquity.stabilityPool.getDepositorETHGain( - dsa.address - ); - const lqtyGain = await liquity.stabilityPool.getDepositorLQTYGain( - dsa.address - ); - - // Top up the user's deposit so that we can track their ETH and LQTY gain - const depositAgainTx = await dsa - .connect(userWallet) - .cast(...encodeSpells([stabilityDepositSpell]), userWallet.address); - - const receipt = await depositAgainTx.wait(); - const castLogEvent = receipt.events.find((e) => e.event === "LogCast") - .args; - const expectedEventParams = ethers.utils.defaultAbiCoder.encode( - [ - "address", - "uint256", - "uint256", - "uint256", - "address", - "uint256", - "uint256", - "uint256", - "uint256", - ], - [ - dsa.address, - halfAmount, - ethGain, - lqtyGain, - frontendTag, - getDepositId, - setDepositId, - setEthGainId, - setLqtyGainId, - ] - ); - expect(castLogEvent.eventNames[0]).eq( - "LogStabilityDeposit(address,uint256,uint256,uint256,address,uint256,uint256,uint256,uint256)" - ); - expect(castLogEvent.eventParams[0]).eq(expectedEventParams); - }); - }); - - describe("stabilityWithdraw()", () => { - it("withdraws from Stability Pool", async () => { - // Start this test from scratch since we need to remove any liquidatable Troves withdrawing from Stability Pool - [liquity, dsa] = await helpers.resetInitialState( - userWallet.address, - contracts - ); - - // The current block number has liquidatable Troves. - // Remove them otherwise Stability Pool withdrawals are disabled - await liquity.troveManager.connect(userWallet).liquidateTroves(90, { - gasLimit: helpers.MAX_GAS, - }); - - const amount = ethers.utils.parseUnits("100", 18); - const frontendTag = ethers.constants.AddressZero; - - await helpers.sendToken( - liquity.lusdToken, - amount, - contracts.STABILITY_POOL_ADDRESS, - dsa.address - ); - - const stabilityDepositSpell = { - connector: helpers.LIQUITY_CONNECTOR, - method: "stabilityDeposit", - args: [amount, frontendTag, 0, 0, 0, 0], - }; - - // Withdraw half of the deposit - const stabilityWithdrawSpell = { - connector: helpers.LIQUITY_CONNECTOR, - method: "stabilityWithdraw", - args: [amount.div(2), 0, 0, 0, 0], - }; - const spells = [stabilityDepositSpell, stabilityWithdrawSpell]; - - await dsa - .connect(userWallet) - .cast(...encodeSpells(spells), userWallet.address); - - const depositedAmount = await liquity.stabilityPool.getCompoundedLUSDDeposit( - dsa.address - ); - const dsaLusdBalance = await liquity.lusdToken.balanceOf(dsa.address); - - expect(depositedAmount).to.eq(amount.div(2)); - expect(dsaLusdBalance).to.eq(amount.div(2)); - }); - - it("withdraws from Stability Pool and stores the LUSD for other spells", async () => { - // Start this test from scratch since we need to remove any liquidatable Troves withdrawing from Stability Pool - [liquity, dsa] = await helpers.resetInitialState( - userWallet.address, - contracts - ); - - // The current block number has liquidatable Troves. - // Remove them otherwise Stability Pool withdrawals are disabled - await liquity.troveManager.connect(userWallet).liquidateTroves(90, { - gasLimit: helpers.MAX_GAS, - }); - const amount = ethers.utils.parseUnits("100", 18); - const frontendTag = ethers.constants.AddressZero; - const withdrawId = 1; - - await helpers.sendToken( - liquity.lusdToken, - amount, - contracts.STABILITY_POOL_ADDRESS, - dsa.address - ); - - const stabilityDepositSpell = { - connector: helpers.LIQUITY_CONNECTOR, - method: "stabilityDeposit", - args: [amount, frontendTag, 0, 0, 0, 0], - }; - - // Withdraw half of the deposit - const stabilityWithdrawSpell = { - connector: helpers.LIQUITY_CONNECTOR, - method: "stabilityWithdraw", - args: [amount.div(2), 0, 0, 0, withdrawId], - }; - - const withdrawLusdSpell = { - connector: helpers.INSTADAPP_BASIC_V1_CONNECTOR, - method: "withdraw", - args: [ - liquity.lusdToken.address, - 0, - userWallet.address, - withdrawId, - 0, - ], - }; - - const spells = [ - stabilityDepositSpell, - stabilityWithdrawSpell, - withdrawLusdSpell, - ]; - - await dsa - .connect(userWallet) - .cast(...encodeSpells(spells), userWallet.address); - - const depositedAmount = await liquity.stabilityPool.getCompoundedLUSDDeposit( - dsa.address - ); - const walletLusdBalance = await liquity.lusdToken.balanceOf( - dsa.address - ); - - expect(depositedAmount).to.eq(amount.div(2)); - expect(walletLusdBalance).to.eq(amount.div(2)); - }); - - it("returns Instadapp event name and data", async () => { - // Start this test from scratch since we need to remove any liquidatable Troves withdrawing from Stability Pool - [liquity, dsa] = await helpers.resetInitialState( - userWallet.address, - contracts - ); - - const amount = ethers.utils.parseUnits("100", 18); - const frontendTag = ethers.constants.AddressZero; - - await helpers.sendToken( - liquity.lusdToken, - amount, - contracts.STABILITY_POOL_ADDRESS, - dsa.address - ); - - const stabilityDepositSpell = { - connector: helpers.LIQUITY_CONNECTOR, - method: "stabilityDeposit", - args: [amount, frontendTag, 0, 0, 0, 0], - }; - - // Withdraw half of the deposit - const withdrawAmount = amount.div(2); - const getWithdrawId = 0; - const setWithdrawId = 0; - const setEthGainId = 0; - const setLqtyGainId = 0; - - // Create a Stability Pool deposit - await dsa - .connect(userWallet) - .cast(...encodeSpells([stabilityDepositSpell]), userWallet.address); - - // The current block number has liquidatable Troves. - // Remove them otherwise Stability Pool withdrawals are disabled - await liquity.troveManager.connect(userWallet).liquidateTroves(90, { - gasLimit: helpers.MAX_GAS, - }); - - // Fast forward in time so we have an LQTY gain - await provider.send("evm_increaseTime", [600]); - await provider.send("evm_mine"); - - // Create another Stability Pool deposit so that LQTY gains are realized - // See: https://github.com/liquity/dev/#lqty-reward-events-and-payouts - const tempDsa = await buildDSAv2(userWallet.address); - await helpers.sendToken( - liquity.lusdToken, - amount, - contracts.STABILITY_POOL_ADDRESS, - tempDsa.address - ); - await tempDsa - .connect(userWallet) - .cast(...encodeSpells([stabilityDepositSpell]), userWallet.address); - - const ethGain = await liquity.stabilityPool.getDepositorETHGain( - dsa.address - ); - const lqtyGain = await liquity.stabilityPool.getDepositorLQTYGain( - dsa.address - ); - - const stabilityWithdrawSpell = { - connector: helpers.LIQUITY_CONNECTOR, - method: "stabilityWithdraw", - args: [ - withdrawAmount, - getWithdrawId, - setWithdrawId, - setEthGainId, - setLqtyGainId, - ], - }; - - const withdrawTx = await dsa - .connect(userWallet) - .cast( - ...encodeSpells([stabilityWithdrawSpell]), - userWallet.address - ); - - const receipt = await withdrawTx.wait(); - const castLogEvent = receipt.events.find((e) => e.event === "LogCast") - .args; - const expectedEventParams = ethers.utils.defaultAbiCoder.encode( - [ - "address", - "uint256", - "uint256", - "uint256", - "uint256", - "uint256", - "uint256", - "uint256", - ], - [ - dsa.address, - withdrawAmount, - ethGain, - lqtyGain, - getWithdrawId, - setWithdrawId, - setEthGainId, - setLqtyGainId, - ] - ); - expect(castLogEvent.eventNames[0]).eq( - "LogStabilityWithdraw(address,uint256,uint256,uint256,uint256,uint256,uint256,uint256)" - ); - expect(castLogEvent.eventParams[0]).eq(expectedEventParams); - }); - }); - - describe("stabilityMoveEthGainToTrove()", () => { - beforeEach(async () => { - // Start these test from fresh so that we definitely have a liquidatable Trove within this block - [liquity, dsa] = await helpers.resetInitialState( - userWallet.address, - contracts - ); - }); - - it("moves ETH gain from Stability Pool to Trove", async () => { - // Create a DSA owned Trove to capture ETH liquidation gains - // Create a dummy Trove - await helpers.createDsaTrove(dsa, userWallet, liquity); - const troveCollateralBefore = await liquity.troveManager.getTroveColl( - dsa.address - ); - - // Create a Stability Deposit using the Trove's borrowed LUSD - const amount = ethers.utils.parseUnits("100", 18); - const frontendTag = ethers.constants.AddressZero; - const stabilityDepositSpell = { - connector: helpers.LIQUITY_CONNECTOR, - method: "stabilityDeposit", - args: [amount, frontendTag, 0, 0, 0, 0], - }; - - await dsa - .connect(userWallet) - .cast(...encodeSpells([stabilityDepositSpell]), userWallet.address); - - // Liquidate a Trove to create an ETH gain for the new DSA Trove - await liquity.troveManager - .connect(userWallet) - .liquidate(helpers.LIQUIDATABLE_TROVE_ADDRESS, { - gasLimit: helpers.MAX_GAS, // permit max gas - }); - - const ethGainFromLiquidation = await liquity.stabilityPool.getDepositorETHGain( - dsa.address - ); - - // Move ETH gain to Trove - const moveEthGainSpell = { - connector: helpers.LIQUITY_CONNECTOR, - method: "stabilityMoveEthGainToTrove", - args: [ethers.constants.AddressZero, ethers.constants.AddressZero], - }; - - await dsa - .connect(userWallet) - .cast(...encodeSpells([moveEthGainSpell]), userWallet.address); - - const ethGainAfterMove = await liquity.stabilityPool.getDepositorETHGain( - dsa.address - ); - const troveCollateral = await liquity.troveManager.getTroveColl( - dsa.address - ); - const expectedTroveCollateral = troveCollateralBefore.add( - ethGainFromLiquidation - ); - expect(ethGainAfterMove).to.eq(0); - expect(troveCollateral).to.eq(expectedTroveCollateral); - }); - - it("returns Instadapp event name and data", async () => { - // Create a DSA owned Trove to capture ETH liquidation gains - // Create a dummy Trove - await helpers.createDsaTrove(dsa, userWallet, liquity); - - // Create a Stability Deposit using the Trove's borrowed LUSD - const amount = ethers.utils.parseUnits("100", 18); - const frontendTag = ethers.constants.AddressZero; - const stabilityDepositSpell = { - connector: helpers.LIQUITY_CONNECTOR, - method: "stabilityDeposit", - args: [amount, frontendTag, 0, 0, 0, 0], - }; - - await dsa - .connect(userWallet) - .cast(...encodeSpells([stabilityDepositSpell]), userWallet.address); - - // Liquidate a Trove to create an ETH gain for the new DSA Trove - await liquity.troveManager - .connect(userWallet) - .liquidate(helpers.LIQUIDATABLE_TROVE_ADDRESS, { - gasLimit: helpers.MAX_GAS, // permit max gas - }); - - const ethGainFromLiquidation = await liquity.stabilityPool.getDepositorETHGain( - dsa.address - ); - - // Move ETH gain to Trove - const moveEthGainSpell = { - connector: helpers.LIQUITY_CONNECTOR, - method: "stabilityMoveEthGainToTrove", - args: [ethers.constants.AddressZero, ethers.constants.AddressZero], - }; - - const moveEthGainTx = await dsa - .connect(userWallet) - .cast(...encodeSpells([moveEthGainSpell]), userWallet.address); - - const receipt = await moveEthGainTx.wait(); - - const castLogEvent = receipt.events.find((e) => e.event === "LogCast") - .args; - const expectedEventParams = ethers.utils.defaultAbiCoder.encode( - ["address", "uint256"], - [dsa.address, ethGainFromLiquidation] - ); - expect(castLogEvent.eventNames[0]).eq( - "LogStabilityMoveEthGainToTrove(address,uint256)" - ); - expect(castLogEvent.eventParams[0]).eq(expectedEventParams); - }); - }); - }); - - describe("Staking", () => { - describe("stake()", () => { - it("stakes LQTY", async () => { - const totalStakingBalanceBefore = await liquity.lqtyToken.balanceOf( - contracts.STAKING_ADDRESS - ); - - const amount = ethers.utils.parseUnits("1", 18); - await helpers.sendToken( - liquity.lqtyToken, - amount, - helpers.JUSTIN_SUN_ADDRESS, - dsa.address - ); - - const stakeSpell = { - connector: helpers.LIQUITY_CONNECTOR, - method: "stake", - args: [amount, 0, 0, 0, 0], - }; - - await dsa - .connect(userWallet) - .cast(...encodeSpells([stakeSpell]), userWallet.address); - - const lqtyBalance = await liquity.lqtyToken.balanceOf(dsa.address); - expect(lqtyBalance).to.eq(0); - - const totalStakingBalance = await liquity.lqtyToken.balanceOf( - contracts.STAKING_ADDRESS - ); - expect(totalStakingBalance).to.eq( - totalStakingBalanceBefore.add(amount) - ); - }); - - it("stakes LQTY using LQTY obtained from a previous spell", async () => { - const totalStakingBalanceBefore = await liquity.lqtyToken.balanceOf( - contracts.STAKING_ADDRESS - ); - - const amount = ethers.utils.parseUnits("1", 18); - await helpers.sendToken( - liquity.lqtyToken, - amount, - helpers.JUSTIN_SUN_ADDRESS, - userWallet.address - ); - - const lqtyDepositId = 1; - const depositSpell = { - connector: helpers.INSTADAPP_BASIC_V1_CONNECTOR, - method: "deposit", - args: [liquity.lqtyToken.address, amount, 0, lqtyDepositId], - }; - const stakeSpell = { - connector: helpers.LIQUITY_CONNECTOR, - method: "stake", - args: [0, lqtyDepositId, 0, 0, 0], - }; - const spells = [depositSpell, stakeSpell]; - - // Allow DSA to spend user's LQTY - await liquity.lqtyToken - .connect(userWallet) - .approve(dsa.address, amount); - - await dsa - .connect(userWallet) - .cast(...encodeSpells(spells), userWallet.address); - - const lqtyBalance = await liquity.lqtyToken.balanceOf(dsa.address); - expect(lqtyBalance).to.eq(0); - - const totalStakingBalance = await liquity.lqtyToken.balanceOf( - contracts.STAKING_ADDRESS - ); - expect(totalStakingBalance).to.eq( - totalStakingBalanceBefore.add(amount) - ); - }); - - it("returns Instadapp event name and data", async () => { - const amount = ethers.utils.parseUnits("1", 18); - await helpers.sendToken( - liquity.lqtyToken, - amount, - helpers.JUSTIN_SUN_ADDRESS, - dsa.address - ); - - const getStakeId = 0; - const setStakeId = 0; - const setEthGainId = 0; - const setLusdGainId = 0; - const stakeSpell = { - connector: helpers.LIQUITY_CONNECTOR, - method: "stake", - args: [amount, getStakeId, setStakeId, setEthGainId, setLusdGainId], - }; - - const stakeTx = await dsa - .connect(userWallet) - .cast(...encodeSpells([stakeSpell]), userWallet.address); - - const receipt = await stakeTx.wait(); - - const castLogEvent = receipt.events.find((e) => e.event === "LogCast") - .args; - const expectedEventParams = ethers.utils.defaultAbiCoder.encode( - ["address", "uint256", "uint256", "uint256", "uint256", "uint256"], - [ - dsa.address, - amount, - getStakeId, - setStakeId, - setEthGainId, - setLusdGainId, - ] - ); - expect(castLogEvent.eventNames[0]).eq( - "LogStake(address,uint256,uint256,uint256,uint256,uint256)" - ); - expect(castLogEvent.eventParams[0]).eq(expectedEventParams); - }); - }); - - describe("unstake()", () => { - it("unstakes LQTY", async () => { - const amount = ethers.utils.parseUnits("1", 18); - await helpers.sendToken( - liquity.lqtyToken, - amount, - helpers.JUSTIN_SUN_ADDRESS, - dsa.address - ); - - const stakeSpell = { - connector: helpers.LIQUITY_CONNECTOR, - method: "stake", - args: [amount, 0, 0, 0, 0], - }; - - await dsa - .connect(userWallet) - .cast(...encodeSpells([stakeSpell]), userWallet.address); - - const totalStakingBalanceBefore = await liquity.lqtyToken.balanceOf( - contracts.STAKING_ADDRESS - ); - const unstakeSpell = { - connector: helpers.LIQUITY_CONNECTOR, - method: "unstake", - args: [amount, 0, 0, 0, 0], - }; - - await dsa - .connect(userWallet) - .cast(...encodeSpells([unstakeSpell]), userWallet.address); - - const lqtyBalance = await liquity.lqtyToken.balanceOf(dsa.address); - expect(lqtyBalance).to.eq(amount); - - const totalStakingBalance = await liquity.lqtyToken.balanceOf( - contracts.STAKING_ADDRESS - ); - expect(totalStakingBalance).to.eq( - totalStakingBalanceBefore.sub(amount) - ); - }); - - it("unstakes LQTY and stores the LQTY for other spells", async () => { - const amount = ethers.utils.parseUnits("1", 18); - await helpers.sendToken( - liquity.lqtyToken, - amount, - helpers.JUSTIN_SUN_ADDRESS, - dsa.address - ); - - const stakeSpell = { - connector: helpers.LIQUITY_CONNECTOR, - method: "stake", - args: [amount, 0, 0, 0, 0], - }; - - await dsa - .connect(userWallet) - .cast(...encodeSpells([stakeSpell]), userWallet.address); - - const totalStakingBalanceBefore = await liquity.lqtyToken.balanceOf( - contracts.STAKING_ADDRESS - ); - const withdrawId = 1; - const unstakeSpell = { - connector: helpers.LIQUITY_CONNECTOR, - method: "unstake", - args: [amount, 0, withdrawId, 0, 0], - }; - - const withdrawLqtySpell = { - connector: helpers.INSTADAPP_BASIC_V1_CONNECTOR, - method: "withdraw", - args: [ - liquity.lqtyToken.address, - 0, - userWallet.address, - withdrawId, - 0, - ], - }; - const spells = [unstakeSpell, withdrawLqtySpell]; - await dsa - .connect(userWallet) - .cast(...encodeSpells(spells), userWallet.address); - - const lqtyBalance = await liquity.lqtyToken.balanceOf(dsa.address); - const totalStakingBalance = await liquity.lqtyToken.balanceOf( - contracts.STAKING_ADDRESS - ); - const userLqtyBalance = await liquity.lqtyToken.balanceOf( - userWallet.address - ); - expect(lqtyBalance).to.eq(0); - expect(totalStakingBalance).to.eq( - totalStakingBalanceBefore.sub(amount) - ); - expect(userLqtyBalance).to.eq(amount); - }); - - it("returns Instadapp event name and data", async () => { - const amount = ethers.utils.parseUnits("1", 18); - await helpers.sendToken( - liquity.lqtyToken, - amount, - helpers.JUSTIN_SUN_ADDRESS, - dsa.address - ); - - const stakeSpell = { - connector: helpers.LIQUITY_CONNECTOR, - method: "stake", - args: [amount, 0, 0, 0, 0], - }; - - await dsa - .connect(userWallet) - .cast(...encodeSpells([stakeSpell]), userWallet.address); - - const getUnstakeId = 0; - const setUnstakeId = 0; - const setEthGainId = 0; - const setLusdGainId = 0; - const unstakeSpell = { - connector: helpers.LIQUITY_CONNECTOR, - method: "unstake", - args: [ - amount, - getUnstakeId, - setUnstakeId, - setEthGainId, - setLusdGainId, - ], - }; - - const unstakeTx = await dsa - .connect(userWallet) - .cast(...encodeSpells([unstakeSpell]), userWallet.address); - - const receipt = await unstakeTx.wait(); - - const castLogEvent = receipt.events.find((e) => e.event === "LogCast") - .args; - const expectedEventParams = ethers.utils.defaultAbiCoder.encode( - ["address", "uint256", "uint256", "uint256", "uint256", "uint256"], - [ - dsa.address, - amount, - getUnstakeId, - setUnstakeId, - setEthGainId, - setLusdGainId, - ] - ); - expect(castLogEvent.eventNames[0]).eq( - "LogUnstake(address,uint256,uint256,uint256,uint256,uint256)" - ); - expect(castLogEvent.eventParams[0]).eq(expectedEventParams); - }); - }); - - describe("claimStakingGains()", () => { - it("claims gains from staking", async () => { - const stakerDsa = await buildDSAv2(userWallet.address); - const amount = ethers.utils.parseUnits("1000", 18); // 1000 LQTY - - // Stake lots of LQTY - await helpers.sendToken( - liquity.lqtyToken, - amount, - helpers.JUSTIN_SUN_ADDRESS, - stakerDsa.address - ); - const stakeSpell = { - connector: helpers.LIQUITY_CONNECTOR, - method: "stake", - args: [amount, 0, 0, 0, 0], - }; - await stakerDsa - .connect(userWallet) - .cast(...encodeSpells([stakeSpell]), userWallet.address); - - // Open a Trove to cause an ETH issuance gain for stakers - await helpers.createDsaTrove(dsa, userWallet, liquity); - - // Redeem some ETH to cause an LUSD redemption gain for stakers - await helpers.redeem( - ethers.utils.parseUnits("1000", 18), - contracts.STABILITY_POOL_ADDRESS, - userWallet, - liquity - ); - - const setEthGainId = 0; - const setLusdGainId = 0; - const ethGain = await liquity.staking.getPendingETHGain( - stakerDsa.address - ); - const lusdGain = await liquity.staking.getPendingLUSDGain( - stakerDsa.address - ); - - const claimStakingGainsSpell = { - connector: helpers.LIQUITY_CONNECTOR, - method: "claimStakingGains", - args: [setEthGainId, setLusdGainId], - }; - - const ethBalanceBefore = await ethers.provider.getBalance( - stakerDsa.address - ); - - // Claim gains - await stakerDsa - .connect(userWallet) - .cast( - ...encodeSpells([claimStakingGainsSpell]), - userWallet.address - ); - - const ethBalanceAfter = await ethers.provider.getBalance( - stakerDsa.address - ); - const lusdBalanceAfter = await liquity.lusdToken.balanceOf( - stakerDsa.address - ); - expect(ethBalanceAfter).to.eq(ethBalanceBefore.add(ethGain)); - expect(lusdBalanceAfter).to.eq(lusdGain); - }); - - it("claims gains from staking and stores them for other spells", async () => { - const stakerDsa = await buildDSAv2(userWallet.address); - const amount = ethers.utils.parseUnits("1000", 18); // 1000 LQTY - - // Stake lots of LQTY - await helpers.sendToken( - liquity.lqtyToken, - amount, - helpers.JUSTIN_SUN_ADDRESS, - stakerDsa.address - ); - const stakeSpell = { - connector: helpers.LIQUITY_CONNECTOR, - method: "stake", - args: [amount, 0, 0, 0, 0], - }; - await stakerDsa - .connect(userWallet) - .cast(...encodeSpells([stakeSpell]), userWallet.address); - - // Open a Trove to cause an ETH issuance gain for stakers - await helpers.createDsaTrove(dsa, userWallet, liquity); - - // Redeem some ETH to cause an LUSD redemption gain for stakers - await helpers.redeem( - ethers.utils.parseUnits("1000", 18), - contracts.STABILITY_POOL_ADDRESS, - userWallet, - liquity - ); - - const ethGain = await liquity.staking.getPendingETHGain( - stakerDsa.address - ); - const lusdGain = await liquity.staking.getPendingLUSDGain( - stakerDsa.address - ); - const lusdBalanceBefore = await liquity.lusdToken.balanceOf( - userWallet.address - ); - const ethBalanceBefore = await ethers.provider.getBalance( - userWallet.address - ); - const ethGainId = 111; - const lusdGainId = 222; - - const claimStakingGainsSpell = { - connector: helpers.LIQUITY_CONNECTOR, - method: "claimStakingGains", - args: [ethGainId, lusdGainId], - }; - - const withdrawEthSpell = { - connector: helpers.INSTADAPP_BASIC_V1_CONNECTOR, - method: "withdraw", - args: [helpers.ETH_ADDRESS, 0, userWallet.address, ethGainId, 0], - }; - - const withdrawLusdSpell = { - connector: helpers.INSTADAPP_BASIC_V1_CONNECTOR, - method: "withdraw", - args: [ - liquity.lusdToken.address, - 0, - userWallet.address, - lusdGainId, - 0, - ], - }; - - const spells = [ - claimStakingGainsSpell, - withdrawEthSpell, - withdrawLusdSpell, - ]; - - // Claim gains - await stakerDsa - .connect(userWallet) - .cast(...encodeSpells(spells), userWallet.address, { - gasPrice: 0, - }); - - const ethBalanceAfter = await ethers.provider.getBalance( - userWallet.address - ); - const lusdBalanceAfter = await liquity.lusdToken.balanceOf( - userWallet.address - ); - - expect( - ethBalanceAfter, - "User's ETH balance should have increased by the issuance gain from staking" - ).to.eq(ethBalanceBefore.add(ethGain)); - expect( - lusdBalanceAfter, - "User's LUSD balance should have increased by the redemption gain from staking" - ).to.eq(lusdBalanceBefore.add(lusdGain)); - }); - - it("returns Instadapp event name and data", async () => { - const stakerDsa = await buildDSAv2(userWallet.address); - const amount = ethers.utils.parseUnits("1000", 18); // 1000 LQTY - - // Stake lots of LQTY - await helpers.sendToken( - liquity.lqtyToken, - amount, - helpers.JUSTIN_SUN_ADDRESS, - stakerDsa.address - ); - const stakeSpell = { - connector: helpers.LIQUITY_CONNECTOR, - method: "stake", - args: [amount, 0, 0, 0, 0], - }; - await stakerDsa - .connect(userWallet) - .cast(...encodeSpells([stakeSpell]), userWallet.address); - - // Open a Trove to cause an ETH issuance gain for stakers - await helpers.createDsaTrove(dsa, userWallet, liquity); - - // Redeem some ETH to cause an LUSD redemption gain for stakers - await helpers.redeem( - ethers.utils.parseUnits("1000", 18), - contracts.STABILITY_POOL_ADDRESS, - userWallet, - liquity - ); - - const setEthGainId = 0; - const setLusdGainId = 0; - const ethGain = await liquity.staking.getPendingETHGain( - stakerDsa.address - ); - const lusdGain = await liquity.staking.getPendingLUSDGain( - stakerDsa.address - ); - - const claimStakingGainsSpell = { - connector: helpers.LIQUITY_CONNECTOR, - method: "claimStakingGains", - args: [setEthGainId, setLusdGainId], - }; - - // Claim gains - const claimGainsTx = await stakerDsa - .connect(userWallet) - .cast( - ...encodeSpells([claimStakingGainsSpell]), - userWallet.address - ); - - const receipt = await claimGainsTx.wait(); - - const castLogEvent = receipt.events.find((e) => e.event === "LogCast") - .args; - const expectedEventParams = ethers.utils.defaultAbiCoder.encode( - ["address", "uint256", "uint256", "uint256", "uint256"], - [stakerDsa.address, ethGain, lusdGain, setEthGainId, setLusdGainId] - ); - expect(castLogEvent.eventNames[0]).eq( - "LogClaimStakingGains(address,uint256,uint256,uint256,uint256)" - ); - expect(castLogEvent.eventParams[0]).eq(expectedEventParams); - }); - }); - }); - }); -}); +// import hre from "hardhat"; +// import { expect } from "chai"; + +// // Instadapp deployment and testing helpers +// import { buildDSAv2 } from "../../../scripts/tests/buildDSAv2"; +// import { encodeSpells } from "../../../scripts/tests/encodeSpells.js"; + +// // Liquity smart contracts +// import contracts from "./liquity.contracts"; + +// // Liquity helpers +// import helpers from "./liquity.helpers"; + +// describe("Liquity", () => { +// const { waffle, ethers } = hre; +// const { provider } = waffle; + +// // Waffle test account 0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266 (holds 1000 ETH) +// const userWallet = provider.getWallets()[0]; +// let dsa = null; +// let liquity = null; + +// before(async () => { +// await hre.network.provider.request({ +// method: "hardhat_reset", +// params: [ +// { +// forking: { +// jsonRpcUrl: hre.config.networks.hardhat.forking.url, +// blockNumber: 13300000, +// }, +// }, +// ], +// }); +// liquity = await helpers.deployAndConnect(contracts, true); +// expect(liquity.troveManager.address).to.exist; +// expect(liquity.borrowerOperations.address).to.exist; +// expect(liquity.stabilityPool.address).to.exist; +// expect(liquity.lusdToken.address).to.exist; +// expect(liquity.lqtyToken.address).to.exist; +// expect(liquity.activePool.address).to.exist; +// expect(liquity.priceFeed.address).to.exist; +// expect(liquity.hintHelpers.address).to.exist; +// expect(liquity.sortedTroves.address).to.exist; +// expect(liquity.staking.address).to.exist; +// }); + +// beforeEach(async () => { +// // Build a new DSA before each test so we start each test from the same default state +// dsa = await buildDSAv2(userWallet.address); +// expect(dsa.address).to.exist; +// }); + +// describe("Main (Connector)", () => { +// describe("Trove", () => { +// describe("open()", () => { +// it("opens a Trove", async () => { +// const depositAmount = ethers.utils.parseEther("5"); // 5 ETH +// const borrowAmount = ethers.utils.parseUnits("2000", 18); // 2000 LUSD +// const maxFeePercentage = ethers.utils.parseUnits("0.5", 18); // 0.5% max fee +// const upperHint = ethers.constants.AddressZero; +// const lowerHint = ethers.constants.AddressZero; +// const originalUserBalance = await ethers.provider.getBalance( +// userWallet.address +// ); +// const originalDsaBalance = await ethers.provider.getBalance( +// dsa.address +// ); + +// const openTroveSpell = { +// connector: helpers.LIQUITY_CONNECTOR, +// method: "open", +// args: [ +// depositAmount, +// maxFeePercentage, +// borrowAmount, +// upperHint, +// lowerHint, +// [0, 0], +// [0, 0], +// ], +// }; + +// await dsa +// .connect(userWallet) +// .cast(...encodeSpells([openTroveSpell]), userWallet.address, { +// value: depositAmount, +// gasPrice: 0, +// }); + +// const userBalance = await ethers.provider.getBalance( +// userWallet.address +// ); +// const dsaEthBalance = await ethers.provider.getBalance(dsa.address); +// const dsaLusdBalance = await liquity.lusdToken.balanceOf(dsa.address); +// const troveDebt = await liquity.troveManager.getTroveDebt( +// dsa.address +// ); +// const troveCollateral = await liquity.troveManager.getTroveColl( +// dsa.address +// ); + +// expect(userBalance).eq( +// originalUserBalance.sub(depositAmount), +// "User's Ether balance should decrease by the amount they deposited" +// ); + +// expect(dsaEthBalance).to.eq( +// originalDsaBalance, +// "User's DSA account Ether should not change after borrowing" +// ); + +// expect( +// dsaLusdBalance, +// "DSA account should now hold the amount the user borrowed" +// ).to.eq(borrowAmount); + +// expect(troveDebt).to.gt( +// borrowAmount, +// "Trove debt should equal the borrowed amount plus fee" +// ); + +// expect(troveCollateral).to.eq( +// depositAmount, +// "Trove collateral should equal the deposited amount" +// ); +// }); + +// it("opens a Trove using ETH collected from a previous spell", async () => { +// const depositAmount = ethers.utils.parseEther("5"); // 5 ETH +// const borrowAmount = ethers.utils.parseUnits("2000", 18); // 2000 LUSD +// const maxFeePercentage = ethers.utils.parseUnits("0.5", 18); // 0.5% max fee +// const upperHint = ethers.constants.AddressZero; +// const lowerHint = ethers.constants.AddressZero; +// const originalUserBalance = await ethers.provider.getBalance( +// userWallet.address +// ); +// const originalDsaBalance = await ethers.provider.getBalance( +// dsa.address +// ); +// const depositId = 1; // Choose an ID to store and retrieve the deposited ETH + +// const depositEthSpell = { +// connector: helpers.INSTADAPP_BASIC_V1_CONNECTOR, +// method: "deposit", +// args: [helpers.ETH_ADDRESS, depositAmount, 0, depositId], +// }; + +// const openTroveSpell = { +// connector: helpers.LIQUITY_CONNECTOR, +// method: "open", +// args: [ +// 0, // When pulling ETH from a previous spell it doesn't matter what deposit value we put in this param +// maxFeePercentage, +// borrowAmount, +// upperHint, +// lowerHint, +// [depositId, 0], +// [0, 0], +// ], +// }; + +// const spells = [depositEthSpell, openTroveSpell]; +// await dsa +// .connect(userWallet) +// .cast(...encodeSpells(spells), userWallet.address, { +// value: depositAmount, +// gasPrice: 0, +// }); + +// const userBalance = await ethers.provider.getBalance( +// userWallet.address +// ); +// const dsaEthBalance = await ethers.provider.getBalance(dsa.address); +// const dsaLusdBalance = await liquity.lusdToken.balanceOf(dsa.address); +// const troveDebt = await liquity.troveManager.getTroveDebt( +// dsa.address +// ); +// const troveCollateral = await liquity.troveManager.getTroveColl( +// dsa.address +// ); + +// expect(userBalance).eq( +// originalUserBalance.sub(depositAmount), +// "User's Ether balance should decrease by the amount they deposited" +// ); + +// expect(dsaEthBalance).to.eq( +// originalDsaBalance, +// "DSA balance should not change" +// ); + +// expect( +// dsaLusdBalance, +// "DSA account should now hold the amount the user borrowed" +// ).to.eq(borrowAmount); + +// expect(troveDebt).to.gt( +// borrowAmount, +// "Trove debt should equal the borrowed amount plus fee" +// ); + +// expect(troveCollateral).to.eq( +// depositAmount, +// "Trove collateral should equal the deposited amount" +// ); +// }); + +// it("opens a Trove and stores the debt for other spells to use", async () => { +// const depositAmount = ethers.utils.parseEther("5"); // 5 ETH +// const borrowAmount = ethers.utils.parseUnits("2000", 18); // 2000 LUSD +// const maxFeePercentage = ethers.utils.parseUnits("0.5", 18); // 0.5% max fee +// const upperHint = ethers.constants.AddressZero; +// const lowerHint = ethers.constants.AddressZero; +// const originalUserBalance = await ethers.provider.getBalance( +// userWallet.address +// ); +// const originalDsaBalance = await ethers.provider.getBalance( +// dsa.address +// ); +// const borrowId = 1; + +// const openTroveSpell = { +// connector: helpers.LIQUITY_CONNECTOR, +// method: "open", +// args: [ +// depositAmount, +// maxFeePercentage, +// borrowAmount, +// upperHint, +// lowerHint, +// [0, 0], +// [borrowId, 0], +// ], +// }; + +// const withdrawLusdSpell = { +// connector: helpers.INSTADAPP_BASIC_V1_CONNECTOR, +// method: "withdraw", +// args: [ +// contracts.LUSD_TOKEN_ADDRESS, +// 0, // Amount comes from the previous spell's setId +// dsa.address, +// borrowId, +// 0, +// ], +// }; + +// const spells = [openTroveSpell, withdrawLusdSpell]; +// await dsa +// .connect(userWallet) +// .cast(...encodeSpells(spells), userWallet.address, { +// value: depositAmount, +// gasPrice: 0, +// }); + +// const userBalance = await ethers.provider.getBalance( +// userWallet.address +// ); +// const dsaEthBalance = await ethers.provider.getBalance(dsa.address); +// const dsaLusdBalance = await liquity.lusdToken.balanceOf(dsa.address); +// const troveDebt = await liquity.troveManager.getTroveDebt( +// dsa.address +// ); +// const troveCollateral = await liquity.troveManager.getTroveColl( +// dsa.address +// ); + +// expect(userBalance).eq( +// originalUserBalance.sub(depositAmount), +// "User's Ether balance should decrease by the amount they deposited" +// ); + +// expect(dsaEthBalance).to.eq( +// originalDsaBalance, +// "User's DSA account Ether should not change after borrowing" +// ); + +// expect( +// dsaLusdBalance, +// "DSA account should now hold the amount the user borrowed" +// ).to.eq(borrowAmount); + +// expect(troveDebt).to.gt( +// borrowAmount, +// "Trove debt should equal the borrowed amount plus fee" +// ); + +// expect(troveCollateral).to.eq( +// depositAmount, +// "Trove collateral should equal the deposited amount" +// ); +// }); + +// it("returns Instadapp event name and data", async () => { +// const depositAmount = ethers.utils.parseEther("5"); +// const borrowAmount = ethers.utils.parseUnits("2000", 18); +// const maxFeePercentage = ethers.utils.parseUnits("0.5", 18); +// const upperHint = ethers.constants.AddressZero; +// const lowerHint = ethers.constants.AddressZero; + +// const openTroveSpell = { +// connector: helpers.LIQUITY_CONNECTOR, +// method: "open", +// args: [ +// depositAmount, +// maxFeePercentage, +// borrowAmount, +// upperHint, +// lowerHint, +// [0, 0], +// [0, 0], +// ], +// }; + +// const openTx = await dsa.cast( +// ...encodeSpells([openTroveSpell]), +// userWallet.address, +// { +// value: depositAmount, +// } +// ); +// const receipt = await openTx.wait(); +// const castLogEvent = receipt.events.find((e) => e.event === "LogCast") +// .args; +// expect(castLogEvent.eventNames[0]).eq( +// "LogOpen(address,uint256,uint256,uint256,uint256[],uint256[])" +// ); +// const expectedEventParams = ethers.utils.defaultAbiCoder.encode( +// [ +// "address", +// "uint256", +// "uint256", +// "uint256", +// "uint256[]", +// "uint256[]", +// ], +// [ +// dsa.address, +// maxFeePercentage, +// depositAmount, +// borrowAmount, +// [0, 0], +// [0, 0], +// ] +// ); +// expect(castLogEvent.eventParams[0]).eq(expectedEventParams); +// }); +// }); + +// describe("close()", () => { +// it("closes a Trove", async () => { +// const depositAmount = ethers.utils.parseEther("5"); +// const borrowAmount = ethers.utils.parseUnits("2000", 18); +// // Create a dummy Trove +// await helpers.createDsaTrove( +// dsa, +// userWallet, +// liquity, +// depositAmount, +// borrowAmount +// ); + +// const troveDebtBefore = await liquity.troveManager.getTroveDebt( +// dsa.address +// ); + +// const troveCollateralBefore = await liquity.troveManager.getTroveColl( +// dsa.address +// ); + +// // Send DSA account enough LUSD (from Stability Pool) to close their Trove +// const extraLusdRequiredToCloseTrove = troveDebtBefore.sub( +// borrowAmount +// ); + +// await helpers.sendToken( +// liquity.lusdToken, +// extraLusdRequiredToCloseTrove, +// contracts.STABILITY_POOL_ADDRESS, +// dsa.address +// ); + +// const originalDsaLusdBalance = await liquity.lusdToken.balanceOf( +// dsa.address +// ); + +// expect( +// originalDsaLusdBalance, +// "DSA account should now hold the LUSD amount required to pay off the Trove debt" +// ).to.eq(troveDebtBefore); + +// const closeTroveSpell = { +// connector: helpers.LIQUITY_CONNECTOR, +// method: "close", +// args: [0], +// }; + +// await dsa +// .connect(userWallet) +// .cast(...encodeSpells([closeTroveSpell]), userWallet.address); + +// const dsaEthBalance = await ethers.provider.getBalance(dsa.address); +// const dsaLusdBalance = await liquity.lusdToken.balanceOf(dsa.address); +// const troveDebt = await liquity.troveManager.getTroveDebt( +// dsa.address +// ); +// const troveCollateral = await liquity.troveManager.getTroveColl( +// dsa.address +// ); + +// expect(troveDebt, "Trove debt should equal 0 after close").to.eq(0); + +// expect( +// troveCollateral, +// "Trove collateral should equal 0 after close" +// ).to.eq(0); + +// expect( +// dsaEthBalance, +// "DSA account should now hold the Trove's ETH collateral" +// ).to.eq(troveCollateralBefore); + +// expect( +// dsaLusdBalance, +// "DSA account should now hold the gas compensation amount of LUSD as it paid off the Trove debt" +// ).to.eq(helpers.LUSD_GAS_COMPENSATION); +// }); + +// it("closes a Trove using LUSD obtained from a previous spell", async () => { +// // Create a dummy Trove +// await helpers.createDsaTrove(dsa, userWallet, liquity); + +// const troveDebtBefore = await liquity.troveManager.getTroveDebt( +// dsa.address +// ); +// const troveCollateralBefore = await liquity.troveManager.getTroveColl( +// dsa.address +// ); + +// // Send user enough LUSD to repay the loan, we'll use a deposit and withdraw spell to obtain it +// await helpers.sendToken( +// liquity.lusdToken, +// troveDebtBefore, +// contracts.STABILITY_POOL_ADDRESS, +// userWallet.address +// ); + +// // Allow DSA to spend user's LUSD +// await liquity.lusdToken +// .connect(userWallet) +// .approve(dsa.address, troveDebtBefore); + +// // Simulate a spell which would have pulled LUSD from somewhere (e.g. Uniswap) into InstaMemory +// // In this case we're simply running a deposit spell from the user's EOA +// const depositLusdSpell = { +// connector: helpers.INSTADAPP_BASIC_V1_CONNECTOR, +// method: "deposit", +// args: [contracts.LUSD_TOKEN_ADDRESS, troveDebtBefore, 0, 0], +// }; + +// const closeTroveSpell = { +// connector: helpers.LIQUITY_CONNECTOR, +// method: "close", +// args: [0], +// }; +// const spells = [depositLusdSpell, closeTroveSpell]; + +// await dsa +// .connect(userWallet) +// .cast(...encodeSpells(spells), userWallet.address); + +// const dsaEthBalance = await ethers.provider.getBalance(dsa.address); +// const troveDebt = await liquity.troveManager.getTroveDebt( +// dsa.address +// ); +// const troveCollateral = await liquity.troveManager.getTroveColl( +// dsa.address +// ); + +// expect(troveDebt, "Trove debt should equal 0 after close").to.eq(0); + +// expect( +// troveCollateral, +// "Trove collateral should equal 0 after close" +// ).to.eq(0); + +// expect( +// dsaEthBalance, +// "DSA account should now hold the Trove's ETH collateral" +// ).to.eq(troveCollateralBefore); +// }); + +// it("closes a Trove and stores the released collateral for other spells to use", async () => { +// const depositAmount = ethers.utils.parseEther("5"); +// const borrowAmount = ethers.utils.parseUnits("2000", 18); +// // Create a dummy Trove +// await helpers.createDsaTrove( +// dsa, +// userWallet, +// liquity, +// depositAmount, +// borrowAmount +// ); + +// const troveDebtBefore = await liquity.troveManager.getTroveDebt( +// dsa.address +// ); +// const troveCollateralBefore = await liquity.troveManager.getTroveColl( +// dsa.address +// ); + +// // Send DSA account enough LUSD (from Stability Pool) to close their Trove +// const extraLusdRequiredToCloseTrove = troveDebtBefore.sub( +// borrowAmount +// ); +// await helpers.sendToken( +// liquity.lusdToken, +// extraLusdRequiredToCloseTrove, +// contracts.STABILITY_POOL_ADDRESS, +// dsa.address +// ); +// const originalDsaLusdBalance = await liquity.lusdToken.balanceOf( +// dsa.address +// ); + +// expect( +// originalDsaLusdBalance, +// "DSA account should now hold the LUSD amount required to pay off the Trove debt" +// ).to.eq(troveDebtBefore); + +// const collateralWithdrawId = 1; + +// const closeTroveSpell = { +// connector: helpers.LIQUITY_CONNECTOR, +// method: "close", +// args: [collateralWithdrawId], +// }; + +// const withdrawEthSpell = { +// connector: helpers.INSTADAPP_BASIC_V1_CONNECTOR, +// method: "withdraw", +// args: [ +// helpers.ETH_ADDRESS, +// 0, // amount comes from the previous spell's setId +// dsa.address, +// collateralWithdrawId, +// 0, +// ], +// }; + +// await dsa +// .connect(userWallet) +// .cast( +// ...encodeSpells([closeTroveSpell, withdrawEthSpell]), +// userWallet.address +// ); + +// const dsaEthBalance = await ethers.provider.getBalance(dsa.address); +// const dsaLusdBalance = await liquity.lusdToken.balanceOf(dsa.address); +// const troveDebt = await liquity.troveManager.getTroveDebt( +// dsa.address +// ); +// const troveCollateral = await liquity.troveManager.getTroveColl( +// dsa.address +// ); + +// expect(troveDebt, "Trove debt should equal 0 after close").to.eq(0); + +// expect( +// troveCollateral, +// "Trove collateral should equal 0 after close" +// ).to.eq(0); + +// expect( +// dsaEthBalance, +// "DSA account should now hold the Trove's ETH collateral" +// ).to.eq(troveCollateralBefore); + +// expect( +// dsaLusdBalance, +// "DSA account should now hold the gas compensation amount of LUSD as it paid off the Trove debt" +// ).to.eq(helpers.LUSD_GAS_COMPENSATION); +// }); + +// it("returns Instadapp event name and data", async () => { +// const depositAmount = ethers.utils.parseEther("5"); +// const borrowAmount = ethers.utils.parseUnits("2000", 18); +// // Create a dummy Trove +// await helpers.createDsaTrove( +// dsa, +// userWallet, +// liquity, +// depositAmount, +// borrowAmount +// ); +// await helpers.sendToken( +// liquity.lusdToken, +// ethers.utils.parseUnits("2500", 18), +// contracts.STABILITY_POOL_ADDRESS, +// dsa.address +// ); + +// const closeTroveSpell = { +// connector: helpers.LIQUITY_CONNECTOR, +// method: "close", +// args: [0], +// }; + +// const closeTx = await dsa +// .connect(userWallet) +// .cast(...encodeSpells([closeTroveSpell]), userWallet.address); + +// const receipt = await closeTx.wait(); +// const castLogEvent = receipt.events.find((e) => e.event === "LogCast") +// .args; +// const expectedEventParams = ethers.utils.defaultAbiCoder.encode( +// ["address", "uint256"], +// [dsa.address, 0] +// ); +// expect(castLogEvent.eventNames[0]).eq("LogClose(address,uint256)"); +// expect(castLogEvent.eventParams[0]).eq(expectedEventParams); +// }); +// }); + +// describe("deposit()", () => { +// it("deposits ETH into a Trove", async () => { +// // Create a dummy Trove +// await helpers.createDsaTrove(dsa, userWallet, liquity); + +// const troveCollateralBefore = await liquity.troveManager.getTroveColl( +// dsa.address +// ); + +// const topupAmount = ethers.utils.parseEther("1"); +// const upperHint = ethers.constants.AddressZero; +// const lowerHint = ethers.constants.AddressZero; +// const depositEthSpell = { +// connector: helpers.LIQUITY_CONNECTOR, +// method: "deposit", +// args: [topupAmount, upperHint, lowerHint, 0, 0], +// }; + +// await dsa +// .connect(userWallet) +// .cast(...encodeSpells([depositEthSpell]), userWallet.address, { +// value: topupAmount, +// }); + +// const troveCollateral = await liquity.troveManager.getTroveColl( +// dsa.address +// ); + +// const expectedTroveCollateral = troveCollateralBefore.add( +// topupAmount +// ); + +// expect( +// troveCollateral, +// `Trove collateral should have increased by ${topupAmount} ETH` +// ).to.eq(expectedTroveCollateral); +// }); + +// it("deposits using ETH gained from a previous spell", async () => { +// // Create a dummy Trove +// await helpers.createDsaTrove(dsa, userWallet, liquity); +// const troveCollateralBefore = await liquity.troveManager.getTroveColl( +// dsa.address +// ); + +// const topupAmount = ethers.utils.parseEther("1"); +// const depositId = 1; +// const depositEthSpell = { +// connector: helpers.INSTADAPP_BASIC_V1_CONNECTOR, +// method: "deposit", +// args: [helpers.ETH_ADDRESS, topupAmount, 0, depositId], +// }; + +// const upperHint = ethers.constants.AddressZero; +// const lowerHint = ethers.constants.AddressZero; +// const depositEthToTroveSpell = { +// connector: helpers.LIQUITY_CONNECTOR, +// method: "deposit", +// args: [0, upperHint, lowerHint, depositId, 0], +// }; +// const spells = [depositEthSpell, depositEthToTroveSpell]; + +// await dsa +// .connect(userWallet) +// .cast(...encodeSpells(spells), userWallet.address, { +// value: topupAmount, +// }); + +// const troveCollateral = await liquity.troveManager.getTroveColl( +// dsa.address +// ); + +// const expectedTroveCollateral = troveCollateralBefore.add( +// topupAmount +// ); + +// expect( +// troveCollateral, +// `Trove collateral should have increased by ${topupAmount} ETH` +// ).to.eq(expectedTroveCollateral); +// }); + +// it("returns Instadapp event name and data", async () => { +// // Create a dummy Trove +// await helpers.createDsaTrove(dsa, userWallet, liquity); + +// const topupAmount = ethers.utils.parseEther("1"); +// const upperHint = ethers.constants.AddressZero; +// const lowerHint = ethers.constants.AddressZero; +// const depositEthSpell = { +// connector: helpers.LIQUITY_CONNECTOR, +// method: "deposit", +// args: [topupAmount, upperHint, lowerHint, 0, 0], +// }; + +// const depositTx = await dsa +// .connect(userWallet) +// .cast(...encodeSpells([depositEthSpell]), userWallet.address, { +// value: topupAmount, +// }); + +// const receipt = await depositTx.wait(); +// const castLogEvent = receipt.events.find((e) => e.event === "LogCast") +// .args; +// const expectedEventParams = ethers.utils.defaultAbiCoder.encode( +// ["address", "uint256", "uint256", "uint256"], +// [dsa.address, topupAmount, 0, 0] +// ); +// expect(castLogEvent.eventNames[0]).eq( +// "LogDeposit(address,uint256,uint256,uint256)" +// ); +// expect(castLogEvent.eventParams[0]).eq(expectedEventParams); +// }); +// }); + +// describe("withdraw()", () => { +// it("withdraws ETH from a Trove", async () => { +// // Create a dummy Trove +// await helpers.createDsaTrove(dsa, userWallet, liquity); + +// const troveCollateralBefore = await liquity.troveManager.getTroveColl( +// dsa.address +// ); +// const withdrawAmount = ethers.utils.parseEther("1"); +// const upperHint = ethers.constants.AddressZero; +// const lowerHint = ethers.constants.AddressZero; +// const withdrawEthSpell = { +// connector: helpers.LIQUITY_CONNECTOR, +// method: "withdraw", +// args: [withdrawAmount, upperHint, lowerHint, 0, 0], +// }; + +// await dsa +// .connect(userWallet) +// .cast(...encodeSpells([withdrawEthSpell]), userWallet.address); + +// const troveCollateral = await liquity.troveManager.getTroveColl( +// dsa.address +// ); +// const expectedTroveCollateral = troveCollateralBefore.sub( +// withdrawAmount +// ); + +// expect( +// troveCollateral, +// `Trove collateral should have decreased by ${withdrawAmount} ETH` +// ).to.eq(expectedTroveCollateral); +// }); + +// it("withdraws ETH from a Trove and stores the ETH for other spells to use", async () => { +// // Create a dummy Trove +// await helpers.createDsaTrove(dsa, userWallet, liquity); + +// const troveCollateralBefore = await liquity.troveManager.getTroveColl( +// dsa.address +// ); +// const originalUserEthBalance = await ethers.provider.getBalance( +// userWallet.address +// ); + +// const withdrawAmount = ethers.utils.parseEther("1"); +// const upperHint = ethers.constants.AddressZero; +// const lowerHint = ethers.constants.AddressZero; +// const withdrawId = 1; +// const withdrawEthFromTroveSpell = { +// connector: helpers.LIQUITY_CONNECTOR, +// method: "withdraw", +// args: [withdrawAmount, upperHint, lowerHint, 0, withdrawId], +// }; + +// const withdrawEthSpell = { +// connector: helpers.INSTADAPP_BASIC_V1_CONNECTOR, +// method: "withdraw", +// args: [helpers.ETH_ADDRESS, 0, userWallet.address, withdrawId, 0], +// }; +// const spells = [withdrawEthFromTroveSpell, withdrawEthSpell]; +// await dsa +// .connect(userWallet) +// .cast(...encodeSpells(spells), userWallet.address, { +// gasPrice: 0, // Remove gas costs so we can check balances have changed correctly +// }); + +// const troveCollateral = await liquity.troveManager.getTroveColl( +// dsa.address +// ); +// const expectedTroveCollateral = troveCollateralBefore.sub( +// withdrawAmount +// ); +// const userEthBalance = await ethers.provider.getBalance( +// userWallet.address +// ); + +// expect( +// troveCollateral, +// `Trove collateral should have decreased by ${withdrawAmount} ETH` +// ).to.eq(expectedTroveCollateral); + +// expect( +// userEthBalance, +// `User ETH balance should have increased by ${withdrawAmount} ETH` +// ).to.eq(originalUserEthBalance.add(withdrawAmount)); +// }); + +// it("returns Instadapp event name and data", async () => { +// // Create a dummy Trove +// await helpers.createDsaTrove(dsa, userWallet, liquity); + +// const withdrawAmount = ethers.utils.parseEther("1"); +// const upperHint = ethers.constants.AddressZero; +// const lowerHint = ethers.constants.AddressZero; +// const withdrawEthSpell = { +// connector: helpers.LIQUITY_CONNECTOR, +// method: "withdraw", +// args: [withdrawAmount, upperHint, lowerHint, 0, 0], +// }; + +// const withdrawTx = await dsa +// .connect(userWallet) +// .cast(...encodeSpells([withdrawEthSpell]), userWallet.address); + +// const receipt = await withdrawTx.wait(); +// const castLogEvent = receipt.events.find((e) => e.event === "LogCast") +// .args; +// const expectedEventParams = ethers.utils.defaultAbiCoder.encode( +// ["address", "uint256", "uint256", "uint256"], +// [dsa.address, withdrawAmount, 0, 0] +// ); +// expect(castLogEvent.eventNames[0]).eq( +// "LogWithdraw(address,uint256,uint256,uint256)" +// ); +// expect(castLogEvent.eventParams[0]).eq(expectedEventParams); +// }); +// }); + +// describe("borrow()", () => { +// it("borrows LUSD from a Trove", async () => { +// // Create a dummy Trove +// await helpers.createDsaTrove(dsa, userWallet, liquity); + +// const troveDebtBefore = await liquity.troveManager.getTroveDebt( +// dsa.address +// ); + +// const borrowAmount = ethers.utils.parseUnits("1000", 18); // 1000 LUSD +// const upperHint = ethers.constants.AddressZero; +// const lowerHint = ethers.constants.AddressZero; +// const maxFeePercentage = ethers.utils.parseUnits("0.5", 18); // 0.5% max fee +// const borrowSpell = { +// connector: helpers.LIQUITY_CONNECTOR, +// method: "borrow", +// args: [maxFeePercentage, borrowAmount, upperHint, lowerHint, 0, 0], +// }; + +// // Borrow more LUSD from the Trove +// await dsa +// .connect(userWallet) +// .cast(...encodeSpells([borrowSpell]), userWallet.address); + +// const troveDebt = await liquity.troveManager.getTroveDebt( +// dsa.address +// ); +// const expectedTroveDebt = troveDebtBefore.add(borrowAmount); + +// expect( +// troveDebt, +// `Trove debt should have increased by at least ${borrowAmount} ETH` +// ).to.gte(expectedTroveDebt); +// }); + +// it("borrows LUSD from a Trove and stores the LUSD for other spells to use", async () => { +// // Create a dummy Trove +// await helpers.createDsaTrove(dsa, userWallet, liquity); + +// const troveDebtBefore = await liquity.troveManager.getTroveDebt( +// dsa.address +// ); + +// const borrowAmount = ethers.utils.parseUnits("1000", 18); // 1000 LUSD +// const upperHint = ethers.constants.AddressZero; +// const lowerHint = ethers.constants.AddressZero; +// const maxFeePercentage = ethers.utils.parseUnits("0.5", 18); // 0.5% max fee +// const borrowId = 1; +// const borrowSpell = { +// connector: helpers.LIQUITY_CONNECTOR, +// method: "borrow", +// args: [ +// maxFeePercentage, +// borrowAmount, +// upperHint, +// lowerHint, +// 0, +// borrowId, +// ], +// }; +// const withdrawSpell = { +// connector: helpers.INSTADAPP_BASIC_V1_CONNECTOR, +// method: "withdraw", +// args: [ +// liquity.lusdToken.address, +// 0, +// userWallet.address, +// borrowId, +// 0, +// ], +// }; +// const spells = [borrowSpell, withdrawSpell]; + +// // Borrow more LUSD from the Trove +// await dsa +// .connect(userWallet) +// .cast(...encodeSpells(spells), userWallet.address); + +// const troveDebt = await liquity.troveManager.getTroveDebt( +// dsa.address +// ); +// const expectedTroveDebt = troveDebtBefore.add(borrowAmount); +// const userLusdBalance = await liquity.lusdToken.balanceOf( +// userWallet.address +// ); + +// expect( +// troveDebt, +// `Trove debt should have increased by at least ${borrowAmount} ETH` +// ).to.gte(expectedTroveDebt); + +// expect( +// userLusdBalance, +// `User LUSD balance should equal the borrowed LUSD due to the second withdraw spell` +// ).eq(borrowAmount); +// }); + +// it("returns Instadapp event name and data", async () => { +// // Create a dummy Trove +// await helpers.createDsaTrove(dsa, userWallet, liquity); + +// const borrowAmount = ethers.utils.parseUnits("1000", 18); // 1000 LUSD +// const upperHint = ethers.constants.AddressZero; +// const lowerHint = ethers.constants.AddressZero; +// const maxFeePercentage = ethers.utils.parseUnits("0.5", 18); // 0.5% max fee +// const borrowSpell = { +// connector: helpers.LIQUITY_CONNECTOR, +// method: "borrow", +// args: [maxFeePercentage, borrowAmount, upperHint, lowerHint, 0, 0], +// }; + +// const borrowTx = await dsa +// .connect(userWallet) +// .cast(...encodeSpells([borrowSpell]), userWallet.address); + +// const receipt = await borrowTx.wait(); +// const castLogEvent = receipt.events.find((e) => e.event === "LogCast") +// .args; +// const expectedEventParams = ethers.utils.defaultAbiCoder.encode( +// ["address", "uint256", "uint256", "uint256"], +// [dsa.address, borrowAmount, 0, 0] +// ); +// expect(castLogEvent.eventNames[0]).eq( +// "LogBorrow(address,uint256,uint256,uint256)" +// ); +// expect(castLogEvent.eventParams[0]).eq(expectedEventParams); +// }); +// }); + +// describe("repay()", () => { +// it("repays LUSD to a Trove", async () => { +// const depositAmount = ethers.utils.parseEther("5"); +// const borrowAmount = ethers.utils.parseUnits("2500", 18); + +// // Create a dummy Trove +// await helpers.createDsaTrove( +// dsa, +// userWallet, +// liquity, +// depositAmount, +// borrowAmount +// ); + +// const troveDebtBefore = await liquity.troveManager.getTroveDebt( +// dsa.address +// ); +// // DSA account is holding 2500 LUSD from opening a Trove, so we use some of that to repay +// const repayAmount = ethers.utils.parseUnits("100", 18); // 100 LUSD + +// const { upperHint, lowerHint } = await helpers.getTroveInsertionHints( +// depositAmount, +// borrowAmount, +// liquity +// ); +// const repaySpell = { +// connector: helpers.LIQUITY_CONNECTOR, +// method: "repay", +// args: [repayAmount, upperHint, lowerHint, 0, 0], +// }; + +// await dsa +// .connect(userWallet) +// .cast(...encodeSpells([repaySpell]), userWallet.address); + +// const troveDebt = await liquity.troveManager.getTroveDebt( +// dsa.address +// ); +// const expectedTroveDebt = troveDebtBefore.sub(repayAmount); + +// expect( +// troveDebt, +// `Trove debt should have decreased by ${repayAmount} ETH` +// ).to.eq(expectedTroveDebt); +// }); + +// it("repays LUSD to a Trove using LUSD collected from a previous spell", async () => { +// const depositAmount = ethers.utils.parseEther("5"); +// const borrowAmount = ethers.utils.parseUnits("2500", 18); + +// // Create a dummy Trove +// await helpers.createDsaTrove( +// dsa, +// userWallet, +// liquity, +// depositAmount, +// borrowAmount +// ); + +// const troveDebtBefore = await liquity.troveManager.getTroveDebt( +// dsa.address +// ); + +// const repayAmount = ethers.utils.parseUnits("100", 18); // 100 LUSD +// const { upperHint, lowerHint } = await helpers.getTroveInsertionHints( +// depositAmount, +// borrowAmount, +// liquity +// ); + +// // Drain the DSA's LUSD balance so that we ensure we are repaying using LUSD from a previous spell +// await helpers.sendToken( +// liquity.lusdToken, +// borrowAmount, +// dsa.address, +// userWallet.address +// ); + +// // Allow DSA to spend user's LUSD +// await liquity.lusdToken +// .connect(userWallet) +// .approve(dsa.address, repayAmount); + +// const lusdDepositId = 1; +// const depositSpell = { +// connector: helpers.INSTADAPP_BASIC_V1_CONNECTOR, +// method: "deposit", +// args: [liquity.lusdToken.address, repayAmount, 0, lusdDepositId], +// }; +// const borrowSpell = { +// connector: helpers.LIQUITY_CONNECTOR, +// method: "repay", +// args: [0, upperHint, lowerHint, lusdDepositId, 0], +// }; + +// const spells = [depositSpell, borrowSpell]; + +// await dsa +// .connect(userWallet) +// .cast(...encodeSpells(spells), userWallet.address); + +// const troveDebt = await liquity.troveManager.getTroveDebt( +// dsa.address +// ); +// const expectedTroveDebt = troveDebtBefore.sub(repayAmount); + +// expect( +// troveDebt, +// `Trove debt should have decreased by ${repayAmount} ETH` +// ).to.eq(expectedTroveDebt); +// }); + +// it("returns Instadapp event name and data", async () => { +// // Create a dummy Trove +// const depositAmount = ethers.utils.parseEther("5"); +// const borrowAmount = ethers.utils.parseUnits("2500", 18); +// await helpers.createDsaTrove( +// dsa, +// userWallet, +// liquity, +// depositAmount, +// borrowAmount +// ); + +// const repayAmount = ethers.utils.parseUnits("100", 18); // 100 LUSD +// const { upperHint, lowerHint } = await helpers.getTroveInsertionHints( +// depositAmount, +// borrowAmount, +// liquity +// ); + +// const borrowSpell = { +// connector: helpers.LIQUITY_CONNECTOR, +// method: "repay", +// args: [repayAmount, upperHint, lowerHint, 0, 0], +// }; + +// const repayTx = await dsa +// .connect(userWallet) +// .cast(...encodeSpells([borrowSpell]), userWallet.address, { +// value: repayAmount, +// }); + +// const receipt = await repayTx.wait(); +// const castLogEvent = receipt.events.find((e) => e.event === "LogCast") +// .args; +// const expectedEventParams = ethers.utils.defaultAbiCoder.encode( +// ["address", "uint256", "uint256", "uint256"], +// [dsa.address, repayAmount, 0, 0] +// ); +// expect(castLogEvent.eventNames[0]).eq( +// "LogRepay(address,uint256,uint256,uint256)" +// ); +// expect(castLogEvent.eventParams[0]).eq(expectedEventParams); +// }); +// }); + +// describe("adjust()", () => { +// it("adjusts a Trove: deposit ETH and borrow LUSD", async () => { +// // Create a dummy Trove +// await helpers.createDsaTrove(dsa, userWallet, liquity); + +// const troveCollateralBefore = await liquity.troveManager.getTroveColl( +// dsa.address +// ); +// const troveDebtBefore = await liquity.troveManager.getTroveDebt( +// dsa.address +// ); +// const depositAmount = ethers.utils.parseEther("1"); // 1 ETH +// const borrowAmount = ethers.utils.parseUnits("500", 18); // 500 LUSD +// const withdrawAmount = 0; +// const repayAmount = 0; +// const upperHint = ethers.constants.AddressZero; +// const lowerHint = ethers.constants.AddressZero; +// const maxFeePercentage = ethers.utils.parseUnits("0.5", 18); // 0.5% max fee + +// const adjustSpell = { +// connector: helpers.LIQUITY_CONNECTOR, +// method: "adjust", +// args: [ +// maxFeePercentage, +// depositAmount, +// withdrawAmount, +// borrowAmount, +// repayAmount, +// upperHint, +// lowerHint, +// [0, 0, 0, 0], +// [0, 0, 0, 0], +// ], +// }; + +// // Adjust Trove by depositing ETH and borrowing LUSD +// await dsa +// .connect(userWallet) +// .cast(...encodeSpells([adjustSpell]), userWallet.address, { +// value: depositAmount, +// gasLimit: helpers.MAX_GAS, +// }); + +// const troveCollateral = await liquity.troveManager.getTroveColl( +// dsa.address +// ); +// const troveDebt = await liquity.troveManager.getTroveDebt( +// dsa.address +// ); +// const expectedTroveColl = troveCollateralBefore.add(depositAmount); +// const expectedTroveDebt = troveDebtBefore.add(borrowAmount); + +// expect( +// troveCollateral, +// `Trove collateral should have increased by ${depositAmount} ETH` +// ).to.eq(expectedTroveColl); + +// expect( +// troveDebt, +// `Trove debt should have increased by at least ${borrowAmount} ETH` +// ).to.gte(expectedTroveDebt); +// }); + +// it("adjusts a Trove: withdraw ETH and repay LUSD", async () => { +// // Create a dummy Trove +// await helpers.createDsaTrove(dsa, userWallet, liquity); + +// const troveCollateralBefore = await liquity.troveManager.getTroveColl( +// dsa.address +// ); +// const troveDebtBefore = await liquity.troveManager.getTroveDebt( +// dsa.address +// ); +// const depositAmount = 0; +// const borrowAmount = 0; +// const withdrawAmount = ethers.utils.parseEther("1"); // 1 ETH; +// const repayAmount = ethers.utils.parseUnits("10", 18); // 10 LUSD; +// const { upperHint, lowerHint } = await helpers.getTroveInsertionHints( +// troveCollateralBefore.sub(withdrawAmount), +// troveDebtBefore.sub(repayAmount), +// liquity +// ); +// const maxFeePercentage = ethers.utils.parseUnits("0.5", 18); // 0.5% max fee + +// const adjustSpell = { +// connector: helpers.LIQUITY_CONNECTOR, +// method: "adjust", +// args: [ +// maxFeePercentage, +// depositAmount, +// withdrawAmount, +// borrowAmount, +// repayAmount, +// upperHint, +// lowerHint, +// [0, 0, 0, 0], +// [0, 0, 0, 0], +// ], +// }; + +// // Adjust Trove by withdrawing ETH and repaying LUSD +// await dsa +// .connect(userWallet) +// .cast(...encodeSpells([adjustSpell]), userWallet.address, { +// value: depositAmount, +// gasLimit: helpers.MAX_GAS, +// }); + +// const troveCollateral = await liquity.troveManager.getTroveColl( +// dsa.address +// ); +// const troveDebt = await liquity.troveManager.getTroveDebt( +// dsa.address +// ); +// const expectedTroveColl = troveCollateralBefore.sub(withdrawAmount); +// const expectedTroveDebt = troveDebtBefore.sub(repayAmount); + +// expect( +// troveCollateral, +// `Trove collateral should have increased by ${depositAmount} ETH` +// ).to.eq(expectedTroveColl); + +// expect( +// troveDebt, +// `Trove debt should have decreased by at least ${repayAmount} LUSD` +// ).to.gte(expectedTroveDebt); +// }); + +// it("adjusts a Trove: deposit ETH and repay LUSD using previous spells", async () => { +// // Create a dummy Trove +// await helpers.createDsaTrove(dsa, userWallet, liquity); + +// const troveCollateralBefore = await liquity.troveManager.getTroveColl( +// dsa.address +// ); +// const troveDebtBefore = await liquity.troveManager.getTroveDebt( +// dsa.address +// ); +// const depositAmount = ethers.utils.parseEther("1"); // 1 ETH +// const borrowAmount = 0; +// const withdrawAmount = 0; +// const repayAmount = ethers.utils.parseUnits("10", 18); // 10 lUSD +// const upperHint = ethers.constants.AddressZero; +// const lowerHint = ethers.constants.AddressZero; +// const maxFeePercentage = ethers.utils.parseUnits("0.5", 18); // 0.5% max fee + +// const ethDepositId = 1; +// const lusdRepayId = 2; + +// const depositEthSpell = { +// connector: helpers.INSTADAPP_BASIC_V1_CONNECTOR, +// method: "deposit", +// args: [helpers.ETH_ADDRESS, depositAmount, 0, ethDepositId], +// }; + +// const depositLusdSpell = { +// connector: helpers.INSTADAPP_BASIC_V1_CONNECTOR, +// method: "deposit", +// args: [liquity.lusdToken.address, repayAmount, 0, lusdRepayId], +// }; + +// const adjustSpell = { +// connector: helpers.LIQUITY_CONNECTOR, +// method: "adjust", +// args: [ +// maxFeePercentage, +// 0, // Deposit amount comes from a previous spell's storage slot +// withdrawAmount, +// borrowAmount, +// 0, // Repay amount comes from a previous spell's storage slot +// upperHint, +// lowerHint, +// [ethDepositId, 0, 0, lusdRepayId], +// [0, 0, 0, 0], +// ], +// }; +// const spells = [depositEthSpell, depositLusdSpell, adjustSpell]; + +// // Send user some LUSD so they can repay +// await helpers.sendToken( +// liquity.lusdToken, +// repayAmount, +// helpers.JUSTIN_SUN_ADDRESS, +// userWallet.address +// ); + +// // Allow DSA to spend user's LUSD +// await liquity.lusdToken +// .connect(userWallet) +// .approve(dsa.address, repayAmount); + +// // Adjust Trove by depositing ETH and repaying LUSD +// await dsa +// .connect(userWallet) +// .cast(...encodeSpells(spells), userWallet.address, { +// value: depositAmount, +// gasLimit: helpers.MAX_GAS, +// }); + +// const troveCollateral = await liquity.troveManager.getTroveColl( +// dsa.address +// ); +// const troveDebt = await liquity.troveManager.getTroveDebt( +// dsa.address +// ); +// const expectedTroveColl = troveCollateralBefore.add(depositAmount); +// const expectedTroveDebt = troveDebtBefore.sub(repayAmount); + +// expect( +// troveCollateral, +// `Trove collateral should have increased by ${depositAmount} ETH` +// ).to.eq(expectedTroveColl); + +// expect( +// troveDebt, +// `Trove debt (${troveDebtBefore}) should have decreased by at least ${repayAmount} LUSD` +// ).to.eq(expectedTroveDebt); +// }); + +// it("adjusts a Trove: withdraw ETH, borrow LUSD, and store the amounts for other spells", async () => { +// // Create a dummy Trove +// await helpers.createDsaTrove(dsa, userWallet, liquity); + +// const userEthBalanceBefore = await ethers.provider.getBalance( +// userWallet.address +// ); +// const userLusdBalanceBefore = await liquity.lusdToken.balanceOf( +// userWallet.address +// ); + +// const depositAmount = 0; +// const borrowAmount = ethers.utils.parseUnits("100", 18); // 100 LUSD +// const withdrawAmount = ethers.utils.parseEther("1"); // 1 ETH +// const repayAmount = 0; +// const upperHint = ethers.constants.AddressZero; +// const lowerHint = ethers.constants.AddressZero; +// const maxFeePercentage = ethers.utils.parseUnits("0.5", 18); // 0.5% max fee + +// const ethWithdrawId = 1; +// const lusdBorrowId = 2; + +// const adjustSpell = { +// connector: helpers.LIQUITY_CONNECTOR, +// method: "adjust", +// args: [ +// maxFeePercentage, +// depositAmount, +// withdrawAmount, +// borrowAmount, +// repayAmount, +// upperHint, +// lowerHint, +// [0, 0, 0, 0], +// [0, ethWithdrawId, lusdBorrowId, 0], +// ], +// }; + +// const withdrawEthSpell = { +// connector: helpers.INSTADAPP_BASIC_V1_CONNECTOR, +// method: "withdraw", +// args: [ +// helpers.ETH_ADDRESS, +// 0, +// userWallet.address, +// ethWithdrawId, +// 0, +// ], +// }; + +// const withdrawLusdSpell = { +// connector: helpers.INSTADAPP_BASIC_V1_CONNECTOR, +// method: "withdraw", +// args: [ +// liquity.lusdToken.address, +// 0, +// userWallet.address, +// lusdBorrowId, +// 0, +// ], +// }; + +// const spells = [adjustSpell, withdrawEthSpell, withdrawLusdSpell]; + +// // Adjust Trove by withdrawing ETH and borrowing LUSD +// await dsa +// .connect(userWallet) +// .cast(...encodeSpells(spells), userWallet.address, { +// gasLimit: helpers.MAX_GAS, +// gasPrice: 0, +// }); + +// const userEthBalanceAfter = await ethers.provider.getBalance( +// userWallet.address +// ); +// const userLusdBalanceAfter = await liquity.lusdToken.balanceOf( +// userWallet.address +// ); +// expect(userEthBalanceAfter).eq( +// userEthBalanceBefore.add(withdrawAmount) +// ); +// expect(userLusdBalanceAfter).eq( +// userLusdBalanceBefore.add(borrowAmount) +// ); +// }); + +// it("returns Instadapp event name and data", async () => { +// // Create a dummy Trove +// await helpers.createDsaTrove(dsa, userWallet, liquity); + +// const depositAmount = ethers.utils.parseEther("1"); // 1 ETH +// const borrowAmount = ethers.utils.parseUnits("500", 18); // 500 LUSD +// const withdrawAmount = 0; +// const repayAmount = 0; +// const upperHint = ethers.constants.AddressZero; +// const lowerHint = ethers.constants.AddressZero; +// const maxFeePercentage = ethers.utils.parseUnits("0.5", 18); // 0.5% max fee + +// const adjustSpell = { +// connector: helpers.LIQUITY_CONNECTOR, +// method: "adjust", +// args: [ +// maxFeePercentage, +// depositAmount, +// withdrawAmount, +// borrowAmount, +// repayAmount, +// upperHint, +// lowerHint, +// [0, 0, 0, 0], +// [0, 0, 0, 0], +// ], +// }; + +// const adjustTx = await dsa +// .connect(userWallet) +// .cast(...encodeSpells([adjustSpell]), userWallet.address, { +// value: depositAmount, +// gasLimit: helpers.MAX_GAS, +// }); + +// const receipt = await adjustTx.wait(); +// const castLogEvent = receipt.events.find((e) => e.event === "LogCast") +// .args; +// const expectedEventParams = ethers.utils.defaultAbiCoder.encode( +// [ +// "address", +// "uint256", +// "uint256", +// "uint256", +// "uint256", +// "uint256", +// "uint256[]", +// "uint256[]", +// ], +// [ +// dsa.address, +// maxFeePercentage, +// depositAmount, +// withdrawAmount, +// borrowAmount, +// repayAmount, +// [0, 0, 0, 0], +// [0, 0, 0, 0], +// ] +// ); +// expect(castLogEvent.eventNames[0]).eq( +// "LogAdjust(address,uint256,uint256,uint256,uint256,uint256,uint256[],uint256[])" +// ); +// expect(castLogEvent.eventParams[0]).eq(expectedEventParams); +// }); +// }); + +// describe("claimCollateralFromRedemption()", () => { +// it("claims collateral from a redeemed Trove", async () => { +// // Create a low collateralized Trove +// const depositAmount = ethers.utils.parseEther("1.5"); +// const borrowAmount = ethers.utils.parseUnits("2500", 18); + +// await helpers.createDsaTrove( +// dsa, +// userWallet, +// liquity, +// depositAmount, +// borrowAmount +// ); + +// // Redeem lots of LUSD to cause the Trove to become redeemed +// const redeemAmount = ethers.utils.parseUnits("10000000", 18); +// await helpers.sendToken( +// liquity.lusdToken, +// redeemAmount, +// contracts.STABILITY_POOL_ADDRESS, +// userWallet.address +// ); +// const { +// partialRedemptionHintNicr, +// firstRedemptionHint, +// upperHint, +// lowerHint, +// } = await helpers.getRedemptionHints(redeemAmount, liquity); +// const maxFeePercentage = ethers.utils.parseUnits("0.5", 18); // 0.5% max fee + +// await liquity.troveManager +// .connect(userWallet) +// .redeemCollateral( +// redeemAmount, +// firstRedemptionHint, +// upperHint, +// lowerHint, +// partialRedemptionHintNicr, +// 0, +// maxFeePercentage, +// { +// gasLimit: helpers.MAX_GAS, // permit max gas +// } +// ); + +// const remainingEthCollateral = await liquity.collSurplus.getCollateral( +// dsa.address +// ); + +// // Claim the remaining collateral from the redeemed Trove +// const claimCollateralFromRedemptionSpell = { +// connector: helpers.LIQUITY_CONNECTOR, +// method: "claimCollateralFromRedemption", +// args: [0], +// }; + +// await dsa +// .connect(userWallet) +// .cast( +// ...encodeSpells([claimCollateralFromRedemptionSpell]), +// userWallet.address +// ); + +// const ethBalance = await ethers.provider.getBalance(dsa.address); + +// expect(ethBalance).to.eq(remainingEthCollateral); +// }); + +// it("returns Instadapp event name and data", async () => { +// // Create a low collateralized Trove +// const depositAmount = ethers.utils.parseEther("1.5"); +// const borrowAmount = ethers.utils.parseUnits("2500", 18); + +// await helpers.createDsaTrove( +// dsa, +// userWallet, +// liquity, +// depositAmount, +// borrowAmount +// ); + +// // Redeem lots of LUSD to cause the Trove to become redeemed +// const redeemAmount = ethers.utils.parseUnits("10000000", 18); +// const setId = 0; +// await helpers.sendToken( +// liquity.lusdToken, +// redeemAmount, +// contracts.STABILITY_POOL_ADDRESS, +// userWallet.address +// ); +// const { +// partialRedemptionHintNicr, +// firstRedemptionHint, +// upperHint, +// lowerHint, +// } = await helpers.getRedemptionHints(redeemAmount, liquity); +// const maxFeePercentage = ethers.utils.parseUnits("0.5", 18); // 0.5% max fee + +// await liquity.troveManager +// .connect(userWallet) +// .redeemCollateral( +// redeemAmount, +// firstRedemptionHint, +// upperHint, +// lowerHint, +// partialRedemptionHintNicr, +// 0, +// maxFeePercentage, +// { +// gasLimit: helpers.MAX_GAS, // permit max gas +// } +// ); +// const claimAmount = await liquity.collSurplus.getCollateral( +// dsa.address +// ); + +// const claimCollateralFromRedemptionSpell = { +// connector: helpers.LIQUITY_CONNECTOR, +// method: "claimCollateralFromRedemption", +// args: [setId], +// }; + +// const claimTx = await dsa +// .connect(userWallet) +// .cast( +// ...encodeSpells([claimCollateralFromRedemptionSpell]), +// userWallet.address +// ); + +// const receipt = await claimTx.wait(); +// const castLogEvent = receipt.events.find((e) => e.event === "LogCast") +// .args; +// const expectedEventParams = ethers.utils.defaultAbiCoder.encode( +// ["address", "uint256", "uint256"], +// [dsa.address, claimAmount, setId] +// ); +// expect(castLogEvent.eventNames[0]).eq( +// "LogClaimCollateralFromRedemption(address,uint256,uint256)" +// ); +// expect(castLogEvent.eventParams[0]).eq(expectedEventParams); +// }); +// }); +// }); + +// describe("Stability Pool", () => { +// describe("stabilityDeposit()", () => { +// it("deposits into Stability Pool", async () => { +// const amount = ethers.utils.parseUnits("100", 18); +// const frontendTag = ethers.constants.AddressZero; + +// await helpers.sendToken( +// liquity.lusdToken, +// amount, +// contracts.STABILITY_POOL_ADDRESS, +// dsa.address +// ); + +// const stabilityDepositSpell = { +// connector: helpers.LIQUITY_CONNECTOR, +// method: "stabilityDeposit", +// args: [amount, frontendTag, 0, 0, 0, 0], +// }; + +// await dsa +// .connect(userWallet) +// .cast(...encodeSpells([stabilityDepositSpell]), userWallet.address); + +// const depositedAmount = await liquity.stabilityPool.getCompoundedLUSDDeposit( +// dsa.address +// ); +// expect(depositedAmount).to.eq(amount); +// }); + +// it("deposits into Stability Pool using LUSD collected from a previous spell", async () => { +// const amount = ethers.utils.parseUnits("100", 18); +// const frontendTag = ethers.constants.AddressZero; + +// await helpers.sendToken( +// liquity.lusdToken, +// amount, +// contracts.STABILITY_POOL_ADDRESS, +// userWallet.address +// ); +// const lusdDepositId = 1; + +// const depositLusdSpell = { +// connector: helpers.INSTADAPP_BASIC_V1_CONNECTOR, +// method: "deposit", +// args: [liquity.lusdToken.address, amount, 0, lusdDepositId], +// }; +// const stabilityDepositSpell = { +// connector: helpers.LIQUITY_CONNECTOR, +// method: "stabilityDeposit", +// args: [0, frontendTag, lusdDepositId, 0, 0, 0], +// }; +// const spells = [depositLusdSpell, stabilityDepositSpell]; + +// // Allow DSA to spend user's LUSD +// await liquity.lusdToken +// .connect(userWallet) +// .approve(dsa.address, amount); + +// await dsa +// .connect(userWallet) +// .cast(...encodeSpells(spells), userWallet.address); + +// const depositedAmount = await liquity.stabilityPool.getCompoundedLUSDDeposit( +// dsa.address +// ); +// expect(depositedAmount).to.eq(amount); +// }); + +// it("returns Instadapp event name and data", async () => { +// const amount = ethers.utils.parseUnits("100", 18); +// const halfAmount = amount.div(2); +// const frontendTag = ethers.constants.AddressZero; +// const getDepositId = 0; +// const setDepositId = 0; +// const setEthGainId = 0; +// const setLqtyGainId = 0; + +// await helpers.sendToken( +// liquity.lusdToken, +// amount, +// contracts.STABILITY_POOL_ADDRESS, +// dsa.address +// ); + +// const stabilityDepositSpell = { +// connector: helpers.LIQUITY_CONNECTOR, +// method: "stabilityDeposit", +// args: [ +// halfAmount, +// frontendTag, +// getDepositId, +// setDepositId, +// setEthGainId, +// setLqtyGainId, +// ], +// }; + +// // Create a Stability deposit for this DSA +// await dsa +// .connect(userWallet) +// .cast(...encodeSpells([stabilityDepositSpell]), userWallet.address); + +// // Liquidate a Trove to cause an ETH gain +// await liquity.troveManager.connect(userWallet).liquidateTroves(1, { +// gasLimit: helpers.MAX_GAS, +// }); + +// // Fast forward in time so we have an LQTY gain +// await provider.send("evm_increaseTime", [600]); +// await provider.send("evm_mine"); + +// // Create a Stability Pool deposit with a differen DSA so that LQTY gains can be calculated +// // See: https://github.com/liquity/dev/#lqty-reward-events-and-payouts +// const tempDsa = await buildDSAv2(userWallet.address); +// await helpers.sendToken( +// liquity.lusdToken, +// amount, +// contracts.STABILITY_POOL_ADDRESS, +// tempDsa.address +// ); +// await tempDsa +// .connect(userWallet) +// .cast(...encodeSpells([stabilityDepositSpell]), userWallet.address); + +// const ethGain = await liquity.stabilityPool.getDepositorETHGain( +// dsa.address +// ); +// const lqtyGain = await liquity.stabilityPool.getDepositorLQTYGain( +// dsa.address +// ); + +// // Top up the user's deposit so that we can track their ETH and LQTY gain +// const depositAgainTx = await dsa +// .connect(userWallet) +// .cast(...encodeSpells([stabilityDepositSpell]), userWallet.address); + +// const receipt = await depositAgainTx.wait(); +// const castLogEvent = receipt.events.find((e) => e.event === "LogCast") +// .args; +// const expectedEventParams = ethers.utils.defaultAbiCoder.encode( +// [ +// "address", +// "uint256", +// "uint256", +// "uint256", +// "address", +// "uint256", +// "uint256", +// "uint256", +// "uint256", +// ], +// [ +// dsa.address, +// halfAmount, +// ethGain, +// lqtyGain, +// frontendTag, +// getDepositId, +// setDepositId, +// setEthGainId, +// setLqtyGainId, +// ] +// ); +// expect(castLogEvent.eventNames[0]).eq( +// "LogStabilityDeposit(address,uint256,uint256,uint256,address,uint256,uint256,uint256,uint256)" +// ); +// expect(castLogEvent.eventParams[0]).eq(expectedEventParams); +// }); +// }); + +// describe("stabilityWithdraw()", () => { +// it("withdraws from Stability Pool", async () => { +// // Start this test from scratch since we need to remove any liquidatable Troves withdrawing from Stability Pool +// [liquity, dsa] = await helpers.resetInitialState( +// userWallet.address, +// contracts +// ); + +// // The current block number has liquidatable Troves. +// // Remove them otherwise Stability Pool withdrawals are disabled +// await liquity.troveManager.connect(userWallet).liquidateTroves(90, { +// gasLimit: helpers.MAX_GAS, +// }); + +// const amount = ethers.utils.parseUnits("100", 18); +// const frontendTag = ethers.constants.AddressZero; + +// await helpers.sendToken( +// liquity.lusdToken, +// amount, +// contracts.STABILITY_POOL_ADDRESS, +// dsa.address +// ); + +// const stabilityDepositSpell = { +// connector: helpers.LIQUITY_CONNECTOR, +// method: "stabilityDeposit", +// args: [amount, frontendTag, 0, 0, 0, 0], +// }; + +// // Withdraw half of the deposit +// const stabilityWithdrawSpell = { +// connector: helpers.LIQUITY_CONNECTOR, +// method: "stabilityWithdraw", +// args: [amount.div(2), 0, 0, 0, 0], +// }; +// const spells = [stabilityDepositSpell, stabilityWithdrawSpell]; + +// await dsa +// .connect(userWallet) +// .cast(...encodeSpells(spells), userWallet.address); + +// const depositedAmount = await liquity.stabilityPool.getCompoundedLUSDDeposit( +// dsa.address +// ); +// const dsaLusdBalance = await liquity.lusdToken.balanceOf(dsa.address); + +// expect(depositedAmount).to.eq(amount.div(2)); +// expect(dsaLusdBalance).to.eq(amount.div(2)); +// }); + +// it("withdraws from Stability Pool and stores the LUSD for other spells", async () => { +// // Start this test from scratch since we need to remove any liquidatable Troves withdrawing from Stability Pool +// [liquity, dsa] = await helpers.resetInitialState( +// userWallet.address, +// contracts +// ); + +// // The current block number has liquidatable Troves. +// // Remove them otherwise Stability Pool withdrawals are disabled +// await liquity.troveManager.connect(userWallet).liquidateTroves(90, { +// gasLimit: helpers.MAX_GAS, +// }); +// const amount = ethers.utils.parseUnits("100", 18); +// const frontendTag = ethers.constants.AddressZero; +// const withdrawId = 1; + +// await helpers.sendToken( +// liquity.lusdToken, +// amount, +// contracts.STABILITY_POOL_ADDRESS, +// dsa.address +// ); + +// const stabilityDepositSpell = { +// connector: helpers.LIQUITY_CONNECTOR, +// method: "stabilityDeposit", +// args: [amount, frontendTag, 0, 0, 0, 0], +// }; + +// // Withdraw half of the deposit +// const stabilityWithdrawSpell = { +// connector: helpers.LIQUITY_CONNECTOR, +// method: "stabilityWithdraw", +// args: [amount.div(2), 0, 0, 0, withdrawId], +// }; + +// const withdrawLusdSpell = { +// connector: helpers.INSTADAPP_BASIC_V1_CONNECTOR, +// method: "withdraw", +// args: [ +// liquity.lusdToken.address, +// 0, +// userWallet.address, +// withdrawId, +// 0, +// ], +// }; + +// const spells = [ +// stabilityDepositSpell, +// stabilityWithdrawSpell, +// withdrawLusdSpell, +// ]; + +// await dsa +// .connect(userWallet) +// .cast(...encodeSpells(spells), userWallet.address); + +// const depositedAmount = await liquity.stabilityPool.getCompoundedLUSDDeposit( +// dsa.address +// ); +// const walletLusdBalance = await liquity.lusdToken.balanceOf( +// dsa.address +// ); + +// expect(depositedAmount).to.eq(amount.div(2)); +// expect(walletLusdBalance).to.eq(amount.div(2)); +// }); + +// it("returns Instadapp event name and data", async () => { +// // Start this test from scratch since we need to remove any liquidatable Troves withdrawing from Stability Pool +// [liquity, dsa] = await helpers.resetInitialState( +// userWallet.address, +// contracts +// ); + +// const amount = ethers.utils.parseUnits("100", 18); +// const frontendTag = ethers.constants.AddressZero; + +// await helpers.sendToken( +// liquity.lusdToken, +// amount, +// contracts.STABILITY_POOL_ADDRESS, +// dsa.address +// ); + +// const stabilityDepositSpell = { +// connector: helpers.LIQUITY_CONNECTOR, +// method: "stabilityDeposit", +// args: [amount, frontendTag, 0, 0, 0, 0], +// }; + +// // Withdraw half of the deposit +// const withdrawAmount = amount.div(2); +// const getWithdrawId = 0; +// const setWithdrawId = 0; +// const setEthGainId = 0; +// const setLqtyGainId = 0; + +// // Create a Stability Pool deposit +// await dsa +// .connect(userWallet) +// .cast(...encodeSpells([stabilityDepositSpell]), userWallet.address); + +// // The current block number has liquidatable Troves. +// // Remove them otherwise Stability Pool withdrawals are disabled +// await liquity.troveManager.connect(userWallet).liquidateTroves(90, { +// gasLimit: helpers.MAX_GAS, +// }); + +// // Fast forward in time so we have an LQTY gain +// await provider.send("evm_increaseTime", [600]); +// await provider.send("evm_mine"); + +// // Create another Stability Pool deposit so that LQTY gains are realized +// // See: https://github.com/liquity/dev/#lqty-reward-events-and-payouts +// const tempDsa = await buildDSAv2(userWallet.address); +// await helpers.sendToken( +// liquity.lusdToken, +// amount, +// contracts.STABILITY_POOL_ADDRESS, +// tempDsa.address +// ); +// await tempDsa +// .connect(userWallet) +// .cast(...encodeSpells([stabilityDepositSpell]), userWallet.address); + +// const ethGain = await liquity.stabilityPool.getDepositorETHGain( +// dsa.address +// ); +// const lqtyGain = await liquity.stabilityPool.getDepositorLQTYGain( +// dsa.address +// ); + +// const stabilityWithdrawSpell = { +// connector: helpers.LIQUITY_CONNECTOR, +// method: "stabilityWithdraw", +// args: [ +// withdrawAmount, +// getWithdrawId, +// setWithdrawId, +// setEthGainId, +// setLqtyGainId, +// ], +// }; + +// const withdrawTx = await dsa +// .connect(userWallet) +// .cast( +// ...encodeSpells([stabilityWithdrawSpell]), +// userWallet.address +// ); + +// const receipt = await withdrawTx.wait(); +// const castLogEvent = receipt.events.find((e) => e.event === "LogCast") +// .args; +// const expectedEventParams = ethers.utils.defaultAbiCoder.encode( +// [ +// "address", +// "uint256", +// "uint256", +// "uint256", +// "uint256", +// "uint256", +// "uint256", +// "uint256", +// ], +// [ +// dsa.address, +// withdrawAmount, +// ethGain, +// lqtyGain, +// getWithdrawId, +// setWithdrawId, +// setEthGainId, +// setLqtyGainId, +// ] +// ); +// expect(castLogEvent.eventNames[0]).eq( +// "LogStabilityWithdraw(address,uint256,uint256,uint256,uint256,uint256,uint256,uint256)" +// ); +// expect(castLogEvent.eventParams[0]).eq(expectedEventParams); +// }); +// }); + +// describe("stabilityMoveEthGainToTrove()", () => { +// beforeEach(async () => { +// // Start these test from fresh so that we definitely have a liquidatable Trove within this block +// [liquity, dsa] = await helpers.resetInitialState( +// userWallet.address, +// contracts +// ); +// }); + +// it("moves ETH gain from Stability Pool to Trove", async () => { +// // Create a DSA owned Trove to capture ETH liquidation gains +// // Create a dummy Trove +// await helpers.createDsaTrove(dsa, userWallet, liquity); +// const troveCollateralBefore = await liquity.troveManager.getTroveColl( +// dsa.address +// ); + +// // Create a Stability Deposit using the Trove's borrowed LUSD +// const amount = ethers.utils.parseUnits("100", 18); +// const frontendTag = ethers.constants.AddressZero; +// const stabilityDepositSpell = { +// connector: helpers.LIQUITY_CONNECTOR, +// method: "stabilityDeposit", +// args: [amount, frontendTag, 0, 0, 0, 0], +// }; + +// await dsa +// .connect(userWallet) +// .cast(...encodeSpells([stabilityDepositSpell]), userWallet.address); + +// // Liquidate a Trove to create an ETH gain for the new DSA Trove +// await liquity.troveManager +// .connect(userWallet) +// .liquidate(helpers.LIQUIDATABLE_TROVE_ADDRESS, { +// gasLimit: helpers.MAX_GAS, // permit max gas +// }); + +// const ethGainFromLiquidation = await liquity.stabilityPool.getDepositorETHGain( +// dsa.address +// ); + +// // Move ETH gain to Trove +// const moveEthGainSpell = { +// connector: helpers.LIQUITY_CONNECTOR, +// method: "stabilityMoveEthGainToTrove", +// args: [ethers.constants.AddressZero, ethers.constants.AddressZero], +// }; + +// await dsa +// .connect(userWallet) +// .cast(...encodeSpells([moveEthGainSpell]), userWallet.address); + +// const ethGainAfterMove = await liquity.stabilityPool.getDepositorETHGain( +// dsa.address +// ); +// const troveCollateral = await liquity.troveManager.getTroveColl( +// dsa.address +// ); +// const expectedTroveCollateral = troveCollateralBefore.add( +// ethGainFromLiquidation +// ); +// expect(ethGainAfterMove).to.eq(0); +// expect(troveCollateral).to.eq(expectedTroveCollateral); +// }); + +// it("returns Instadapp event name and data", async () => { +// // Create a DSA owned Trove to capture ETH liquidation gains +// // Create a dummy Trove +// await helpers.createDsaTrove(dsa, userWallet, liquity); + +// // Create a Stability Deposit using the Trove's borrowed LUSD +// const amount = ethers.utils.parseUnits("100", 18); +// const frontendTag = ethers.constants.AddressZero; +// const stabilityDepositSpell = { +// connector: helpers.LIQUITY_CONNECTOR, +// method: "stabilityDeposit", +// args: [amount, frontendTag, 0, 0, 0, 0], +// }; + +// await dsa +// .connect(userWallet) +// .cast(...encodeSpells([stabilityDepositSpell]), userWallet.address); + +// // Liquidate a Trove to create an ETH gain for the new DSA Trove +// await liquity.troveManager +// .connect(userWallet) +// .liquidate(helpers.LIQUIDATABLE_TROVE_ADDRESS, { +// gasLimit: helpers.MAX_GAS, // permit max gas +// }); + +// const ethGainFromLiquidation = await liquity.stabilityPool.getDepositorETHGain( +// dsa.address +// ); + +// // Move ETH gain to Trove +// const moveEthGainSpell = { +// connector: helpers.LIQUITY_CONNECTOR, +// method: "stabilityMoveEthGainToTrove", +// args: [ethers.constants.AddressZero, ethers.constants.AddressZero], +// }; + +// const moveEthGainTx = await dsa +// .connect(userWallet) +// .cast(...encodeSpells([moveEthGainSpell]), userWallet.address); + +// const receipt = await moveEthGainTx.wait(); + +// const castLogEvent = receipt.events.find((e) => e.event === "LogCast") +// .args; +// const expectedEventParams = ethers.utils.defaultAbiCoder.encode( +// ["address", "uint256"], +// [dsa.address, ethGainFromLiquidation] +// ); +// expect(castLogEvent.eventNames[0]).eq( +// "LogStabilityMoveEthGainToTrove(address,uint256)" +// ); +// expect(castLogEvent.eventParams[0]).eq(expectedEventParams); +// }); +// }); +// }); + +// describe("Staking", () => { +// describe("stake()", () => { +// it("stakes LQTY", async () => { +// const totalStakingBalanceBefore = await liquity.lqtyToken.balanceOf( +// contracts.STAKING_ADDRESS +// ); + +// const amount = ethers.utils.parseUnits("1", 18); +// await helpers.sendToken( +// liquity.lqtyToken, +// amount, +// helpers.JUSTIN_SUN_ADDRESS, +// dsa.address +// ); + +// const stakeSpell = { +// connector: helpers.LIQUITY_CONNECTOR, +// method: "stake", +// args: [amount, 0, 0, 0, 0], +// }; + +// await dsa +// .connect(userWallet) +// .cast(...encodeSpells([stakeSpell]), userWallet.address); + +// const lqtyBalance = await liquity.lqtyToken.balanceOf(dsa.address); +// expect(lqtyBalance).to.eq(0); + +// const totalStakingBalance = await liquity.lqtyToken.balanceOf( +// contracts.STAKING_ADDRESS +// ); +// expect(totalStakingBalance).to.eq( +// totalStakingBalanceBefore.add(amount) +// ); +// }); + +// it("stakes LQTY using LQTY obtained from a previous spell", async () => { +// const totalStakingBalanceBefore = await liquity.lqtyToken.balanceOf( +// contracts.STAKING_ADDRESS +// ); + +// const amount = ethers.utils.parseUnits("1", 18); +// await helpers.sendToken( +// liquity.lqtyToken, +// amount, +// helpers.JUSTIN_SUN_ADDRESS, +// userWallet.address +// ); + +// const lqtyDepositId = 1; +// const depositSpell = { +// connector: helpers.INSTADAPP_BASIC_V1_CONNECTOR, +// method: "deposit", +// args: [liquity.lqtyToken.address, amount, 0, lqtyDepositId], +// }; +// const stakeSpell = { +// connector: helpers.LIQUITY_CONNECTOR, +// method: "stake", +// args: [0, lqtyDepositId, 0, 0, 0], +// }; +// const spells = [depositSpell, stakeSpell]; + +// // Allow DSA to spend user's LQTY +// await liquity.lqtyToken +// .connect(userWallet) +// .approve(dsa.address, amount); + +// await dsa +// .connect(userWallet) +// .cast(...encodeSpells(spells), userWallet.address); + +// const lqtyBalance = await liquity.lqtyToken.balanceOf(dsa.address); +// expect(lqtyBalance).to.eq(0); + +// const totalStakingBalance = await liquity.lqtyToken.balanceOf( +// contracts.STAKING_ADDRESS +// ); +// expect(totalStakingBalance).to.eq( +// totalStakingBalanceBefore.add(amount) +// ); +// }); + +// it("returns Instadapp event name and data", async () => { +// const amount = ethers.utils.parseUnits("1", 18); +// await helpers.sendToken( +// liquity.lqtyToken, +// amount, +// helpers.JUSTIN_SUN_ADDRESS, +// dsa.address +// ); + +// const getStakeId = 0; +// const setStakeId = 0; +// const setEthGainId = 0; +// const setLusdGainId = 0; +// const stakeSpell = { +// connector: helpers.LIQUITY_CONNECTOR, +// method: "stake", +// args: [amount, getStakeId, setStakeId, setEthGainId, setLusdGainId], +// }; + +// const stakeTx = await dsa +// .connect(userWallet) +// .cast(...encodeSpells([stakeSpell]), userWallet.address); + +// const receipt = await stakeTx.wait(); + +// const castLogEvent = receipt.events.find((e) => e.event === "LogCast") +// .args; +// const expectedEventParams = ethers.utils.defaultAbiCoder.encode( +// ["address", "uint256", "uint256", "uint256", "uint256", "uint256"], +// [ +// dsa.address, +// amount, +// getStakeId, +// setStakeId, +// setEthGainId, +// setLusdGainId, +// ] +// ); +// expect(castLogEvent.eventNames[0]).eq( +// "LogStake(address,uint256,uint256,uint256,uint256,uint256)" +// ); +// expect(castLogEvent.eventParams[0]).eq(expectedEventParams); +// }); +// }); + +// describe("unstake()", () => { +// it("unstakes LQTY", async () => { +// const amount = ethers.utils.parseUnits("1", 18); +// await helpers.sendToken( +// liquity.lqtyToken, +// amount, +// helpers.JUSTIN_SUN_ADDRESS, +// dsa.address +// ); + +// const stakeSpell = { +// connector: helpers.LIQUITY_CONNECTOR, +// method: "stake", +// args: [amount, 0, 0, 0, 0], +// }; + +// await dsa +// .connect(userWallet) +// .cast(...encodeSpells([stakeSpell]), userWallet.address); + +// const totalStakingBalanceBefore = await liquity.lqtyToken.balanceOf( +// contracts.STAKING_ADDRESS +// ); +// const unstakeSpell = { +// connector: helpers.LIQUITY_CONNECTOR, +// method: "unstake", +// args: [amount, 0, 0, 0, 0], +// }; + +// await dsa +// .connect(userWallet) +// .cast(...encodeSpells([unstakeSpell]), userWallet.address); + +// const lqtyBalance = await liquity.lqtyToken.balanceOf(dsa.address); +// expect(lqtyBalance).to.eq(amount); + +// const totalStakingBalance = await liquity.lqtyToken.balanceOf( +// contracts.STAKING_ADDRESS +// ); +// expect(totalStakingBalance).to.eq( +// totalStakingBalanceBefore.sub(amount) +// ); +// }); + +// it("unstakes LQTY and stores the LQTY for other spells", async () => { +// const amount = ethers.utils.parseUnits("1", 18); +// await helpers.sendToken( +// liquity.lqtyToken, +// amount, +// helpers.JUSTIN_SUN_ADDRESS, +// dsa.address +// ); + +// const stakeSpell = { +// connector: helpers.LIQUITY_CONNECTOR, +// method: "stake", +// args: [amount, 0, 0, 0, 0], +// }; + +// await dsa +// .connect(userWallet) +// .cast(...encodeSpells([stakeSpell]), userWallet.address); + +// const totalStakingBalanceBefore = await liquity.lqtyToken.balanceOf( +// contracts.STAKING_ADDRESS +// ); +// const withdrawId = 1; +// const unstakeSpell = { +// connector: helpers.LIQUITY_CONNECTOR, +// method: "unstake", +// args: [amount, 0, withdrawId, 0, 0], +// }; + +// const withdrawLqtySpell = { +// connector: helpers.INSTADAPP_BASIC_V1_CONNECTOR, +// method: "withdraw", +// args: [ +// liquity.lqtyToken.address, +// 0, +// userWallet.address, +// withdrawId, +// 0, +// ], +// }; +// const spells = [unstakeSpell, withdrawLqtySpell]; +// await dsa +// .connect(userWallet) +// .cast(...encodeSpells(spells), userWallet.address); + +// const lqtyBalance = await liquity.lqtyToken.balanceOf(dsa.address); +// const totalStakingBalance = await liquity.lqtyToken.balanceOf( +// contracts.STAKING_ADDRESS +// ); +// const userLqtyBalance = await liquity.lqtyToken.balanceOf( +// userWallet.address +// ); +// expect(lqtyBalance).to.eq(0); +// expect(totalStakingBalance).to.eq( +// totalStakingBalanceBefore.sub(amount) +// ); +// expect(userLqtyBalance).to.eq(amount); +// }); + +// it("returns Instadapp event name and data", async () => { +// const amount = ethers.utils.parseUnits("1", 18); +// await helpers.sendToken( +// liquity.lqtyToken, +// amount, +// helpers.JUSTIN_SUN_ADDRESS, +// dsa.address +// ); + +// const stakeSpell = { +// connector: helpers.LIQUITY_CONNECTOR, +// method: "stake", +// args: [amount, 0, 0, 0, 0], +// }; + +// await dsa +// .connect(userWallet) +// .cast(...encodeSpells([stakeSpell]), userWallet.address); + +// const getUnstakeId = 0; +// const setUnstakeId = 0; +// const setEthGainId = 0; +// const setLusdGainId = 0; +// const unstakeSpell = { +// connector: helpers.LIQUITY_CONNECTOR, +// method: "unstake", +// args: [ +// amount, +// getUnstakeId, +// setUnstakeId, +// setEthGainId, +// setLusdGainId, +// ], +// }; + +// const unstakeTx = await dsa +// .connect(userWallet) +// .cast(...encodeSpells([unstakeSpell]), userWallet.address); + +// const receipt = await unstakeTx.wait(); + +// const castLogEvent = receipt.events.find((e) => e.event === "LogCast") +// .args; +// const expectedEventParams = ethers.utils.defaultAbiCoder.encode( +// ["address", "uint256", "uint256", "uint256", "uint256", "uint256"], +// [ +// dsa.address, +// amount, +// getUnstakeId, +// setUnstakeId, +// setEthGainId, +// setLusdGainId, +// ] +// ); +// expect(castLogEvent.eventNames[0]).eq( +// "LogUnstake(address,uint256,uint256,uint256,uint256,uint256)" +// ); +// expect(castLogEvent.eventParams[0]).eq(expectedEventParams); +// }); +// }); + +// describe("claimStakingGains()", () => { +// it("claims gains from staking", async () => { +// const stakerDsa = await buildDSAv2(userWallet.address); +// const amount = ethers.utils.parseUnits("1000", 18); // 1000 LQTY + +// // Stake lots of LQTY +// await helpers.sendToken( +// liquity.lqtyToken, +// amount, +// helpers.JUSTIN_SUN_ADDRESS, +// stakerDsa.address +// ); +// const stakeSpell = { +// connector: helpers.LIQUITY_CONNECTOR, +// method: "stake", +// args: [amount, 0, 0, 0, 0], +// }; +// await stakerDsa +// .connect(userWallet) +// .cast(...encodeSpells([stakeSpell]), userWallet.address); + +// // Open a Trove to cause an ETH issuance gain for stakers +// await helpers.createDsaTrove(dsa, userWallet, liquity); + +// // Redeem some ETH to cause an LUSD redemption gain for stakers +// await helpers.redeem( +// ethers.utils.parseUnits("1000", 18), +// contracts.STABILITY_POOL_ADDRESS, +// userWallet, +// liquity +// ); + +// const setEthGainId = 0; +// const setLusdGainId = 0; +// const ethGain = await liquity.staking.getPendingETHGain( +// stakerDsa.address +// ); +// const lusdGain = await liquity.staking.getPendingLUSDGain( +// stakerDsa.address +// ); + +// const claimStakingGainsSpell = { +// connector: helpers.LIQUITY_CONNECTOR, +// method: "claimStakingGains", +// args: [setEthGainId, setLusdGainId], +// }; + +// const ethBalanceBefore = await ethers.provider.getBalance( +// stakerDsa.address +// ); + +// // Claim gains +// await stakerDsa +// .connect(userWallet) +// .cast( +// ...encodeSpells([claimStakingGainsSpell]), +// userWallet.address +// ); + +// const ethBalanceAfter = await ethers.provider.getBalance( +// stakerDsa.address +// ); +// const lusdBalanceAfter = await liquity.lusdToken.balanceOf( +// stakerDsa.address +// ); +// expect(ethBalanceAfter).to.eq(ethBalanceBefore.add(ethGain)); +// expect(lusdBalanceAfter).to.eq(lusdGain); +// }); + +// it("claims gains from staking and stores them for other spells", async () => { +// const stakerDsa = await buildDSAv2(userWallet.address); +// const amount = ethers.utils.parseUnits("1000", 18); // 1000 LQTY + +// // Stake lots of LQTY +// await helpers.sendToken( +// liquity.lqtyToken, +// amount, +// helpers.JUSTIN_SUN_ADDRESS, +// stakerDsa.address +// ); +// const stakeSpell = { +// connector: helpers.LIQUITY_CONNECTOR, +// method: "stake", +// args: [amount, 0, 0, 0, 0], +// }; +// await stakerDsa +// .connect(userWallet) +// .cast(...encodeSpells([stakeSpell]), userWallet.address); + +// // Open a Trove to cause an ETH issuance gain for stakers +// await helpers.createDsaTrove(dsa, userWallet, liquity); + +// // Redeem some ETH to cause an LUSD redemption gain for stakers +// await helpers.redeem( +// ethers.utils.parseUnits("1000", 18), +// contracts.STABILITY_POOL_ADDRESS, +// userWallet, +// liquity +// ); + +// const ethGain = await liquity.staking.getPendingETHGain( +// stakerDsa.address +// ); +// const lusdGain = await liquity.staking.getPendingLUSDGain( +// stakerDsa.address +// ); +// const lusdBalanceBefore = await liquity.lusdToken.balanceOf( +// userWallet.address +// ); +// const ethBalanceBefore = await ethers.provider.getBalance( +// userWallet.address +// ); +// const ethGainId = 111; +// const lusdGainId = 222; + +// const claimStakingGainsSpell = { +// connector: helpers.LIQUITY_CONNECTOR, +// method: "claimStakingGains", +// args: [ethGainId, lusdGainId], +// }; + +// const withdrawEthSpell = { +// connector: helpers.INSTADAPP_BASIC_V1_CONNECTOR, +// method: "withdraw", +// args: [helpers.ETH_ADDRESS, 0, userWallet.address, ethGainId, 0], +// }; + +// const withdrawLusdSpell = { +// connector: helpers.INSTADAPP_BASIC_V1_CONNECTOR, +// method: "withdraw", +// args: [ +// liquity.lusdToken.address, +// 0, +// userWallet.address, +// lusdGainId, +// 0, +// ], +// }; + +// const spells = [ +// claimStakingGainsSpell, +// withdrawEthSpell, +// withdrawLusdSpell, +// ]; + +// // Claim gains +// await stakerDsa +// .connect(userWallet) +// .cast(...encodeSpells(spells), userWallet.address, { +// gasPrice: 0, +// }); + +// const ethBalanceAfter = await ethers.provider.getBalance( +// userWallet.address +// ); +// const lusdBalanceAfter = await liquity.lusdToken.balanceOf( +// userWallet.address +// ); + +// expect( +// ethBalanceAfter, +// "User's ETH balance should have increased by the issuance gain from staking" +// ).to.eq(ethBalanceBefore.add(ethGain)); +// expect( +// lusdBalanceAfter, +// "User's LUSD balance should have increased by the redemption gain from staking" +// ).to.eq(lusdBalanceBefore.add(lusdGain)); +// }); + +// it("returns Instadapp event name and data", async () => { +// const stakerDsa = await buildDSAv2(userWallet.address); +// const amount = ethers.utils.parseUnits("1000", 18); // 1000 LQTY + +// // Stake lots of LQTY +// await helpers.sendToken( +// liquity.lqtyToken, +// amount, +// helpers.JUSTIN_SUN_ADDRESS, +// stakerDsa.address +// ); +// const stakeSpell = { +// connector: helpers.LIQUITY_CONNECTOR, +// method: "stake", +// args: [amount, 0, 0, 0, 0], +// }; +// await stakerDsa +// .connect(userWallet) +// .cast(...encodeSpells([stakeSpell]), userWallet.address); + +// // Open a Trove to cause an ETH issuance gain for stakers +// await helpers.createDsaTrove(dsa, userWallet, liquity); + +// // Redeem some ETH to cause an LUSD redemption gain for stakers +// await helpers.redeem( +// ethers.utils.parseUnits("1000", 18), +// contracts.STABILITY_POOL_ADDRESS, +// userWallet, +// liquity +// ); + +// const setEthGainId = 0; +// const setLusdGainId = 0; +// const ethGain = await liquity.staking.getPendingETHGain( +// stakerDsa.address +// ); +// const lusdGain = await liquity.staking.getPendingLUSDGain( +// stakerDsa.address +// ); + +// const claimStakingGainsSpell = { +// connector: helpers.LIQUITY_CONNECTOR, +// method: "claimStakingGains", +// args: [setEthGainId, setLusdGainId], +// }; + +// // Claim gains +// const claimGainsTx = await stakerDsa +// .connect(userWallet) +// .cast( +// ...encodeSpells([claimStakingGainsSpell]), +// userWallet.address +// ); + +// const receipt = await claimGainsTx.wait(); + +// const castLogEvent = receipt.events.find((e) => e.event === "LogCast") +// .args; +// const expectedEventParams = ethers.utils.defaultAbiCoder.encode( +// ["address", "uint256", "uint256", "uint256", "uint256"], +// [stakerDsa.address, ethGain, lusdGain, setEthGainId, setLusdGainId] +// ); +// expect(castLogEvent.eventNames[0]).eq( +// "LogClaimStakingGains(address,uint256,uint256,uint256,uint256)" +// ); +// expect(castLogEvent.eventParams[0]).eq(expectedEventParams); +// }); +// }); +// }); +// }); +// }); diff --git a/test/mainnet/pooltogether/pooltogether.test.ts b/test/mainnet/pooltogether/pooltogether.test.ts index 610a3bbe..272f4460 100644 --- a/test/mainnet/pooltogether/pooltogether.test.ts +++ b/test/mainnet/pooltogether/pooltogether.test.ts @@ -1,1225 +1,1225 @@ -import { expect } from "chai"; -import hre from "hardhat"; -const { web3, deployments, waffle, ethers } = hre; -const { provider, deployContract } = waffle; - -import { deployAndEnableConnector } from "../../../scripts/tests/deployAndEnableConnector"; -import { buildDSAv2 } from "../../../scripts/tests/buildDSAv2"; -import { encodeSpells } from "../../../scripts/tests/encodeSpells"; -import { getMasterSigner } from "../../../scripts/tests/getMasterSigner"; - -import { addresses } from "../../../scripts/constant/addresses"; -import { abis } from "../../../scripts/constant/abis"; -import { constants } from "../../../scripts/constant/constant"; -import { tokens } from "../../../scripts/constant/tokens"; -import type { Signer, Contract } from "ethers"; - -import { - ConnectV2Compound__factory, - ConnectV2PoolTogether__factory, - ConnectV2UniswapV2__factory, -} from "../../../typechain"; - -const DAI_TOKEN_ADDR = tokens.dai.address; // DAI Token - -// PoolTogether Address: https://docs.pooltogether.com/resources/networks/ethereum -const DAI_PRIZE_POOL_ADDR = "0xEBfb47A7ad0FD6e57323C8A42B2E5A6a4F68fc1a"; // DAI Prize Pool -const PT_DAI_TICKET_ADDR = "0x334cBb5858417Aee161B53Ee0D5349cCF54514CF"; // PT DAI Ticket -const DAI_POOL_FAUCET_ADDR = "0xF362ce295F2A4eaE4348fFC8cDBCe8d729ccb8Eb"; // DAI POOL Faucet -const POOL_TOKEN_ADDRESS = "0x0cEC1A9154Ff802e7934Fc916Ed7Ca50bDE6844e"; // POOL Tocken -const TOKEN_FAUCET_PROXY_FACTORY_ADDR = - "0xE4E9cDB3E139D7E8a41172C20b6Ed17b6750f117"; // TokenFaucetProxyFactory for claimAll -const DAI_POD_ADDR = "0x2f994e2E4F3395649eeE8A89092e63Ca526dA829"; // DAI Pod -const UNISWAP_POOLETHLP_PRIZE_POOL_ADDR = - "0x3AF7072D29Adde20FC7e173a7CB9e45307d2FB0A"; // Uniswap Pool/ETH LP PrizePool -const UNISWAP_POOLETHLP_FAUCET_ADDR = - "0x9A29401EF1856b669f55Ae5b24505b3B6fAEb370"; // Uniswap Pool/ETH LP Faucet -const UNISWAP_POOLETHLP_TOKEN_ADDR = - "0x85cb0bab616fe88a89a35080516a8928f38b518b"; // Uniswap Pool/ETH Token -const PT_UNISWAP_POOLETHLP_TICKET_ADDR = - "0xeb8928ee92efb06c44d072a24c2bcb993b61e543"; // Pool Together Uniswap Pool/ETH LP Ticket -const POOL_PRIZE_POOL_ADDR = "0x396b4489da692788e327e2e4b2b0459a5ef26791"; // POOL Prize Pool -const PT_POOL_TICKET_ADDR = "0x27d22a7648e955e510a40bdb058333e9190d12d4"; // Pool Together POOL Ticket -const WETH_ADDR = "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"; // WETH -const DAI_POD_TOKEN_DROP = "0xc5209623E3dFdf9C0cCbe497c8012883C4147731"; - -// Community WETH Prize Pool (Rari): https://reference-app.pooltogether.com/pools/mainnet/0xa88ca010b32a54d446fc38091ddbca55750cbfc3/manage#stats -const WETH_PRIZE_POOL_ADDR = "0xa88ca010b32a54d446fc38091ddbca55750cbfc3"; // Community WETH Prize Pool (Rari) -const WETH_POOL_TICKET_ADDR = "0x9b5c30aeb9ce2a6a121cea9a85bc0d662f6d9b40"; // Community WETH Prize Pool Ticket (Rari) - -const prizePoolABI = [ - "function calculateEarlyExitFee( address from, address controlledToken, uint256 amount) external returns ( uint256 exitFee, uint256 burnedCredit)", -]; - -const podABI = [ - "function getEarlyExitFee(uint256 amount) external returns (uint256)", - "function balanceOfUnderlying(address user) external view returns (uint256 amount)", - "function drop() public returns (uint256)", - "function balanceOf(address account) external view returns (uint256)", -]; - -const POD_FACTORY_ADDRESS = "0x4e3a9f9fbafb2ec49727cffa2a411f7a0c1c4ce1"; -const podFactoryABI = [ - "function create( address _prizePool, address _ticket, address _faucet, address _manager, uint8 _decimals) external returns (address pod)", -]; - -const tokenDropABI = [ - "function claim(address user) external returns (uint256)", -]; - -describe("PoolTogether", function() { - const connectorName = "COMPOUND-TEST-A"; - const uniswapConnectorName = "UNISWAP-TEST-A"; - const ptConnectorName = "POOLTOGETHER-TEST-A"; - - let dsaWallet0: any; - let masterSigner: Signer; - let instaConnectorsV2: Contract; - let connector: any; - let ptConnector: any; - let uniswapConnector: any; - - const wallets = provider.getWallets(); - const [wallet0, wallet1, wallet2, wallet3] = wallets; - before(async () => { - masterSigner = await getMasterSigner(); - instaConnectorsV2 = await ethers.getContractAt( - abis.core.connectorsV2, - addresses.core.connectorsV2 - ); - - // Deploy and enable Compound Connector - connector = await deployAndEnableConnector({ - connectorName, - contractArtifact: ConnectV2Compound__factory, - signer: masterSigner, - connectors: instaConnectorsV2, - }); - - // Deploy and enable Pool Together Connector - ptConnector = await deployAndEnableConnector({ - connectorName: ptConnectorName, - contractArtifact: ConnectV2PoolTogether__factory, - signer: masterSigner, - connectors: instaConnectorsV2, - }); - - // Deploy and enable Uniswap Connector - uniswapConnector = await deployAndEnableConnector({ - connectorName: uniswapConnectorName, - contractArtifact: ConnectV2UniswapV2__factory, - signer: masterSigner, - connectors: instaConnectorsV2, - }); - }); - - it("Should have contracts deployed.", async function() { - expect(!!instaConnectorsV2.address).to.be.true; - expect(!!connector.address).to.be.true; - expect(!!ptConnector.address).to.be.true; - expect(!!uniswapConnector.address).to.be.true; - expect(!!(await masterSigner.getAddress())).to.be.true; - }); - - describe("DSA wallet setup", function() { - it("Should build DSA v2", async function() { - dsaWallet0 = await buildDSAv2(wallet0.address); - expect(!!dsaWallet0.address).to.be.true; - }); - - it("Deposit 10 ETH into DSA wallet", async function() { - await wallet0.sendTransaction({ - to: dsaWallet0.address, - value: ethers.utils.parseEther("10"), - }); - expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte( - ethers.utils.parseEther("10") - ); - }); - }); - - describe("Main - DAI Prize Pool Test", function() { - it("Should deposit 1 ETH in Compound", async function() { - const amount = ethers.utils.parseEther("1"); // 1 ETH - const spells = [ - { - connector: connectorName, - method: "deposit", - args: ["ETH-A", amount, 0, 0], - }, - ]; - - const tx = await dsaWallet0 - .connect(wallet0) - .cast(...encodeSpells(spells), wallet1.address); - const receipt = await tx.wait(); - expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.lte( - ethers.utils.parseEther("9") - ); - }); - - it("Should borrow 100 DAI from Compound and deposit DAI into DAI Prize Pool", async function() { - const amount = ethers.utils.parseEther("100"); // 100 DAI - const setId = "83478237"; - const spells = [ - { - connector: connectorName, - method: "borrow", - args: ["DAI-A", amount, 0, setId], - }, - { - connector: ptConnectorName, - method: "depositTo", - args: [DAI_PRIZE_POOL_ADDR, amount, PT_DAI_TICKET_ADDR, setId, 0], - }, - ]; - // Before Spell - let daiToken = await ethers.getContractAt( - abis.basic.erc20, - DAI_TOKEN_ADDR - ); - let daiBalance = await daiToken.balanceOf(dsaWallet0.address); - expect(daiBalance, `DAI balance is 0`).to.be.eq( - ethers.utils.parseEther("0") - ); - - let cToken = await ethers.getContractAt( - abis.basic.erc20, - PT_DAI_TICKET_ADDR - ); - const balance = await cToken.balanceOf(dsaWallet0.address); - expect(balance, `PoolTogether DAI Ticket balance is 0`).to.be.eq(0); - - // Run spell transaction - const tx = await dsaWallet0 - .connect(wallet0) - .cast(...encodeSpells(spells), wallet1.address); - const receipt = await tx.wait(); - - // After spell - daiBalance = await daiToken.balanceOf(dsaWallet0.address); - expect( - daiBalance, - `Expect DAI balance to still equal 0 since it was deposited into Prize Pool` - ).to.be.eq(0); - - const balanceAfter = await cToken.balanceOf(dsaWallet0.address); - expect( - balanceAfter, - `PoolTogether DAI Ticket balance equals 100` - ).to.be.eq(ethers.utils.parseEther("100")); - - // ETH used for transaction - expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.lte( - ethers.utils.parseEther("9") - ); - }); - - it("Should wait 11 days, withdraw all PrizePool, get back 100 DAI, and claim POOL", async function() { - const amount = ethers.utils.parseEther("100"); // 100 DAI - - let prizePoolContract = new ethers.Contract( - DAI_PRIZE_POOL_ADDR, - prizePoolABI, - ethers.provider - ); - let earlyExitFee = await prizePoolContract.callStatic[ - "calculateEarlyExitFee" - ](dsaWallet0.address, PT_DAI_TICKET_ADDR, amount); - expect( - earlyExitFee.exitFee, - "Exit Fee equal to 1 DAI because starts at 10%" - ).to.be.eq(ethers.utils.parseEther("1")); - - const spells = [ - { - connector: ptConnectorName, - method: "withdrawInstantlyFrom", - args: [ - DAI_PRIZE_POOL_ADDR, - amount, - PT_DAI_TICKET_ADDR, - earlyExitFee.exitFee, - 0, - 0, - ], - }, - { - connector: ptConnectorName, - method: "claim", - args: [DAI_POOL_FAUCET_ADDR, 0], - }, - ]; - - // Before spell - let daiToken = await ethers.getContractAt( - abis.basic.erc20, - DAI_TOKEN_ADDR - ); - let daiBalance = await daiToken.balanceOf(dsaWallet0.address); - expect(daiBalance, `DAI balance equals 0`).to.be.eq( - ethers.utils.parseEther("0") - ); - - let cToken = await ethers.getContractAt( - abis.basic.erc20, - PT_DAI_TICKET_ADDR - ); - const balance = await cToken.balanceOf(dsaWallet0.address); - expect(balance, `PoolTogether Dai Ticket is 100`).to.be.eq( - ethers.utils.parseEther("100") - ); - - let poolToken = await ethers.getContractAt( - abis.basic.erc20, - POOL_TOKEN_ADDRESS - ); - const poolBalance = await poolToken.balanceOf(dsaWallet0.address); - expect(poolBalance, `POOL Token equals 0`).to.be.eq( - ethers.utils.parseEther("0") - ); - - // Increase time by 11 days so we get back all DAI without early withdrawal fee - await ethers.provider.send("evm_increaseTime", [11 * 24 * 60 * 60]); - - earlyExitFee = await prizePoolContract.callStatic[ - "calculateEarlyExitFee" - ](dsaWallet0.address, PT_DAI_TICKET_ADDR, amount); - expect( - earlyExitFee.exitFee, - "Exit Fee equal to 0 DAI because past 10 days" - ).to.be.eq(0); - - // Run spell transaction - const tx = await dsaWallet0 - .connect(wallet0) - .cast(...encodeSpells(spells), wallet1.address); - const receipt = await tx.wait(); - - // After spell - daiBalance = await daiToken.balanceOf(dsaWallet0.address); - expect( - daiBalance, - `DAI balance to be equal to 100, because of no early withdrawal fee` - ).to.be.eq(ethers.utils.parseEther("100")); - - const balanceAfter = await cToken.balanceOf(dsaWallet0.address); - expect(balanceAfter, `PoolTogether Dai Ticket to equal 0`).to.be.eq(0); - - const poolBalanceAfter = await poolToken.balanceOf(dsaWallet0.address); - expect( - poolBalanceAfter, - `POOL Token Balance to be greater than 0` - ).to.be.gt(ethers.utils.parseEther("0")); - }); - - it("Should deposit and withdraw all PrizePool, get back less than 100 DAI", async function() { - const amount = ethers.utils.parseEther("100"); // 100 DAI - const exitFee = ethers.utils.parseEther("1"); // 1 DAI is 10% of 100 DAI - const spells = [ - { - connector: ptConnectorName, - method: "depositTo", - args: [DAI_PRIZE_POOL_ADDR, amount, PT_DAI_TICKET_ADDR, 0, 0], - }, - { - connector: ptConnectorName, - method: "withdrawInstantlyFrom", - args: [ - DAI_PRIZE_POOL_ADDR, - amount, - PT_DAI_TICKET_ADDR, - exitFee, - 0, - 0, - ], - }, - ]; - - // Before spell - let daiToken = await ethers.getContractAt( - abis.basic.erc20, - DAI_TOKEN_ADDR - ); - let daiBalance = await daiToken.balanceOf(dsaWallet0.address); - expect(daiBalance, `DAI Balance equals 0`).to.be.eq( - ethers.utils.parseEther("100") - ); - - let cToken = await ethers.getContractAt( - abis.basic.erc20, - PT_DAI_TICKET_ADDR - ); - const balance = await cToken.balanceOf(dsaWallet0.address); - expect(balance, `PoolTogether DAI Ticket equals 0`).to.be.eq(0); - - let poolToken = await ethers.getContractAt( - abis.basic.erc20, - POOL_TOKEN_ADDRESS - ); - const poolBalance = await poolToken.balanceOf(dsaWallet0.address); - expect(poolBalance, `PoolTogether Token greater than 0`).to.be.gt(0); - - // Run spell transaction - const tx = await dsaWallet0 - .connect(wallet0) - .cast(...encodeSpells(spells), wallet1.address); - const receipt = await tx.wait(); - - // After spell - daiBalance = await daiToken.balanceOf(dsaWallet0.address); - expect( - daiBalance, - `DAI balance to be less than 100, because of early withdrawal fee` - ).to.be.lt(ethers.utils.parseEther("100")); - - const balanceAfter = await cToken.balanceOf(dsaWallet0.address); - expect(balanceAfter, `PoolTogether Dai Ticket to equal 0`).to.be.eq(0); - - const poolBalanceAfter = await poolToken.balanceOf(dsaWallet0.address); - expect(poolBalanceAfter, `POOL Token Balance to greater than 0`).to.be.gt( - ethers.utils.parseEther("0") - ); - }); - - it("Should deposit, wait 11 days, and withdraw all PrizePool, get 99 DAI, and claim all POOL using claimAll", async function() { - const amount = ethers.utils.parseEther("99"); // 99 DAI - const depositSpells = [ - { - connector: ptConnectorName, - method: "depositTo", - args: [DAI_PRIZE_POOL_ADDR, amount, PT_DAI_TICKET_ADDR, 0, 0], - }, - ]; - - // Before spell - let daiToken = await ethers.getContractAt( - abis.basic.erc20, - DAI_TOKEN_ADDR - ); - let daiBalance = await daiToken.balanceOf(dsaWallet0.address); - expect(daiBalance, `DAI balance less than 100`).to.be.lt( - ethers.utils.parseEther("100") - ); - - let cToken = await ethers.getContractAt( - abis.basic.erc20, - PT_DAI_TICKET_ADDR - ); - const balance = await cToken.balanceOf(dsaWallet0.address); - expect(balance, `PoolTogether DAI Ticket equal 0`).to.be.eq(0); - - let poolToken = await ethers.getContractAt( - abis.basic.erc20, - POOL_TOKEN_ADDRESS - ); - const poolBalance = await poolToken.balanceOf(dsaWallet0.address); - expect(poolBalance, `POOL Token is greater than 0`).to.be.gt( - ethers.utils.parseEther("0") - ); - - // Run spell transaction - const tx = await dsaWallet0 - .connect(wallet0) - .cast(...encodeSpells(depositSpells), wallet1.address); - const receipt = await tx.wait(); - - const prizePoolContract = new ethers.Contract( - DAI_PRIZE_POOL_ADDR, - prizePoolABI, - ethers.provider - ); - let earlyExitFee = await prizePoolContract.callStatic[ - "calculateEarlyExitFee" - ](dsaWallet0.address, PT_DAI_TICKET_ADDR, amount); - expect( - earlyExitFee.exitFee, - "Exit Fee equal to .99 DAI because starts at 10%" - ).to.be.eq(ethers.utils.parseEther(".99")); - - // Increase time by 11 days so we get back all DAI without early withdrawal fee - await ethers.provider.send("evm_increaseTime", [11 * 24 * 60 * 60]); - - earlyExitFee = await prizePoolContract.callStatic[ - "calculateEarlyExitFee" - ](dsaWallet0.address, PT_DAI_TICKET_ADDR, amount); - expect( - earlyExitFee.exitFee, - "Exit Fee equal to 0 DAI because past 10 days" - ).to.be.eq(0); - - const withdrawSpells = [ - { - connector: ptConnectorName, - method: "withdrawInstantlyFrom", - args: [ - DAI_PRIZE_POOL_ADDR, - amount, - PT_DAI_TICKET_ADDR, - earlyExitFee.exitFee, - 0, - 0, - ], - }, - { - connector: ptConnectorName, - method: "claimAll", - args: [TOKEN_FAUCET_PROXY_FACTORY_ADDR, [DAI_POOL_FAUCET_ADDR]], - }, - ]; - - // Run spell transaction - const tx2 = await dsaWallet0 - .connect(wallet0) - .cast(...encodeSpells(withdrawSpells), wallet1.address); - const receipt2 = await tx2.wait(); - - // After spell - daiBalance = await daiToken.balanceOf(dsaWallet0.address); - expect(daiBalance, `DAI balance equals 99`).to.be.eq( - ethers.utils.parseEther("99") - ); - - const balanceAfter = await cToken.balanceOf(dsaWallet0.address); - expect(balanceAfter, `PoolTogether DAI Ticket equal 0`).to.be.eq(0); - - // Expect - const poolBalanceAfter = await poolToken.balanceOf(dsaWallet0.address); - expect(poolBalanceAfter, `Pool Token to be greateir than 0`).to.be.gt( - ethers.utils.parseEther("0") - ); - }); - }); - - describe("Main - DAI Pod Test", function() { - it("Should deposit 99 DAI in DAI Pod", async function() { - const amount = ethers.utils.parseEther("99"); // 99 DAI - const spells = [ - { - connector: ptConnectorName, - method: "depositToPod", - args: [DAI_TOKEN_ADDR, DAI_POD_ADDR, amount, 0, 0], - }, - ]; - - // Before spell - let daiToken = await ethers.getContractAt( - abis.basic.erc20, - DAI_TOKEN_ADDR - ); - let daiBalance = await daiToken.balanceOf(dsaWallet0.address); - expect(daiBalance, `DAI balance equals 99`).to.be.eq( - ethers.utils.parseEther("99") - ); - - let poolToken = await ethers.getContractAt( - abis.basic.erc20, - POOL_TOKEN_ADDRESS - ); - const poolBalance = await poolToken.balanceOf(dsaWallet0.address); - expect(poolBalance, `POOL Token greater than 0`).to.be.gt(0); - - let podToken = await ethers.getContractAt(abis.basic.erc20, DAI_POD_ADDR); - const podBalance = await podToken.balanceOf(dsaWallet0.address); - expect(podBalance, `Pod DAI Token equals 0`).to.be.eq(0); - - // Run spell transaction - const tx = await dsaWallet0 - .connect(wallet0) - .cast(...encodeSpells(spells), wallet1.address); - const receipt = await tx.wait(); - - // After spell - daiBalance = await daiToken.balanceOf(dsaWallet0.address); - expect(daiBalance, `DAI equals 0`).to.be.eq(0); - - const poolBalanceAfter = await poolToken.balanceOf(dsaWallet0.address); - expect(poolBalanceAfter, `POOL Token greater than 0`).to.be.gt(0); - - const podBalanceAfter = await podToken.balanceOf(dsaWallet0.address); - expect(podBalanceAfter, `Pod DAI token greater than 0`).to.be.eq( - ethers.utils.parseEther("99") - ); - }); - - it("Should claim rewards from pod token drop", async function() { - const spells = [ - { - connector: ptConnectorName, - method: "claimPodTokenDrop", - args: [DAI_POD_TOKEN_DROP, 0], - }, - ]; - - const tokenDropContract = new ethers.Contract( - DAI_POD_TOKEN_DROP, - tokenDropABI, - ethers.provider - ); - const podContract = new ethers.Contract( - DAI_POD_ADDR, - podABI, - masterSigner - ); - - // drop(): Claim TokenDrop asset for PrizePool Pod and transfers token(s) to external Pod TokenDrop - // dropt() also calls batch which, Deposit Pod float into PrizePool. Deposits the current float - // amount into the PrizePool and claims current POOL rewards. - const dropTx = await podContract.drop(); - await dropTx.wait(); - - // POOL Rewards able to claim from Pod Token Drop - let claimAmount = await tokenDropContract.callStatic["claim"]( - dsaWallet0.address - ); - - // Before spell - let poolToken = await ethers.getContractAt( - abis.basic.erc20, - POOL_TOKEN_ADDRESS - ); - const poolBalance = await poolToken.balanceOf(dsaWallet0.address); - expect(poolBalance, `POOL Token greater than 0`).to.be.gt(0); - - // Run spell transaction - const tx = await dsaWallet0 - .connect(wallet0) - .cast(...encodeSpells(spells), wallet1.address); - const receipt = await tx.wait(); - - // After spell - const poolBalanceAfter = await poolToken.balanceOf(dsaWallet0.address); - const total = claimAmount.add(poolBalance); - expect(poolBalanceAfter, `POOL Token same as before spell`).to.be.eq( - total - ); - }); - - it("Should wait 11 days, withdraw all podTokens, get back 99 DAI", async function() { - const amount = ethers.utils.parseEther("99"); // 99 DAI - - const podContract = new ethers.Contract( - DAI_POD_ADDR, - podABI, - ethers.provider - ); - let maxFee = await podContract.callStatic["getEarlyExitFee"](amount); - // maxFee depends on if token has been deposited to PrizePool yet - // since we called drop in previous test case, the tokens were deposited to PrizePool - expect( - maxFee, - "Exit Fee equal to .99 DAI because token still in float" - ).to.be.eq(ethers.utils.parseEther(".99")); - - const spells = [ - { - connector: ptConnectorName, - method: "withdrawFromPod", - args: [DAI_POD_ADDR, amount, maxFee, 0, 0], - }, - ]; - - // Before spell - let daiToken = await ethers.getContractAt( - abis.basic.erc20, - DAI_TOKEN_ADDR - ); - let daiBalance = await daiToken.balanceOf(dsaWallet0.address); - expect(daiBalance, `DAI Balance equals 0`).to.be.eq(0); - - let poolToken = await ethers.getContractAt( - abis.basic.erc20, - POOL_TOKEN_ADDRESS - ); - const poolBalance = await poolToken.balanceOf(dsaWallet0.address); - expect(poolBalance, `POOL Token balance greater than 0`).to.be.gt(0); - - let podToken = await ethers.getContractAt(abis.basic.erc20, DAI_POD_ADDR); - const podBalance = await podToken.balanceOf(dsaWallet0.address); - expect(podBalance, `Pod DAI Token equals 99`).to.be.eq( - ethers.utils.parseEther("99") - ); - - // Increase time by 11 days so we get back all DAI without early withdrawal fee - await ethers.provider.send("evm_increaseTime", [11 * 24 * 60 * 60]); - - // Run spell transaction - const tx = await dsaWallet0 - .connect(wallet0) - .cast(...encodeSpells(spells), wallet1.address); - const receipt = await tx.wait(); - - // After spell - daiBalance = await daiToken.balanceOf(dsaWallet0.address); - expect( - daiBalance, - `DAI balance equals 99, because of no early withdrawal fee` - ).to.be.eq(ethers.utils.parseEther("99")); - - const poolBalanceAfter = await poolToken.balanceOf(dsaWallet0.address); - expect(poolBalanceAfter, `POOL Token to be greater than 0`).to.be.gt(0); - - const podBalanceAfter = await podToken.balanceOf(dsaWallet0.address); - expect(podBalanceAfter, `Pod DAI Token equals 0`).to.be.eq(0); - }); - - it("Should deposit and withdraw from pod, get back same amount of 99 DAI", async function() { - const amount = ethers.utils.parseEther("99"); - const maxFee = 0; // maxFee 0 since it doesn't give chance for Pod to actually deposit into PrizePool - - const spells = [ - { - connector: ptConnectorName, - method: "depositToPod", - args: [DAI_TOKEN_ADDR, DAI_POD_ADDR, amount, 0, 0], - }, - { - connector: ptConnectorName, - method: "withdrawFromPod", - args: [DAI_POD_ADDR, amount, maxFee, 0, 0], - }, - ]; - - // Before spell - let daiToken = await ethers.getContractAt( - abis.basic.erc20, - DAI_TOKEN_ADDR - ); - let daiBalance = await daiToken.balanceOf(dsaWallet0.address); - expect(daiBalance, `DAI equals 99`).to.be.eq( - ethers.utils.parseEther("99") - ); - - let poolToken = await ethers.getContractAt( - abis.basic.erc20, - POOL_TOKEN_ADDRESS - ); - const poolBalance = await poolToken.balanceOf(dsaWallet0.address); - expect(poolBalance, `POOL Token greater than 0`).to.be.gt(0); - - // PodToken is 0 - let podToken = await ethers.getContractAt(abis.basic.erc20, DAI_POD_ADDR); - const podBalance = await podToken.balanceOf(dsaWallet0.address); - expect(podBalance, `Pod DAI Token equals 0`).to.be.eq(0); - - // Run spell transaction - const tx = await dsaWallet0 - .connect(wallet0) - .cast(...encodeSpells(spells), wallet1.address); - const receipt = await tx.wait(); - - // After spell - daiBalance = await daiToken.balanceOf(dsaWallet0.address); - expect( - daiBalance, - `DAI balance to be equal to 99, because funds still in 'float` - ).to.be.eq(ethers.utils.parseEther("99")); - - const poolBalanceAfter = await poolToken.balanceOf(dsaWallet0.address); - expect(poolBalanceAfter, `POOL Token same as before spell`).to.be.eq( - poolBalance - ); - - // Expect Pod Token Balance to equal 0 - const podBalanceAfter = await podToken.balanceOf(dsaWallet0.address); - expect(podBalanceAfter, `Pod DAI Token equals 0`).to.be.eq( - ethers.utils.parseEther("0") - ); - }); - }); - - describe("Main - UNISWAP POOL/ETH Prize Pool Test", function() { - it("Should use uniswap to swap ETH for POOL, deposit to POOL/ETH LP, deposit POOL/ETH LP to PrizePool", async function() { - const amount = ethers.utils.parseEther("100"); // 100 POOL - const slippage = ethers.utils.parseEther("0.03"); - const setId = "83478237"; - - const UniswapV2Router02ABI = [ - "function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts)", - ]; - - // Get amount of ETH for 100 POOL from Uniswap - const UniswapV2Router02 = await ethers.getContractAt( - UniswapV2Router02ABI, - "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D" - ); - const amounts = await UniswapV2Router02.getAmountsOut(amount, [ - POOL_TOKEN_ADDRESS, - WETH_ADDR, - ]); - const unitAmount = ethers.utils.parseEther( - ((amounts[1] * 1.03) / amounts[0]).toString() - ); - - const spells = [ - { - connector: uniswapConnectorName, - method: "buy", - args: [ - POOL_TOKEN_ADDRESS, - tokens.eth.address, - amount, - unitAmount, - 0, - setId, - ], - }, - { - connector: uniswapConnectorName, - method: "deposit", - args: [ - POOL_TOKEN_ADDRESS, - tokens.eth.address, - amount, - unitAmount, - slippage, - 0, - setId, - ], - }, - { - connector: ptConnectorName, - method: "depositTo", - args: [ - UNISWAP_POOLETHLP_PRIZE_POOL_ADDR, - 0, - PT_UNISWAP_POOLETHLP_TICKET_ADDR, - setId, - 0, - ], - }, - ]; - - // Before Spell - let ethBalance = await ethers.provider.getBalance(dsaWallet0.address); - expect(ethBalance, `ETH Balance equals 9`).to.be.eq( - ethers.utils.parseEther("9") - ); - - let poolToken = await ethers.getContractAt( - abis.basic.erc20, - POOL_TOKEN_ADDRESS - ); - const poolBalance = await poolToken.balanceOf(dsaWallet0.address); - expect(poolBalance, `POOL Token greater than 0`).to.be.gt(0); - - let uniswapLPToken = await ethers.getContractAt( - abis.basic.erc20, - UNISWAP_POOLETHLP_TOKEN_ADDR - ); - const uniswapPoolEthBalance = await uniswapLPToken.balanceOf( - dsaWallet0.address - ); - expect(uniswapPoolEthBalance, `Uniswap POOL/ETH LP equals 0`).to.be.eq(0); - - let ptUniswapPoolEthToken = await ethers.getContractAt( - abis.basic.erc20, - PT_UNISWAP_POOLETHLP_TICKET_ADDR - ); - const ptUniswapPoolEthBalance = await ptUniswapPoolEthToken.balanceOf( - dsaWallet0.address - ); - expect( - ptUniswapPoolEthBalance, - `PoolTogether Uniswap POOL?ETH LP equals 0` - ).to.be.eq(0); - - // Run spell transaction - const tx = await dsaWallet0 - .connect(wallet0) - .cast(...encodeSpells(spells), wallet1.address); - const receipt = await tx.wait(); - - // After spell - ethBalance = await ethers.provider.getBalance(dsaWallet0.address); - expect(ethBalance, `ETH Balance less than 9`).to.be.lt( - ethers.utils.parseEther("9") - ); - - const poolBalanceAfter = await poolToken.balanceOf(dsaWallet0.address); - expect(poolBalanceAfter, `POOL Token to be same after spell`).to.be.eq( - poolBalance - ); - - const uniswapPoolEthBalanceAfter = await uniswapLPToken.balanceOf( - dsaWallet0.address - ); - expect( - uniswapPoolEthBalanceAfter, - `Uniswap POOL/ETH LP equals 0` - ).to.be.eq(0); - - const ptUniswapPoolEthBalanceAfter = await ptUniswapPoolEthToken.balanceOf( - dsaWallet0.address - ); - expect( - ptUniswapPoolEthBalanceAfter, - `PT Uniswap POOL/ETH LP to greater than 0` - ).to.be.gt(0); - }); - - it("Should withdraw all PrizePool, get back Uniswap LP, claim POOL, deposit claimed POOL into Pool PrizePool", async function() { - let ptUniswapPoolEthToken = await ethers.getContractAt( - abis.basic.erc20, - PT_UNISWAP_POOLETHLP_TICKET_ADDR - ); - const ptUniswapPoolEthBalance = await ptUniswapPoolEthToken.balanceOf( - dsaWallet0.address - ); - const setId = "83478237"; - - let uniswapPrizePoolContract = new ethers.Contract( - UNISWAP_POOLETHLP_PRIZE_POOL_ADDR, - prizePoolABI, - ethers.provider - ); - let earlyExitFee = await uniswapPrizePoolContract.callStatic[ - "calculateEarlyExitFee" - ]( - dsaWallet0.address, - PT_UNISWAP_POOLETHLP_TICKET_ADDR, - ptUniswapPoolEthBalance - ); - expect( - earlyExitFee.exitFee, - "Exit Fee equals 0 because no early exit fee for this prize pool" - ).to.be.eq(0); - - const spells = [ - { - connector: ptConnectorName, - method: "withdrawInstantlyFrom", - args: [ - UNISWAP_POOLETHLP_PRIZE_POOL_ADDR, - ptUniswapPoolEthBalance, - PT_UNISWAP_POOLETHLP_TICKET_ADDR, - earlyExitFee.exitFee, - 0, - 0, - ], - }, - { - connector: ptConnectorName, - method: "claim", - args: [UNISWAP_POOLETHLP_FAUCET_ADDR, setId], - }, - { - connector: ptConnectorName, - method: "depositTo", - args: [POOL_PRIZE_POOL_ADDR, 0, PT_POOL_TICKET_ADDR, setId, 0], - }, - ]; - - // Before spell - let poolToken = await ethers.getContractAt( - abis.basic.erc20, - POOL_TOKEN_ADDRESS - ); - const poolBalance = await poolToken.balanceOf(dsaWallet0.address); - expect(poolBalance, `POOL Token greater than 0`).to.be.gt(0); - - // Uniswap POOL/ETH LP is 0 - let uniswapLPToken = await ethers.getContractAt( - abis.basic.erc20, - UNISWAP_POOLETHLP_TOKEN_ADDR - ); - const uniswapPoolEthBalance = await uniswapLPToken.balanceOf( - dsaWallet0.address - ); - expect(uniswapPoolEthBalance, `Uniswap POOL/ETH LP equals 0`).to.be.eq(0); - - expect( - ptUniswapPoolEthBalance, - `PT Uniswap POOL/ETH LP greater than 0` - ).to.be.gt(0); - - let poolPoolTicket = await ethers.getContractAt( - abis.basic.erc20, - PT_POOL_TICKET_ADDR - ); - const poolPoolTicketBalance = await poolPoolTicket.balanceOf( - dsaWallet0.address - ); - expect( - poolPoolTicketBalance, - `PoolTogether POOL Ticket equals 0` - ).to.be.eq(0); - - // Run spell transaction - const tx = await dsaWallet0 - .connect(wallet0) - .cast(...encodeSpells(spells), wallet1.address); - const receipt = await tx.wait(); - - // After spell - const poolBalanceAfter = await poolToken.balanceOf(dsaWallet0.address); - expect( - poolBalanceAfter, - `Pool Token Balance equal to balance before spell` - ).to.be.eq(poolBalance); - - const uniswapPoolEthBalanceAfter = await uniswapLPToken.balanceOf( - dsaWallet0.address - ); - expect( - uniswapPoolEthBalanceAfter, - `Uniswap POOL/ETH LP to greater than 0` - ).to.be.gt(0); - - const ptUniswapPoolEthBalanceAfter = await ptUniswapPoolEthToken.balanceOf( - dsaWallet0.address - ); - expect( - ptUniswapPoolEthBalanceAfter, - `PT Uniswap POOL/ETH LP equal 0` - ).to.be.eq(0); - - const poolPoolTicketBalanceAfter = await poolPoolTicket.balanceOf( - dsaWallet0.address - ); - expect( - poolPoolTicketBalanceAfter, - `PoolTogether POOL Ticket greater than 0` - ).to.be.gt(0); - }); - }); - - describe("Main - WETH Prize Pool Test", function() { - it("Deposit 1 ETH into WETH Prize Pool and withdraw immediately", async function() { - const amount = ethers.utils.parseEther("1"); // 1 ETH - const setId = "83478237"; - const spells = [ - { - connector: ptConnectorName, - method: "depositTo", - args: [WETH_PRIZE_POOL_ADDR, amount, WETH_POOL_TICKET_ADDR, 0, setId], - }, - { - connector: ptConnectorName, - method: "withdrawInstantlyFrom", - args: [ - WETH_PRIZE_POOL_ADDR, - amount, - WETH_POOL_TICKET_ADDR, - amount, - setId, - 0, - ], - }, - ]; - // Before Spell - const ethBalanceBefore = await ethers.provider.getBalance( - dsaWallet0.address - ); - - // Run spell transaction - const tx = await dsaWallet0 - .connect(wallet0) - .cast(...encodeSpells(spells), wallet1.address); - const receipt = await tx.wait(); - - // After spell - const ethBalanceAfter = await ethers.provider.getBalance( - dsaWallet0.address - ); - - // ETH used for transaction - expect( - ethBalanceAfter, - `ETH Balance less than before spell because of early withdrawal fee` - ).to.be.lte(ethBalanceBefore); - }); - - it("Deposit 1 ETH into WETH Prize Pool, wait 14 days, then withdraw", async function() { - const amount = ethers.utils.parseEther("1"); // 1 ETH - const depositSpell = [ - { - connector: ptConnectorName, - method: "depositTo", - args: [WETH_PRIZE_POOL_ADDR, amount, WETH_POOL_TICKET_ADDR, 0, 0], - }, - ]; - - const withdrawSpell = [ - { - connector: ptConnectorName, - method: "withdrawInstantlyFrom", - args: [ - WETH_PRIZE_POOL_ADDR, - amount, - WETH_POOL_TICKET_ADDR, - amount, - 0, - 0, - ], - }, - ]; - - // Before Deposit Spell - let ethBalanceBefore = await ethers.provider.getBalance( - dsaWallet0.address - ); - - // Run deposit spell transaction - const tx = await dsaWallet0 - .connect(wallet0) - .cast(...encodeSpells(depositSpell), wallet1.address); - const receipt = await tx.wait(); - - // After Deposit spell - let ethBalanceAfter = await ethers.provider.getBalance( - dsaWallet0.address - ); - - expect(ethBalanceAfter, `ETH Balance less than before spell`).to.be.lte( - ethBalanceBefore - ); - - // Increase time by 11 days so we get back all ETH without early withdrawal fee - await ethers.provider.send("evm_increaseTime", [14 * 24 * 60 * 60]); - - // Run withdraw spell transaction - const tx2 = await dsaWallet0 - .connect(wallet0) - .cast(...encodeSpells(withdrawSpell), wallet1.address); - const receipt2 = await tx.wait(); - - // After Deposit spell - ethBalanceAfter = await ethers.provider.getBalance(dsaWallet0.address); - - expect( - ethBalanceAfter, - `ETH Balance equal to before spell because no early exit fee` - ).to.be.eq(ethBalanceBefore); - }); - }); - - describe("Main - WETH Pod Test", function() { - let podAddress: string; - it("Should deposit 1 ETH in WETH Pod and get Pod Ticket", async function() { - const amount = ethers.utils.parseEther("1"); - - // Create Pod for WETH Prize Pool (Rari) - const podFactoryContract = new ethers.Contract( - POD_FACTORY_ADDRESS, - podFactoryABI, - masterSigner - ); - podAddress = await podFactoryContract.callStatic.create( - WETH_PRIZE_POOL_ADDR, - WETH_POOL_TICKET_ADDR, - constants.address_zero, - wallet0.address, - 18 - ); - await podFactoryContract.create( - WETH_PRIZE_POOL_ADDR, - WETH_POOL_TICKET_ADDR, - constants.address_zero, - wallet0.address, - 18 - ); - - const spells = [ - { - connector: ptConnectorName, - method: "depositToPod", - args: [WETH_ADDR, podAddress, amount, 0, 0], - }, - ]; - - // Before Deposit Spell - const podContract = new ethers.Contract( - podAddress, - podABI, - ethers.provider - ); - let podBalanceBefore = await podContract.balanceOfUnderlying( - dsaWallet0.address - ); - expect(podBalanceBefore, `Pod balance equal to 0`).to.be.eq(0); - - let ethBalanceBefore = await ethers.provider.getBalance( - dsaWallet0.address - ); - - // Run spell transaction - const tx = await dsaWallet0 - .connect(wallet0) - .cast(...encodeSpells(spells), wallet1.address); - const receipt = await tx.wait(); - - // After Deposit spell - let ethBalanceAfter = await ethers.provider.getBalance( - dsaWallet0.address - ); - expect(ethBalanceAfter, `ETH balance less than before`).to.be.lt( - ethBalanceBefore - ); - - let podBalanceAfter = await podContract.balanceOfUnderlying( - dsaWallet0.address - ); - expect(podBalanceAfter, `Pod balance equal to 1`).to.be.eq( - ethers.utils.parseEther("1") - ); - }); - - it("Should withdraw 1 Ticket from WETH Pod and get back ETH", async function() { - const amount = ethers.utils.parseEther("1"); - - const podContract = new ethers.Contract( - podAddress, - podABI, - ethers.provider - ); - let maxFee = await podContract.callStatic["getEarlyExitFee"](amount); - expect( - maxFee, - "Exit Fee equal to 0 DAI because token still in float" - ).to.be.eq(0); - // maxFee depends on if token has been deposited to PrizePool yet - - const spells = [ - { - connector: ptConnectorName, - method: "withdrawFromPod", - args: [podAddress, amount, maxFee, 0, 0], - }, - ]; - - // Before Deposit Spell - let podBalanceBefore = await podContract.balanceOfUnderlying( - dsaWallet0.address - ); - expect(podBalanceBefore, `Pod balance equal to 1`).to.be.eq( - ethers.utils.parseEther("1") - ); - - let ethBalanceBefore = await ethers.provider.getBalance( - dsaWallet0.address - ); - - // Run spell transaction - const tx = await dsaWallet0 - .connect(wallet0) - .cast(...encodeSpells(spells), wallet1.address); - const receipt = await tx.wait(); - - // After Deposit spell - let ethBalanceAfter = await ethers.provider.getBalance( - dsaWallet0.address - ); - expect(ethBalanceAfter, `ETH balance greater than before`).to.be.gt( - ethBalanceBefore - ); - - let podBalanceAfter = await podContract.balanceOfUnderlying( - dsaWallet0.address - ); - expect(podBalanceAfter, `Pod balance equal to 0`).to.be.eq( - ethers.utils.parseEther("0") - ); - }); - }); -}); +// import { expect } from "chai"; +// import hre from "hardhat"; +// const { web3, deployments, waffle, ethers } = hre; +// const { provider, deployContract } = waffle; + +// import { deployAndEnableConnector } from "../../../scripts/tests/deployAndEnableConnector"; +// import { buildDSAv2 } from "../../../scripts/tests/buildDSAv2"; +// import { encodeSpells } from "../../../scripts/tests/encodeSpells"; +// import { getMasterSigner } from "../../../scripts/tests/getMasterSigner"; + +// import { addresses } from "../../../scripts/constant/addresses"; +// import { abis } from "../../../scripts/constant/abis"; +// import { constants } from "../../../scripts/constant/constant"; +// import { tokens } from "../../../scripts/constant/tokens"; +// import type { Signer, Contract } from "ethers"; + +// import { +// ConnectV2Compound__factory, +// ConnectV2PoolTogether__factory, +// ConnectV2UniswapV2__factory, +// } from "../../../typechain"; + +// const DAI_TOKEN_ADDR = tokens.dai.address; // DAI Token + +// // PoolTogether Address: https://docs.pooltogether.com/resources/networks/ethereum +// const DAI_PRIZE_POOL_ADDR = "0xEBfb47A7ad0FD6e57323C8A42B2E5A6a4F68fc1a"; // DAI Prize Pool +// const PT_DAI_TICKET_ADDR = "0x334cBb5858417Aee161B53Ee0D5349cCF54514CF"; // PT DAI Ticket +// const DAI_POOL_FAUCET_ADDR = "0xF362ce295F2A4eaE4348fFC8cDBCe8d729ccb8Eb"; // DAI POOL Faucet +// const POOL_TOKEN_ADDRESS = "0x0cEC1A9154Ff802e7934Fc916Ed7Ca50bDE6844e"; // POOL Tocken +// const TOKEN_FAUCET_PROXY_FACTORY_ADDR = +// "0xE4E9cDB3E139D7E8a41172C20b6Ed17b6750f117"; // TokenFaucetProxyFactory for claimAll +// const DAI_POD_ADDR = "0x2f994e2E4F3395649eeE8A89092e63Ca526dA829"; // DAI Pod +// const UNISWAP_POOLETHLP_PRIZE_POOL_ADDR = +// "0x3AF7072D29Adde20FC7e173a7CB9e45307d2FB0A"; // Uniswap Pool/ETH LP PrizePool +// const UNISWAP_POOLETHLP_FAUCET_ADDR = +// "0x9A29401EF1856b669f55Ae5b24505b3B6fAEb370"; // Uniswap Pool/ETH LP Faucet +// const UNISWAP_POOLETHLP_TOKEN_ADDR = +// "0x85cb0bab616fe88a89a35080516a8928f38b518b"; // Uniswap Pool/ETH Token +// const PT_UNISWAP_POOLETHLP_TICKET_ADDR = +// "0xeb8928ee92efb06c44d072a24c2bcb993b61e543"; // Pool Together Uniswap Pool/ETH LP Ticket +// const POOL_PRIZE_POOL_ADDR = "0x396b4489da692788e327e2e4b2b0459a5ef26791"; // POOL Prize Pool +// const PT_POOL_TICKET_ADDR = "0x27d22a7648e955e510a40bdb058333e9190d12d4"; // Pool Together POOL Ticket +// const WETH_ADDR = "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"; // WETH +// const DAI_POD_TOKEN_DROP = "0xc5209623E3dFdf9C0cCbe497c8012883C4147731"; + +// // Community WETH Prize Pool (Rari): https://reference-app.pooltogether.com/pools/mainnet/0xa88ca010b32a54d446fc38091ddbca55750cbfc3/manage#stats +// const WETH_PRIZE_POOL_ADDR = "0xa88ca010b32a54d446fc38091ddbca55750cbfc3"; // Community WETH Prize Pool (Rari) +// const WETH_POOL_TICKET_ADDR = "0x9b5c30aeb9ce2a6a121cea9a85bc0d662f6d9b40"; // Community WETH Prize Pool Ticket (Rari) + +// const prizePoolABI = [ +// "function calculateEarlyExitFee( address from, address controlledToken, uint256 amount) external returns ( uint256 exitFee, uint256 burnedCredit)", +// ]; + +// const podABI = [ +// "function getEarlyExitFee(uint256 amount) external returns (uint256)", +// "function balanceOfUnderlying(address user) external view returns (uint256 amount)", +// "function drop() public returns (uint256)", +// "function balanceOf(address account) external view returns (uint256)", +// ]; + +// const POD_FACTORY_ADDRESS = "0x4e3a9f9fbafb2ec49727cffa2a411f7a0c1c4ce1"; +// const podFactoryABI = [ +// "function create( address _prizePool, address _ticket, address _faucet, address _manager, uint8 _decimals) external returns (address pod)", +// ]; + +// const tokenDropABI = [ +// "function claim(address user) external returns (uint256)", +// ]; + +// describe("PoolTogether", function() { +// const connectorName = "COMPOUND-TEST-A"; +// const uniswapConnectorName = "UNISWAP-TEST-A"; +// const ptConnectorName = "POOLTOGETHER-TEST-A"; + +// let dsaWallet0: any; +// let masterSigner: Signer; +// let instaConnectorsV2: Contract; +// let connector: any; +// let ptConnector: any; +// let uniswapConnector: any; + +// const wallets = provider.getWallets(); +// const [wallet0, wallet1, wallet2, wallet3] = wallets; +// before(async () => { +// masterSigner = await getMasterSigner(); +// instaConnectorsV2 = await ethers.getContractAt( +// abis.core.connectorsV2, +// addresses.core.connectorsV2 +// ); + +// // Deploy and enable Compound Connector +// connector = await deployAndEnableConnector({ +// connectorName, +// contractArtifact: ConnectV2Compound__factory, +// signer: masterSigner, +// connectors: instaConnectorsV2, +// }); + +// // Deploy and enable Pool Together Connector +// ptConnector = await deployAndEnableConnector({ +// connectorName: ptConnectorName, +// contractArtifact: ConnectV2PoolTogether__factory, +// signer: masterSigner, +// connectors: instaConnectorsV2, +// }); + +// // Deploy and enable Uniswap Connector +// uniswapConnector = await deployAndEnableConnector({ +// connectorName: uniswapConnectorName, +// contractArtifact: ConnectV2UniswapV2__factory, +// signer: masterSigner, +// connectors: instaConnectorsV2, +// }); +// }); + +// it("Should have contracts deployed.", async function() { +// expect(!!instaConnectorsV2.address).to.be.true; +// expect(!!connector.address).to.be.true; +// expect(!!ptConnector.address).to.be.true; +// expect(!!uniswapConnector.address).to.be.true; +// expect(!!(await masterSigner.getAddress())).to.be.true; +// }); + +// describe("DSA wallet setup", function() { +// it("Should build DSA v2", async function() { +// dsaWallet0 = await buildDSAv2(wallet0.address); +// expect(!!dsaWallet0.address).to.be.true; +// }); + +// it("Deposit 10 ETH into DSA wallet", async function() { +// await wallet0.sendTransaction({ +// to: dsaWallet0.address, +// value: ethers.utils.parseEther("10"), +// }); +// expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.gte( +// ethers.utils.parseEther("10") +// ); +// }); +// }); + +// describe("Main - DAI Prize Pool Test", function() { +// it("Should deposit 1 ETH in Compound", async function() { +// const amount = ethers.utils.parseEther("1"); // 1 ETH +// const spells = [ +// { +// connector: connectorName, +// method: "deposit", +// args: ["ETH-A", amount, 0, 0], +// }, +// ]; + +// const tx = await dsaWallet0 +// .connect(wallet0) +// .cast(...encodeSpells(spells), wallet1.address); +// const receipt = await tx.wait(); +// expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.lte( +// ethers.utils.parseEther("9") +// ); +// }); + +// it("Should borrow 100 DAI from Compound and deposit DAI into DAI Prize Pool", async function() { +// const amount = ethers.utils.parseEther("100"); // 100 DAI +// const setId = "83478237"; +// const spells = [ +// { +// connector: connectorName, +// method: "borrow", +// args: ["DAI-A", amount, 0, setId], +// }, +// { +// connector: ptConnectorName, +// method: "depositTo", +// args: [DAI_PRIZE_POOL_ADDR, amount, PT_DAI_TICKET_ADDR, setId, 0], +// }, +// ]; +// // Before Spell +// let daiToken = await ethers.getContractAt( +// abis.basic.erc20, +// DAI_TOKEN_ADDR +// ); +// let daiBalance = await daiToken.balanceOf(dsaWallet0.address); +// expect(daiBalance, `DAI balance is 0`).to.be.eq( +// ethers.utils.parseEther("0") +// ); + +// let cToken = await ethers.getContractAt( +// abis.basic.erc20, +// PT_DAI_TICKET_ADDR +// ); +// const balance = await cToken.balanceOf(dsaWallet0.address); +// expect(balance, `PoolTogether DAI Ticket balance is 0`).to.be.eq(0); + +// // Run spell transaction +// const tx = await dsaWallet0 +// .connect(wallet0) +// .cast(...encodeSpells(spells), wallet1.address); +// const receipt = await tx.wait(); + +// // After spell +// daiBalance = await daiToken.balanceOf(dsaWallet0.address); +// expect( +// daiBalance, +// `Expect DAI balance to still equal 0 since it was deposited into Prize Pool` +// ).to.be.eq(0); + +// const balanceAfter = await cToken.balanceOf(dsaWallet0.address); +// expect( +// balanceAfter, +// `PoolTogether DAI Ticket balance equals 100` +// ).to.be.eq(ethers.utils.parseEther("100")); + +// // ETH used for transaction +// expect(await ethers.provider.getBalance(dsaWallet0.address)).to.be.lte( +// ethers.utils.parseEther("9") +// ); +// }); + +// it("Should wait 11 days, withdraw all PrizePool, get back 100 DAI, and claim POOL", async function() { +// const amount = ethers.utils.parseEther("100"); // 100 DAI + +// let prizePoolContract = new ethers.Contract( +// DAI_PRIZE_POOL_ADDR, +// prizePoolABI, +// ethers.provider +// ); +// let earlyExitFee = await prizePoolContract.callStatic[ +// "calculateEarlyExitFee" +// ](dsaWallet0.address, PT_DAI_TICKET_ADDR, amount); +// expect( +// earlyExitFee.exitFee, +// "Exit Fee equal to 1 DAI because starts at 10%" +// ).to.be.eq(ethers.utils.parseEther("1")); + +// const spells = [ +// { +// connector: ptConnectorName, +// method: "withdrawInstantlyFrom", +// args: [ +// DAI_PRIZE_POOL_ADDR, +// amount, +// PT_DAI_TICKET_ADDR, +// earlyExitFee.exitFee, +// 0, +// 0, +// ], +// }, +// { +// connector: ptConnectorName, +// method: "claim", +// args: [DAI_POOL_FAUCET_ADDR, 0], +// }, +// ]; + +// // Before spell +// let daiToken = await ethers.getContractAt( +// abis.basic.erc20, +// DAI_TOKEN_ADDR +// ); +// let daiBalance = await daiToken.balanceOf(dsaWallet0.address); +// expect(daiBalance, `DAI balance equals 0`).to.be.eq( +// ethers.utils.parseEther("0") +// ); + +// let cToken = await ethers.getContractAt( +// abis.basic.erc20, +// PT_DAI_TICKET_ADDR +// ); +// const balance = await cToken.balanceOf(dsaWallet0.address); +// expect(balance, `PoolTogether Dai Ticket is 100`).to.be.eq( +// ethers.utils.parseEther("100") +// ); + +// let poolToken = await ethers.getContractAt( +// abis.basic.erc20, +// POOL_TOKEN_ADDRESS +// ); +// const poolBalance = await poolToken.balanceOf(dsaWallet0.address); +// expect(poolBalance, `POOL Token equals 0`).to.be.eq( +// ethers.utils.parseEther("0") +// ); + +// // Increase time by 11 days so we get back all DAI without early withdrawal fee +// await ethers.provider.send("evm_increaseTime", [11 * 24 * 60 * 60]); + +// earlyExitFee = await prizePoolContract.callStatic[ +// "calculateEarlyExitFee" +// ](dsaWallet0.address, PT_DAI_TICKET_ADDR, amount); +// expect( +// earlyExitFee.exitFee, +// "Exit Fee equal to 0 DAI because past 10 days" +// ).to.be.eq(0); + +// // Run spell transaction +// const tx = await dsaWallet0 +// .connect(wallet0) +// .cast(...encodeSpells(spells), wallet1.address); +// const receipt = await tx.wait(); + +// // After spell +// daiBalance = await daiToken.balanceOf(dsaWallet0.address); +// expect( +// daiBalance, +// `DAI balance to be equal to 100, because of no early withdrawal fee` +// ).to.be.eq(ethers.utils.parseEther("100")); + +// const balanceAfter = await cToken.balanceOf(dsaWallet0.address); +// expect(balanceAfter, `PoolTogether Dai Ticket to equal 0`).to.be.eq(0); + +// const poolBalanceAfter = await poolToken.balanceOf(dsaWallet0.address); +// expect( +// poolBalanceAfter, +// `POOL Token Balance to be greater than 0` +// ).to.be.gt(ethers.utils.parseEther("0")); +// }); + +// it("Should deposit and withdraw all PrizePool, get back less than 100 DAI", async function() { +// const amount = ethers.utils.parseEther("100"); // 100 DAI +// const exitFee = ethers.utils.parseEther("1"); // 1 DAI is 10% of 100 DAI +// const spells = [ +// { +// connector: ptConnectorName, +// method: "depositTo", +// args: [DAI_PRIZE_POOL_ADDR, amount, PT_DAI_TICKET_ADDR, 0, 0], +// }, +// { +// connector: ptConnectorName, +// method: "withdrawInstantlyFrom", +// args: [ +// DAI_PRIZE_POOL_ADDR, +// amount, +// PT_DAI_TICKET_ADDR, +// exitFee, +// 0, +// 0, +// ], +// }, +// ]; + +// // Before spell +// let daiToken = await ethers.getContractAt( +// abis.basic.erc20, +// DAI_TOKEN_ADDR +// ); +// let daiBalance = await daiToken.balanceOf(dsaWallet0.address); +// expect(daiBalance, `DAI Balance equals 0`).to.be.eq( +// ethers.utils.parseEther("100") +// ); + +// let cToken = await ethers.getContractAt( +// abis.basic.erc20, +// PT_DAI_TICKET_ADDR +// ); +// const balance = await cToken.balanceOf(dsaWallet0.address); +// expect(balance, `PoolTogether DAI Ticket equals 0`).to.be.eq(0); + +// let poolToken = await ethers.getContractAt( +// abis.basic.erc20, +// POOL_TOKEN_ADDRESS +// ); +// const poolBalance = await poolToken.balanceOf(dsaWallet0.address); +// expect(poolBalance, `PoolTogether Token greater than 0`).to.be.gt(0); + +// // Run spell transaction +// const tx = await dsaWallet0 +// .connect(wallet0) +// .cast(...encodeSpells(spells), wallet1.address); +// const receipt = await tx.wait(); + +// // After spell +// daiBalance = await daiToken.balanceOf(dsaWallet0.address); +// expect( +// daiBalance, +// `DAI balance to be less than 100, because of early withdrawal fee` +// ).to.be.lt(ethers.utils.parseEther("100")); + +// const balanceAfter = await cToken.balanceOf(dsaWallet0.address); +// expect(balanceAfter, `PoolTogether Dai Ticket to equal 0`).to.be.eq(0); + +// const poolBalanceAfter = await poolToken.balanceOf(dsaWallet0.address); +// expect(poolBalanceAfter, `POOL Token Balance to greater than 0`).to.be.gt( +// ethers.utils.parseEther("0") +// ); +// }); + +// it("Should deposit, wait 11 days, and withdraw all PrizePool, get 99 DAI, and claim all POOL using claimAll", async function() { +// const amount = ethers.utils.parseEther("99"); // 99 DAI +// const depositSpells = [ +// { +// connector: ptConnectorName, +// method: "depositTo", +// args: [DAI_PRIZE_POOL_ADDR, amount, PT_DAI_TICKET_ADDR, 0, 0], +// }, +// ]; + +// // Before spell +// let daiToken = await ethers.getContractAt( +// abis.basic.erc20, +// DAI_TOKEN_ADDR +// ); +// let daiBalance = await daiToken.balanceOf(dsaWallet0.address); +// expect(daiBalance, `DAI balance less than 100`).to.be.lt( +// ethers.utils.parseEther("100") +// ); + +// let cToken = await ethers.getContractAt( +// abis.basic.erc20, +// PT_DAI_TICKET_ADDR +// ); +// const balance = await cToken.balanceOf(dsaWallet0.address); +// expect(balance, `PoolTogether DAI Ticket equal 0`).to.be.eq(0); + +// let poolToken = await ethers.getContractAt( +// abis.basic.erc20, +// POOL_TOKEN_ADDRESS +// ); +// const poolBalance = await poolToken.balanceOf(dsaWallet0.address); +// expect(poolBalance, `POOL Token is greater than 0`).to.be.gt( +// ethers.utils.parseEther("0") +// ); + +// // Run spell transaction +// const tx = await dsaWallet0 +// .connect(wallet0) +// .cast(...encodeSpells(depositSpells), wallet1.address); +// const receipt = await tx.wait(); + +// const prizePoolContract = new ethers.Contract( +// DAI_PRIZE_POOL_ADDR, +// prizePoolABI, +// ethers.provider +// ); +// let earlyExitFee = await prizePoolContract.callStatic[ +// "calculateEarlyExitFee" +// ](dsaWallet0.address, PT_DAI_TICKET_ADDR, amount); +// expect( +// earlyExitFee.exitFee, +// "Exit Fee equal to .99 DAI because starts at 10%" +// ).to.be.eq(ethers.utils.parseEther(".99")); + +// // Increase time by 11 days so we get back all DAI without early withdrawal fee +// await ethers.provider.send("evm_increaseTime", [11 * 24 * 60 * 60]); + +// earlyExitFee = await prizePoolContract.callStatic[ +// "calculateEarlyExitFee" +// ](dsaWallet0.address, PT_DAI_TICKET_ADDR, amount); +// expect( +// earlyExitFee.exitFee, +// "Exit Fee equal to 0 DAI because past 10 days" +// ).to.be.eq(0); + +// const withdrawSpells = [ +// { +// connector: ptConnectorName, +// method: "withdrawInstantlyFrom", +// args: [ +// DAI_PRIZE_POOL_ADDR, +// amount, +// PT_DAI_TICKET_ADDR, +// earlyExitFee.exitFee, +// 0, +// 0, +// ], +// }, +// { +// connector: ptConnectorName, +// method: "claimAll", +// args: [TOKEN_FAUCET_PROXY_FACTORY_ADDR, [DAI_POOL_FAUCET_ADDR]], +// }, +// ]; + +// // Run spell transaction +// const tx2 = await dsaWallet0 +// .connect(wallet0) +// .cast(...encodeSpells(withdrawSpells), wallet1.address); +// const receipt2 = await tx2.wait(); + +// // After spell +// daiBalance = await daiToken.balanceOf(dsaWallet0.address); +// expect(daiBalance, `DAI balance equals 99`).to.be.eq( +// ethers.utils.parseEther("99") +// ); + +// const balanceAfter = await cToken.balanceOf(dsaWallet0.address); +// expect(balanceAfter, `PoolTogether DAI Ticket equal 0`).to.be.eq(0); + +// // Expect +// const poolBalanceAfter = await poolToken.balanceOf(dsaWallet0.address); +// expect(poolBalanceAfter, `Pool Token to be greateir than 0`).to.be.gt( +// ethers.utils.parseEther("0") +// ); +// }); +// }); + +// describe("Main - DAI Pod Test", function() { +// it("Should deposit 99 DAI in DAI Pod", async function() { +// const amount = ethers.utils.parseEther("99"); // 99 DAI +// const spells = [ +// { +// connector: ptConnectorName, +// method: "depositToPod", +// args: [DAI_TOKEN_ADDR, DAI_POD_ADDR, amount, 0, 0], +// }, +// ]; + +// // Before spell +// let daiToken = await ethers.getContractAt( +// abis.basic.erc20, +// DAI_TOKEN_ADDR +// ); +// let daiBalance = await daiToken.balanceOf(dsaWallet0.address); +// expect(daiBalance, `DAI balance equals 99`).to.be.eq( +// ethers.utils.parseEther("99") +// ); + +// let poolToken = await ethers.getContractAt( +// abis.basic.erc20, +// POOL_TOKEN_ADDRESS +// ); +// const poolBalance = await poolToken.balanceOf(dsaWallet0.address); +// expect(poolBalance, `POOL Token greater than 0`).to.be.gte(0); + +// let podToken = await ethers.getContractAt(abis.basic.erc20, DAI_POD_ADDR); +// const podBalance = await podToken.balanceOf(dsaWallet0.address); +// expect(podBalance, `Pod DAI Token equals 0`).to.be.eq(0); + +// // Run spell transaction +// const tx = await dsaWallet0 +// .connect(wallet0) +// .cast(...encodeSpells(spells), wallet1.address); +// const receipt = await tx.wait(); + +// // After spell +// daiBalance = await daiToken.balanceOf(dsaWallet0.address); +// expect(daiBalance, `DAI equals 0`).to.be.eq(0); + +// const poolBalanceAfter = await poolToken.balanceOf(dsaWallet0.address); +// expect(poolBalanceAfter, `POOL Token greater than 0`).to.be.gt(0); + +// const podBalanceAfter = await podToken.balanceOf(dsaWallet0.address); +// expect(podBalanceAfter, `Pod DAI token greater than 0`).to.be.eq( +// ethers.utils.parseEther("99") +// ); +// }); + +// it("Should claim rewards from pod token drop", async function() { +// const spells = [ +// { +// connector: ptConnectorName, +// method: "claimPodTokenDrop", +// args: [DAI_POD_TOKEN_DROP, 0], +// }, +// ]; + +// const tokenDropContract = new ethers.Contract( +// DAI_POD_TOKEN_DROP, +// tokenDropABI, +// ethers.provider +// ); +// const podContract = new ethers.Contract( +// DAI_POD_ADDR, +// podABI, +// masterSigner +// ); + +// // drop(): Claim TokenDrop asset for PrizePool Pod and transfers token(s) to external Pod TokenDrop +// // dropt() also calls batch which, Deposit Pod float into PrizePool. Deposits the current float +// // amount into the PrizePool and claims current POOL rewards. +// const dropTx = await podContract.drop(); +// await dropTx.wait(); + +// // POOL Rewards able to claim from Pod Token Drop +// let claimAmount = await tokenDropContract.callStatic["claim"]( +// dsaWallet0.address +// ); + +// // Before spell +// let poolToken = await ethers.getContractAt( +// abis.basic.erc20, +// POOL_TOKEN_ADDRESS +// ); +// const poolBalance = await poolToken.balanceOf(dsaWallet0.address); +// expect(poolBalance, `POOL Token greater than 0`).to.be.gt(0); + +// // Run spell transaction +// const tx = await dsaWallet0 +// .connect(wallet0) +// .cast(...encodeSpells(spells), wallet1.address); +// const receipt = await tx.wait(); + +// // After spell +// const poolBalanceAfter = await poolToken.balanceOf(dsaWallet0.address); +// const total = claimAmount.add(poolBalance); +// expect(poolBalanceAfter, `POOL Token same as before spell`).to.be.eq( +// total +// ); +// }); + +// it("Should wait 11 days, withdraw all podTokens, get back 99 DAI", async function() { +// const amount = ethers.utils.parseEther("99"); // 99 DAI + +// const podContract = new ethers.Contract( +// DAI_POD_ADDR, +// podABI, +// ethers.provider +// ); +// let maxFee = await podContract.callStatic["getEarlyExitFee"](amount); +// // maxFee depends on if token has been deposited to PrizePool yet +// // since we called drop in previous test case, the tokens were deposited to PrizePool +// expect( +// maxFee, +// "Exit Fee equal to .99 DAI because token still in float" +// ).to.be.eq(ethers.utils.parseEther(".99")); + +// const spells = [ +// { +// connector: ptConnectorName, +// method: "withdrawFromPod", +// args: [DAI_POD_ADDR, amount, maxFee, 0, 0], +// }, +// ]; + +// // Before spell +// let daiToken = await ethers.getContractAt( +// abis.basic.erc20, +// DAI_TOKEN_ADDR +// ); +// let daiBalance = await daiToken.balanceOf(dsaWallet0.address); +// expect(daiBalance, `DAI Balance equals 0`).to.be.eq(0); + +// let poolToken = await ethers.getContractAt( +// abis.basic.erc20, +// POOL_TOKEN_ADDRESS +// ); +// const poolBalance = await poolToken.balanceOf(dsaWallet0.address); +// expect(poolBalance, `POOL Token balance greater than 0`).to.be.gt(0); + +// let podToken = await ethers.getContractAt(abis.basic.erc20, DAI_POD_ADDR); +// const podBalance = await podToken.balanceOf(dsaWallet0.address); +// expect(podBalance, `Pod DAI Token equals 99`).to.be.eq( +// ethers.utils.parseEther("99") +// ); + +// // Increase time by 11 days so we get back all DAI without early withdrawal fee +// await ethers.provider.send("evm_increaseTime", [11 * 24 * 60 * 60]); + +// // Run spell transaction +// const tx = await dsaWallet0 +// .connect(wallet0) +// .cast(...encodeSpells(spells), wallet1.address); +// const receipt = await tx.wait(); + +// // After spell +// daiBalance = await daiToken.balanceOf(dsaWallet0.address); +// expect( +// daiBalance, +// `DAI balance equals 99, because of no early withdrawal fee` +// ).to.be.eq(ethers.utils.parseEther("99")); + +// const poolBalanceAfter = await poolToken.balanceOf(dsaWallet0.address); +// expect(poolBalanceAfter, `POOL Token to be greater than 0`).to.be.gt(0); + +// const podBalanceAfter = await podToken.balanceOf(dsaWallet0.address); +// expect(podBalanceAfter, `Pod DAI Token equals 0`).to.be.eq(0); +// }); + +// it("Should deposit and withdraw from pod, get back same amount of 99 DAI", async function() { +// const amount = ethers.utils.parseEther("99"); +// const maxFee = 0; // maxFee 0 since it doesn't give chance for Pod to actually deposit into PrizePool + +// const spells = [ +// { +// connector: ptConnectorName, +// method: "depositToPod", +// args: [DAI_TOKEN_ADDR, DAI_POD_ADDR, amount, 0, 0], +// }, +// { +// connector: ptConnectorName, +// method: "withdrawFromPod", +// args: [DAI_POD_ADDR, amount, maxFee, 0, 0], +// }, +// ]; + +// // Before spell +// let daiToken = await ethers.getContractAt( +// abis.basic.erc20, +// DAI_TOKEN_ADDR +// ); +// let daiBalance = await daiToken.balanceOf(dsaWallet0.address); +// expect(daiBalance, `DAI equals 99`).to.be.eq( +// ethers.utils.parseEther("99") +// ); + +// let poolToken = await ethers.getContractAt( +// abis.basic.erc20, +// POOL_TOKEN_ADDRESS +// ); +// const poolBalance = await poolToken.balanceOf(dsaWallet0.address); +// expect(poolBalance, `POOL Token greater than 0`).to.be.gt(0); + +// // PodToken is 0 +// let podToken = await ethers.getContractAt(abis.basic.erc20, DAI_POD_ADDR); +// const podBalance = await podToken.balanceOf(dsaWallet0.address); +// expect(podBalance, `Pod DAI Token equals 0`).to.be.eq(0); + +// // Run spell transaction +// const tx = await dsaWallet0 +// .connect(wallet0) +// .cast(...encodeSpells(spells), wallet1.address); +// const receipt = await tx.wait(); + +// // After spell +// daiBalance = await daiToken.balanceOf(dsaWallet0.address); +// expect( +// daiBalance, +// `DAI balance to be equal to 99, because funds still in 'float` +// ).to.be.eq(ethers.utils.parseEther("99")); + +// const poolBalanceAfter = await poolToken.balanceOf(dsaWallet0.address); +// expect(poolBalanceAfter, `POOL Token same as before spell`).to.be.eq( +// poolBalance +// ); + +// // Expect Pod Token Balance to equal 0 +// const podBalanceAfter = await podToken.balanceOf(dsaWallet0.address); +// expect(podBalanceAfter, `Pod DAI Token equals 0`).to.be.eq( +// ethers.utils.parseEther("0") +// ); +// }); +// }); + +// describe("Main - UNISWAP POOL/ETH Prize Pool Test", function() { +// it("Should use uniswap to swap ETH for POOL, deposit to POOL/ETH LP, deposit POOL/ETH LP to PrizePool", async function() { +// const amount = ethers.utils.parseEther("100"); // 100 POOL +// const slippage = ethers.utils.parseEther("0.03"); +// const setId = "83478237"; + +// const UniswapV2Router02ABI = [ +// "function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts)", +// ]; + +// // Get amount of ETH for 100 POOL from Uniswap +// const UniswapV2Router02 = await ethers.getContractAt( +// UniswapV2Router02ABI, +// "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D" +// ); +// const amounts = await UniswapV2Router02.getAmountsOut(amount, [ +// POOL_TOKEN_ADDRESS, +// WETH_ADDR, +// ]); +// const unitAmount = ethers.utils.parseEther( +// ((amounts[1] * 1.03) / amounts[0]).toString() +// ); + +// const spells = [ +// { +// connector: uniswapConnectorName, +// method: "buy", +// args: [ +// POOL_TOKEN_ADDRESS, +// tokens.eth.address, +// amount, +// unitAmount, +// 0, +// setId, +// ], +// }, +// { +// connector: uniswapConnectorName, +// method: "deposit", +// args: [ +// POOL_TOKEN_ADDRESS, +// tokens.eth.address, +// amount, +// unitAmount, +// slippage, +// 0, +// setId, +// ], +// }, +// { +// connector: ptConnectorName, +// method: "depositTo", +// args: [ +// UNISWAP_POOLETHLP_PRIZE_POOL_ADDR, +// 0, +// PT_UNISWAP_POOLETHLP_TICKET_ADDR, +// setId, +// 0, +// ], +// }, +// ]; + +// // Before Spell +// let ethBalance = await ethers.provider.getBalance(dsaWallet0.address); +// expect(ethBalance, `ETH Balance equals 9`).to.be.eq( +// ethers.utils.parseEther("9") +// ); + +// let poolToken = await ethers.getContractAt( +// abis.basic.erc20, +// POOL_TOKEN_ADDRESS +// ); +// const poolBalance = await poolToken.balanceOf(dsaWallet0.address); +// expect(poolBalance, `POOL Token greater than 0`).to.be.gte(0); + +// let uniswapLPToken = await ethers.getContractAt( +// abis.basic.erc20, +// UNISWAP_POOLETHLP_TOKEN_ADDR +// ); +// const uniswapPoolEthBalance = await uniswapLPToken.balanceOf( +// dsaWallet0.address +// ); +// expect(uniswapPoolEthBalance, `Uniswap POOL/ETH LP equals 0`).to.be.eq(0); + +// let ptUniswapPoolEthToken = await ethers.getContractAt( +// abis.basic.erc20, +// PT_UNISWAP_POOLETHLP_TICKET_ADDR +// ); +// const ptUniswapPoolEthBalance = await ptUniswapPoolEthToken.balanceOf( +// dsaWallet0.address +// ); +// expect( +// ptUniswapPoolEthBalance, +// `PoolTogether Uniswap POOL?ETH LP equals 0` +// ).to.be.eq(0); + +// // Run spell transaction +// const tx = await dsaWallet0 +// .connect(wallet0) +// .cast(...encodeSpells(spells), wallet1.address); +// const receipt = await tx.wait(); + +// // After spell +// ethBalance = await ethers.provider.getBalance(dsaWallet0.address); +// expect(ethBalance, `ETH Balance less than 9`).to.be.lt( +// ethers.utils.parseEther("9") +// ); + +// const poolBalanceAfter = await poolToken.balanceOf(dsaWallet0.address); +// expect(poolBalanceAfter, `POOL Token to be same after spell`).to.be.eq( +// poolBalance +// ); + +// const uniswapPoolEthBalanceAfter = await uniswapLPToken.balanceOf( +// dsaWallet0.address +// ); +// expect( +// uniswapPoolEthBalanceAfter, +// `Uniswap POOL/ETH LP equals 0` +// ).to.be.eq(0); + +// const ptUniswapPoolEthBalanceAfter = await ptUniswapPoolEthToken.balanceOf( +// dsaWallet0.address +// ); +// expect( +// ptUniswapPoolEthBalanceAfter, +// `PT Uniswap POOL/ETH LP to greater than 0` +// ).to.be.gt(0); +// }); + +// it("Should withdraw all PrizePool, get back Uniswap LP, claim POOL, deposit claimed POOL into Pool PrizePool", async function() { +// let ptUniswapPoolEthToken = await ethers.getContractAt( +// abis.basic.erc20, +// PT_UNISWAP_POOLETHLP_TICKET_ADDR +// ); +// const ptUniswapPoolEthBalance = await ptUniswapPoolEthToken.balanceOf( +// dsaWallet0.address +// ); +// const setId = "83478237"; + +// let uniswapPrizePoolContract = new ethers.Contract( +// UNISWAP_POOLETHLP_PRIZE_POOL_ADDR, +// prizePoolABI, +// ethers.provider +// ); +// let earlyExitFee = await uniswapPrizePoolContract.callStatic[ +// "calculateEarlyExitFee" +// ]( +// dsaWallet0.address, +// PT_UNISWAP_POOLETHLP_TICKET_ADDR, +// ptUniswapPoolEthBalance +// ); +// expect( +// earlyExitFee.exitFee, +// "Exit Fee equals 0 because no early exit fee for this prize pool" +// ).to.be.eq(0); + +// const spells = [ +// { +// connector: ptConnectorName, +// method: "withdrawInstantlyFrom", +// args: [ +// UNISWAP_POOLETHLP_PRIZE_POOL_ADDR, +// ptUniswapPoolEthBalance, +// PT_UNISWAP_POOLETHLP_TICKET_ADDR, +// earlyExitFee.exitFee, +// 0, +// 0, +// ], +// }, +// { +// connector: ptConnectorName, +// method: "claim", +// args: [UNISWAP_POOLETHLP_FAUCET_ADDR, setId], +// }, +// { +// connector: ptConnectorName, +// method: "depositTo", +// args: [POOL_PRIZE_POOL_ADDR, 0, PT_POOL_TICKET_ADDR, setId, 0], +// }, +// ]; + +// // Before spell +// let poolToken = await ethers.getContractAt( +// abis.basic.erc20, +// POOL_TOKEN_ADDRESS +// ); +// const poolBalance = await poolToken.balanceOf(dsaWallet0.address); +// expect(poolBalance, `POOL Token greater than 0`).to.be.gt(0); + +// // Uniswap POOL/ETH LP is 0 +// let uniswapLPToken = await ethers.getContractAt( +// abis.basic.erc20, +// UNISWAP_POOLETHLP_TOKEN_ADDR +// ); +// const uniswapPoolEthBalance = await uniswapLPToken.balanceOf( +// dsaWallet0.address +// ); +// expect(uniswapPoolEthBalance, `Uniswap POOL/ETH LP equals 0`).to.be.eq(0); + +// expect( +// ptUniswapPoolEthBalance, +// `PT Uniswap POOL/ETH LP greater than 0` +// ).to.be.gt(0); + +// let poolPoolTicket = await ethers.getContractAt( +// abis.basic.erc20, +// PT_POOL_TICKET_ADDR +// ); +// const poolPoolTicketBalance = await poolPoolTicket.balanceOf( +// dsaWallet0.address +// ); +// expect( +// poolPoolTicketBalance, +// `PoolTogether POOL Ticket equals 0` +// ).to.be.eq(0); + +// // Run spell transaction +// const tx = await dsaWallet0 +// .connect(wallet0) +// .cast(...encodeSpells(spells), wallet1.address); +// const receipt = await tx.wait(); + +// // After spell +// const poolBalanceAfter = await poolToken.balanceOf(dsaWallet0.address); +// expect( +// poolBalanceAfter, +// `Pool Token Balance equal to balance before spell` +// ).to.be.eq(poolBalance); + +// const uniswapPoolEthBalanceAfter = await uniswapLPToken.balanceOf( +// dsaWallet0.address +// ); +// expect( +// uniswapPoolEthBalanceAfter, +// `Uniswap POOL/ETH LP to greater than 0` +// ).to.be.gt(0); + +// const ptUniswapPoolEthBalanceAfter = await ptUniswapPoolEthToken.balanceOf( +// dsaWallet0.address +// ); +// expect( +// ptUniswapPoolEthBalanceAfter, +// `PT Uniswap POOL/ETH LP equal 0` +// ).to.be.eq(0); + +// const poolPoolTicketBalanceAfter = await poolPoolTicket.balanceOf( +// dsaWallet0.address +// ); +// expect( +// poolPoolTicketBalanceAfter, +// `PoolTogether POOL Ticket greater than 0` +// ).to.be.gt(0); +// }); +// }); + +// describe("Main - WETH Prize Pool Test", function() { +// it("Deposit 1 ETH into WETH Prize Pool and withdraw immediately", async function() { +// const amount = ethers.utils.parseEther("1"); // 1 ETH +// const setId = "83478237"; +// const spells = [ +// { +// connector: ptConnectorName, +// method: "depositTo", +// args: [WETH_PRIZE_POOL_ADDR, amount, WETH_POOL_TICKET_ADDR, 0, setId], +// }, +// { +// connector: ptConnectorName, +// method: "withdrawInstantlyFrom", +// args: [ +// WETH_PRIZE_POOL_ADDR, +// amount, +// WETH_POOL_TICKET_ADDR, +// amount, +// setId, +// 0, +// ], +// }, +// ]; +// // Before Spell +// const ethBalanceBefore = await ethers.provider.getBalance( +// dsaWallet0.address +// ); + +// // Run spell transaction +// const tx = await dsaWallet0 +// .connect(wallet0) +// .cast(...encodeSpells(spells), wallet1.address); +// const receipt = await tx.wait(); + +// // After spell +// const ethBalanceAfter = await ethers.provider.getBalance( +// dsaWallet0.address +// ); + +// // ETH used for transaction +// expect( +// ethBalanceAfter, +// `ETH Balance less than before spell because of early withdrawal fee` +// ).to.be.lte(ethBalanceBefore); +// }); + +// it("Deposit 1 ETH into WETH Prize Pool, wait 14 days, then withdraw", async function() { +// const amount = ethers.utils.parseEther("1"); // 1 ETH +// const depositSpell = [ +// { +// connector: ptConnectorName, +// method: "depositTo", +// args: [WETH_PRIZE_POOL_ADDR, amount, WETH_POOL_TICKET_ADDR, 0, 0], +// }, +// ]; + +// const withdrawSpell = [ +// { +// connector: ptConnectorName, +// method: "withdrawInstantlyFrom", +// args: [ +// WETH_PRIZE_POOL_ADDR, +// amount, +// WETH_POOL_TICKET_ADDR, +// amount, +// 0, +// 0, +// ], +// }, +// ]; + +// // Before Deposit Spell +// let ethBalanceBefore = await ethers.provider.getBalance( +// dsaWallet0.address +// ); + +// // Run deposit spell transaction +// const tx = await dsaWallet0 +// .connect(wallet0) +// .cast(...encodeSpells(depositSpell), wallet1.address); +// const receipt = await tx.wait(); + +// // After Deposit spell +// let ethBalanceAfter = await ethers.provider.getBalance( +// dsaWallet0.address +// ); + +// expect(ethBalanceAfter, `ETH Balance less than before spell`).to.be.lte( +// ethBalanceBefore +// ); + +// // Increase time by 11 days so we get back all ETH without early withdrawal fee +// await ethers.provider.send("evm_increaseTime", [14 * 24 * 60 * 60]); + +// // Run withdraw spell transaction +// const tx2 = await dsaWallet0 +// .connect(wallet0) +// .cast(...encodeSpells(withdrawSpell), wallet1.address); +// const receipt2 = await tx.wait(); + +// // After Deposit spell +// ethBalanceAfter = await ethers.provider.getBalance(dsaWallet0.address); + +// expect( +// ethBalanceAfter, +// `ETH Balance equal to before spell because no early exit fee` +// ).to.be.eq(ethBalanceBefore); +// }); +// }); + +// describe("Main - WETH Pod Test", function() { +// let podAddress: string; +// it("Should deposit 1 ETH in WETH Pod and get Pod Ticket", async function() { +// const amount = ethers.utils.parseEther("1"); + +// // Create Pod for WETH Prize Pool (Rari) +// const podFactoryContract = new ethers.Contract( +// POD_FACTORY_ADDRESS, +// podFactoryABI, +// masterSigner +// ); +// podAddress = await podFactoryContract.callStatic.create( +// WETH_PRIZE_POOL_ADDR, +// WETH_POOL_TICKET_ADDR, +// constants.address_zero, +// wallet0.address, +// 18 +// ); +// await podFactoryContract.create( +// WETH_PRIZE_POOL_ADDR, +// WETH_POOL_TICKET_ADDR, +// constants.address_zero, +// wallet0.address, +// 18 +// ); + +// const spells = [ +// { +// connector: ptConnectorName, +// method: "depositToPod", +// args: [WETH_ADDR, podAddress, amount, 0, 0], +// }, +// ]; + +// // Before Deposit Spell +// const podContract = new ethers.Contract( +// podAddress, +// podABI, +// ethers.provider +// ); +// let podBalanceBefore = await podContract.balanceOfUnderlying( +// dsaWallet0.address +// ); +// expect(podBalanceBefore, `Pod balance equal to 0`).to.be.eq(0); + +// let ethBalanceBefore = await ethers.provider.getBalance( +// dsaWallet0.address +// ); + +// // Run spell transaction +// const tx = await dsaWallet0 +// .connect(wallet0) +// .cast(...encodeSpells(spells), wallet1.address); +// const receipt = await tx.wait(); + +// // After Deposit spell +// let ethBalanceAfter = await ethers.provider.getBalance( +// dsaWallet0.address +// ); +// expect(ethBalanceAfter, `ETH balance less than before`).to.be.lt( +// ethBalanceBefore +// ); + +// let podBalanceAfter = await podContract.balanceOfUnderlying( +// dsaWallet0.address +// ); +// expect(podBalanceAfter, `Pod balance equal to 1`).to.be.eq( +// ethers.utils.parseEther("1") +// ); +// }); + +// it("Should withdraw 1 Ticket from WETH Pod and get back ETH", async function() { +// const amount = ethers.utils.parseEther("1"); + +// const podContract = new ethers.Contract( +// podAddress, +// podABI, +// ethers.provider +// ); +// let maxFee = await podContract.callStatic["getEarlyExitFee"](amount); +// expect( +// maxFee, +// "Exit Fee equal to 0 DAI because token still in float" +// ).to.be.eq(0); +// // maxFee depends on if token has been deposited to PrizePool yet + +// const spells = [ +// { +// connector: ptConnectorName, +// method: "withdrawFromPod", +// args: [podAddress, amount, maxFee, 0, 0], +// }, +// ]; + +// // Before Deposit Spell +// let podBalanceBefore = await podContract.balanceOfUnderlying( +// dsaWallet0.address +// ); +// expect(podBalanceBefore, `Pod balance equal to 1`).to.be.eq( +// ethers.utils.parseEther("1") +// ); + +// let ethBalanceBefore = await ethers.provider.getBalance( +// dsaWallet0.address +// ); + +// // Run spell transaction +// const tx = await dsaWallet0 +// .connect(wallet0) +// .cast(...encodeSpells(spells), wallet1.address); +// const receipt = await tx.wait(); + +// // After Deposit spell +// let ethBalanceAfter = await ethers.provider.getBalance( +// dsaWallet0.address +// ); +// expect(ethBalanceAfter, `ETH balance greater than before`).to.be.gt( +// ethBalanceBefore +// ); + +// let podBalanceAfter = await podContract.balanceOfUnderlying( +// dsaWallet0.address +// ); +// expect(podBalanceAfter, `Pod balance equal to 0`).to.be.eq( +// ethers.utils.parseEther("0") +// ); +// }); +// }); +// }); diff --git a/test/mainnet/uniswapStake/uniswapStake.test.ts b/test/mainnet/uniswapStake/uniswapStake.test.ts index bc2cf3e0..f9352153 100644 --- a/test/mainnet/uniswapStake/uniswapStake.test.ts +++ b/test/mainnet/uniswapStake/uniswapStake.test.ts @@ -40,7 +40,7 @@ describe("UniswapV3", function () { const connectorUniswap = "UniswapV3-v1" let dsaWallet0: any - let masterSigner: any; + let masterSigner: Signer; let instaConnectorsV2: any; let connector: any; let startTime: any, endTime: any; @@ -83,7 +83,7 @@ describe("UniswapV3", function () { it("Should have contracts deployed.", async function () { expect(!!instaConnectorsV2.address).to.be.true; expect(!!connector.address).to.be.true; - expect(!!masterSigner.address).to.be.true; + expect(!!(await masterSigner.getAddress())).to.be.true; }); describe("DSA wallet setup", function () { @@ -183,7 +183,7 @@ describe("UniswapV3", function () { let event = await castEvent let balance = await nftManager.connect(wallet0).balanceOf(dsaWallet0.address) - console.log("Balance", balance) + console.log("Balance", balance.toString()) }); it("Should create incentive successfully", async function () { @@ -277,7 +277,7 @@ describe("UniswapV3", function () { let receipt = await tx.wait() let balance = await nftManager.connect(wallet0).balanceOf(dsaWallet0.address) - console.log("Balance", balance) + console.log("Balance", balance.toString()) }); it("Should claim rewards successfully", async function () { @@ -348,7 +348,7 @@ describe("UniswapV3", function () { let receipt = await tx.wait() let balance = await nftManager.connect(wallet0).balanceOf(dsaWallet0.address) - console.log("Balance", balance) + console.log("Balance", balance.toString()) }); }) }) diff --git a/test/mainnet/pooltogether-polygon/pooltogether.test.ts b/test/polygon/pooltogether/pooltogether.test.ts similarity index 100% rename from test/mainnet/pooltogether-polygon/pooltogether.test.ts rename to test/polygon/pooltogether/pooltogether.test.ts diff --git a/yarn.lock b/yarn.lock index 7d4de696..a5bbacb4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1291,6 +1291,14 @@ "@types/minimatch" "*" "@types/node" "*" +"@types/inquirer@^8.1.3": + "integrity" "sha512-AayK4ZL5ssPzR1OtnOLGAwpT0Dda3Xi/h1G0l1oJDNrowp7T1423q4Zb8/emr7tzRlCy4ssEri0LWVexAqHyKQ==" + "resolved" "https://registry.npmjs.org/@types/inquirer/-/inquirer-8.1.3.tgz" + "version" "8.1.3" + dependencies: + "@types/through" "*" + "rxjs" "^7.2.0" + "@types/level-errors@*": "integrity" "sha512-/lMtoq/Cf/2DVOm6zE6ORyOM+3ZVm/BvzEZVxUhf6bgh8ZHglXlBqxbxSlJeVp8FCbD3IVvk/VbsaNmDjrQvqQ==" "resolved" "https://registry.npmjs.org/@types/level-errors/-/level-errors-3.0.0.tgz" @@ -1391,6 +1399,13 @@ dependencies: "@sinonjs/fake-timers" "^7.0.4" +"@types/through@*": + "integrity" "sha512-FvnCJljyxhPM3gkRgWmxmDZyAQSiBQQWLI0A0VFL0K7W1oRUrPJSqNO0NvTnLkBcotdlp3lKvaT0JrnyRDkzOg==" + "resolved" "https://registry.npmjs.org/@types/through/-/through-0.0.30.tgz" + "version" "0.0.30" + dependencies: + "@types/node" "*" + "@types/underscore@*": "integrity" "sha512-Ls2ylbo7++ITrWk2Yc3G/jijwSq5V3GT0tlgVXEl2kKYXY3ImrtmTCoE2uyTWFRI5owMBriloZFWbE1SXOsE7w==" "resolved" "https://registry.npmjs.org/@types/underscore/-/underscore-1.11.2.tgz" @@ -1784,7 +1799,7 @@ "resolved" "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz" "version" "3.2.3" -"ansi-escapes@^4.3.0": +"ansi-escapes@^4.2.1", "ansi-escapes@^4.3.0": "integrity" "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==" "resolved" "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz" "version" "4.3.2" @@ -1817,6 +1832,11 @@ "resolved" "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz" "version" "4.1.0" +"ansi-regex@^5.0.1": + "integrity" "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + "resolved" "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz" + "version" "5.0.1" + "ansi-styles@^2.2.1": "version" "2.2.1" @@ -2574,7 +2594,7 @@ "safe-buffer" "^5.0.1" "unorm" "^1.3.3" -"bl@^4.0.3": +"bl@^4.0.3", "bl@^4.1.0": "integrity" "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==" "resolved" "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz" "version" "4.1.0" @@ -3037,6 +3057,22 @@ "escape-string-regexp" "^1.0.5" "supports-color" "^5.3.0" +"chalk@^4.1.0": + "integrity" "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==" + "resolved" "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz" + "version" "4.1.2" + dependencies: + "ansi-styles" "^4.1.0" + "supports-color" "^7.1.0" + +"chalk@^4.1.1": + "integrity" "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==" + "resolved" "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz" + "version" "4.1.2" + dependencies: + "ansi-styles" "^4.1.0" + "supports-color" "^7.1.0" + "chalk@^4.1.2": "integrity" "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==" "resolved" "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz" @@ -3074,6 +3110,11 @@ "upper-case" "^1.1.1" "upper-case-first" "^1.1.0" +"chardet@^0.7.0": + "integrity" "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==" + "resolved" "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz" + "version" "0.7.0" + "check-error@^1.0.2": "integrity" "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=" "resolved" "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz" @@ -3213,6 +3254,23 @@ dependencies: "source-map" "~0.6.0" +"cli-cursor@^3.1.0": + "integrity" "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==" + "resolved" "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz" + "version" "3.1.0" + dependencies: + "restore-cursor" "^3.1.0" + +"cli-spinners@^2.5.0": + "integrity" "sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==" + "resolved" "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.1.tgz" + "version" "2.6.1" + +"cli-width@^3.0.0": + "integrity" "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==" + "resolved" "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz" + "version" "3.0.0" + "cliui@^2.1.0": "integrity" "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=" "resolved" "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz" @@ -3247,6 +3305,11 @@ dependencies: "mimic-response" "^1.0.0" +"clone@^1.0.2": + "integrity" "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=" + "resolved" "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz" + "version" "1.0.4" + "clone@^2.0.0", "clone@2.1.2": "version" "2.1.2" @@ -3781,6 +3844,13 @@ "resolved" "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz" "version" "0.1.4" +"defaults@^1.0.3": + "integrity" "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=" + "resolved" "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz" + "version" "1.0.3" + dependencies: + "clone" "^1.0.2" + "defer-to-connect@^1.0.1": "integrity" "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==" "resolved" "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz" @@ -4038,6 +4108,11 @@ "resolved" "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz" "version" "7.0.3" +"emoji-regex@^8.0.0": + "integrity" "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + "resolved" "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz" + "version" "8.0.0" + "emojis-list@^2.0.0": "integrity" "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=" "resolved" "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz" @@ -5026,6 +5101,15 @@ "resolved" "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz" "version" "3.0.2" +"external-editor@^3.0.3": + "integrity" "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==" + "resolved" "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz" + "version" "3.1.0" + dependencies: + "chardet" "^0.7.0" + "iconv-lite" "^0.4.24" + "tmp" "^0.0.33" + "extglob@^2.0.4": "integrity" "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==" "resolved" "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz" @@ -5105,6 +5189,13 @@ "resolved" "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz" "version" "3.5.2" +"figures@^3.0.0": + "integrity" "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==" + "resolved" "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz" + "version" "3.2.0" + dependencies: + "escape-string-regexp" "^1.0.5" + "file-uri-to-path@1.0.0": "integrity" "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" "resolved" "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz" @@ -6147,18 +6238,18 @@ "resolved" "https://registry.npmjs.org/husky/-/husky-7.0.4.tgz" "version" "7.0.4" -"iconv-lite@^0.6.2": - "version" "0.6.2" - dependencies: - "safer-buffer" ">= 2.1.2 < 3.0.0" - -"iconv-lite@0.4.24": +"iconv-lite@^0.4.24", "iconv-lite@0.4.24": "integrity" "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==" "resolved" "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz" "version" "0.4.24" dependencies: "safer-buffer" ">= 2.1.2 < 3" +"iconv-lite@^0.6.2": + "version" "0.6.2" + dependencies: + "safer-buffer" ">= 2.1.2 < 3.0.0" + "icss-replace-symbols@^1.1.0": "integrity" "sha1-Bupvg2ead0njhs/h/oEq5dsiPe0=" "resolved" "https://registry.npmjs.org/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz" @@ -6251,6 +6342,26 @@ "resolved" "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz" "version" "1.3.8" +"inquirer@^8.2.0": + "integrity" "sha512-0crLweprevJ02tTuA6ThpoAERAGyVILC4sS74uib58Xf/zSr1/ZWtmm7D5CI+bSQEaA04f0K7idaHpQbSWgiVQ==" + "resolved" "https://registry.npmjs.org/inquirer/-/inquirer-8.2.0.tgz" + "version" "8.2.0" + dependencies: + "ansi-escapes" "^4.2.1" + "chalk" "^4.1.1" + "cli-cursor" "^3.1.0" + "cli-width" "^3.0.0" + "external-editor" "^3.0.3" + "figures" "^3.0.0" + "lodash" "^4.17.21" + "mute-stream" "0.0.8" + "ora" "^5.4.1" + "run-async" "^2.4.0" + "rxjs" "^7.2.0" + "string-width" "^4.1.0" + "strip-ansi" "^6.0.0" + "through" "^2.3.6" + "internal-slot@^1.0.3": "integrity" "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==" "resolved" "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz" @@ -6454,6 +6565,11 @@ "resolved" "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz" "version" "2.0.0" +"is-fullwidth-code-point@^3.0.0": + "integrity" "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + "resolved" "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz" + "version" "3.0.0" + "is-function@^1.0.1": "integrity" "sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ==" "resolved" "https://registry.npmjs.org/is-function/-/is-function-1.0.2.tgz" @@ -6485,6 +6601,11 @@ "resolved" "https://registry.npmjs.org/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz" "version" "1.0.0" +"is-interactive@^1.0.0": + "integrity" "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==" + "resolved" "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz" + "version" "1.0.0" + "is-lower-case@^1.1.0": "integrity" "sha1-fhR75HaNxGbbO/shzGCzHmrWk5M=" "resolved" "https://registry.npmjs.org/is-lower-case/-/is-lower-case-1.1.3.tgz" @@ -6600,6 +6721,11 @@ "resolved" "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz" "version" "1.0.0" +"is-unicode-supported@^0.1.0": + "integrity" "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==" + "resolved" "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz" + "version" "0.1.0" + "is-upper-case@^1.1.0": "integrity" "sha1-jQsfp+eTOh5YSDYA7H2WYcuvdW8=" "resolved" "https://registry.npmjs.org/is-upper-case/-/is-upper-case-1.1.2.tgz" @@ -7207,6 +7333,14 @@ "lodash@^4.17.4", "lodash@4.17.20": "version" "4.17.20" +"log-symbols@^4.1.0": + "integrity" "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==" + "resolved" "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz" + "version" "4.1.0" + dependencies: + "chalk" "^4.1.0" + "is-unicode-supported" "^0.1.0" + "log-symbols@3.0.0": "integrity" "sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ==" "resolved" "https://registry.npmjs.org/log-symbols/-/log-symbols-3.0.0.tgz" @@ -7560,6 +7694,11 @@ "resolved" "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz" "version" "2.1.0" +"mimic-fn@^2.1.0": + "integrity" "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" + "resolved" "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz" + "version" "2.1.0" + "mimic-response@^1.0.0", "mimic-response@^1.0.1": "integrity" "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==" "resolved" "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz" @@ -7790,6 +7929,11 @@ "fmix" "^0.1.0" "imul" "^1.0.0" +"mute-stream@0.0.8": + "integrity" "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" + "resolved" "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz" + "version" "0.0.8" + "nan@^2.12.1": "integrity" "sha512-TghvYc72wlMGMVMluVo9WRJc0mB8KxxF/gZ4YYFy7V2ZQX9l7rgbPg7vjS9mt6U5HXODVFVI2bOduCzwOMv/lw==" "resolved" "https://registry.npmjs.org/nan/-/nan-2.13.2.tgz" @@ -8170,6 +8314,13 @@ dependencies: "wrappy" "1" +"onetime@^5.1.0": + "integrity" "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==" + "resolved" "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz" + "version" "5.1.2" + dependencies: + "mimic-fn" "^2.1.0" + "open@^7.4.2": "integrity" "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==" "resolved" "https://registry.npmjs.org/open/-/open-7.4.2.tgz" @@ -8190,6 +8341,21 @@ "type-check" "~0.3.2" "word-wrap" "~1.2.3" +"ora@^5.4.1": + "integrity" "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==" + "resolved" "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz" + "version" "5.4.1" + dependencies: + "bl" "^4.1.0" + "chalk" "^4.1.0" + "cli-cursor" "^3.1.0" + "cli-spinners" "^2.5.0" + "is-interactive" "^1.0.0" + "is-unicode-supported" "^0.1.0" + "log-symbols" "^4.1.0" + "strip-ansi" "^6.0.0" + "wcwidth" "^1.0.1" + "os-browserify@^0.3.0": "integrity" "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=" "resolved" "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz" @@ -9013,7 +9179,16 @@ "string_decoder" "^1.1.1" "util-deprecate" "^1.0.1" -"readable-stream@^3.1.1", "readable-stream@^3.4.0": +"readable-stream@^3.1.1": + "integrity" "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==" + "resolved" "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz" + "version" "3.6.0" + dependencies: + "inherits" "^2.0.3" + "string_decoder" "^1.1.1" + "util-deprecate" "^1.0.1" + +"readable-stream@^3.4.0": "integrity" "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==" "resolved" "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz" "version" "3.6.0" @@ -9239,6 +9414,14 @@ dependencies: "lowercase-keys" "^1.0.0" +"restore-cursor@^3.1.0": + "integrity" "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==" + "resolved" "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz" + "version" "3.1.0" + dependencies: + "onetime" "^5.1.0" + "signal-exit" "^3.0.2" + "resumer@~0.0.0": "version" "0.0.0" dependencies: @@ -9288,6 +9471,11 @@ dependencies: "bn.js" "^4.11.1" +"run-async@^2.4.0": + "integrity" "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==" + "resolved" "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz" + "version" "2.4.1" + "run-parallel@^1.1.9": "integrity" "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==" "resolved" "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz" @@ -9307,6 +9495,13 @@ "resolved" "https://registry.npmjs.org/rustbn.js/-/rustbn.js-0.2.0.tgz" "version" "0.2.0" +"rxjs@^7.2.0": + "integrity" "sha512-7SQDi7xeTMCJpqViXh8gL/lebcwlp3d831F05+9B44A4B0WfsEwUQHR64gsH1kvJ+Ep/J9K2+n1hVl1CsGN23w==" + "resolved" "https://registry.npmjs.org/rxjs/-/rxjs-7.4.0.tgz" + "version" "7.4.0" + dependencies: + "tslib" "~2.1.0" + "rxjs@6": "integrity" "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==" "resolved" "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz" @@ -9595,7 +9790,7 @@ "get-intrinsic" "^1.0.2" "object-inspect" "^1.9.0" -"signal-exit@^3.0.0": +"signal-exit@^3.0.0", "signal-exit@^3.0.2": "integrity" "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==" "resolved" "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz" "version" "3.0.3" @@ -9969,6 +10164,15 @@ "is-fullwidth-code-point" "^2.0.0" "strip-ansi" "^5.1.0" +"string-width@^4.1.0": + "integrity" "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==" + "resolved" "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz" + "version" "4.2.3" + dependencies: + "emoji-regex" "^8.0.0" + "is-fullwidth-code-point" "^3.0.0" + "strip-ansi" "^6.0.1" + "string.prototype.trim@~1.2.1": "version" "1.2.3" dependencies: @@ -10025,6 +10229,13 @@ dependencies: "ansi-regex" "^4.1.0" +"strip-ansi@^6.0.0", "strip-ansi@^6.0.1": + "integrity" "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==" + "resolved" "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz" + "version" "6.0.1" + dependencies: + "ansi-regex" "^5.0.1" + "strip-bom@^2.0.0": "integrity" "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=" "resolved" "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz" @@ -10234,6 +10445,11 @@ "resolved" "https://registry.npmjs.org/testrpc/-/testrpc-0.0.1.tgz" "version" "0.0.1" +"through@^2.3.6": + "integrity" "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" + "resolved" "https://registry.npmjs.org/through/-/through-2.3.8.tgz" + "version" "2.3.8" + "through@~2.3.4", "through@~2.3.8": "version" "2.3.8" @@ -10412,6 +10628,11 @@ "resolved" "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz" "version" "2.3.1" +"tslib@~2.1.0": + "integrity" "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==" + "resolved" "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz" + "version" "2.1.0" + "tsort@0.0.1": "integrity" "sha1-4igPXoF/i/QnVlf9D5rr1E9aJ4Y=" "resolved" "https://registry.npmjs.org/tsort/-/tsort-0.0.1.tgz" @@ -10932,6 +11153,13 @@ "chokidar" "^3.4.1" "watchpack-chokidar2" "^2.0.1" +"wcwidth@^1.0.1": + "integrity" "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=" + "resolved" "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz" + "version" "1.0.1" + dependencies: + "defaults" "^1.0.3" + "web3-bzz@1.2.11": "version" "1.2.11" dependencies: