diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index 8d7c4ce5..ca822e13 100644 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -1,9 +1,6 @@ name: checks -on: - pull_request: - branches: - - main +on: [pull_request] concurrency: group: checks-${{ github.ref }} @@ -44,4 +41,4 @@ jobs: uses: ./.github/actions/setup - name: Run tests - run: npm run test:parallel + run: npm run test diff --git a/.states/vm-prague/state.json b/.states/vm-prague/state.json new file mode 100644 index 00000000..6890763a --- /dev/null +++ b/.states/vm-prague/state.json @@ -0,0 +1,126 @@ +{ + "db": { + "0490f0d98c06a6234cc374564f984580f33770d4605e5781451d4971d3235a2d": "0xf873a1205931b4ed56ace4c46b68524cb5bcbf4195f1bbaacbe5228fbd090546c88dd229b84ff84d8089056bc75e2d63100000a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "937514b0e72ad8da6bb5e656f25334fb09e7018992ae794d5c237fbf27a5db15": "0x388b1ee9613a71d8c39a450aff71e7fb9da72089e93ef5c8a28a40df8627abd5", + "ac59032c139346dba6925ea119f110bc037a945991f7349e218edbe12d6d43e9": "0xf872a03931b4ed56ace4c46b68524cb5bcbf4195f1bbaacbe5228fbd090546c88dd229b84ff84d8089056bc75e2d63100000a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "b57eae55d1d898a1388d3065de9102d0f6ade3423b29be2482e1626394acd99f": "0xf872a0399bf57501565dbd2fdcea36efa2b9aef8340a8901e3459f4a4c926275d36cdbb84ff84d8089056bc75e2d63100000a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "dac9f9238909bae6bedf62a95a3ac503b5e6927b8243b9b44e0e335869bef325": "0xf8518080808080a0ac59032c139346dba6925ea119f110bc037a945991f7349e218edbe12d6d43e9808080a0b57eae55d1d898a1388d3065de9102d0f6ade3423b29be2482e1626394acd99f80808080808080", + "6e94ede82e8c381d422f010130a4c2ed35805be58e6783d800fbb37d000090e2": "0xf872a034a10bfd00977f54cc3450c9b25c9b3a502a089eba0097ba35fc33c4ea5fcb54b84ff84d8089056bc75e2d63100000a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "1db6a1394b96218e282fb52d559676dbecfba9a78146880e35ef38cc061dbf44": "0xf871a06e94ede82e8c381d422f010130a4c2ed35805be58e6783d800fbb37d000090e280808080a0ac59032c139346dba6925ea119f110bc037a945991f7349e218edbe12d6d43e9808080a0b57eae55d1d898a1388d3065de9102d0f6ade3423b29be2482e1626394acd99f80808080808080", + "acc98ed24983a10e645870d5b47d42f6a1c47d94ac9165221722626a99b3660c": "0xf872a03fbe3e504ac4e35541bebad4d0e7574668e16fefa26cd4172f93e18b59ce9486b84ff84d8089056bc75e2d63100000a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "de2548e2521504daf92524b329dbb037a000ed381a8f810b8607e2f8832ada7d": "0xf891a06e94ede82e8c381d422f010130a4c2ed35805be58e6783d800fbb37d000090e280808080a0ac59032c139346dba6925ea119f110bc037a945991f7349e218edbe12d6d43e9808080a0b57eae55d1d898a1388d3065de9102d0f6ade3423b29be2482e1626394acd99f808080a0acc98ed24983a10e645870d5b47d42f6a1c47d94ac9165221722626a99b3660c808080", + "5f1ef1b2e89b5ed4e71249e76600493c718bc6c6030189bfab281c7b85389a2c": "0xf872a036d82c545c22b72034803633d3dda2b28e89fb704f3c111355ac43e10612aedcb84ff84d8089056bc75e2d63100000a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "09cc43c2655ecf235e9ef7dbf5c6f27157eb9f6e2b53433a3f0f13301ca34450": "0xf8b1a06e94ede82e8c381d422f010130a4c2ed35805be58e6783d800fbb37d000090e280808080a0ac59032c139346dba6925ea119f110bc037a945991f7349e218edbe12d6d43e9808080a0b57eae55d1d898a1388d3065de9102d0f6ade3423b29be2482e1626394acd99f808080a0acc98ed24983a10e645870d5b47d42f6a1c47d94ac9165221722626a99b3660c80a05f1ef1b2e89b5ed4e71249e76600493c718bc6c6030189bfab281c7b85389a2c80", + "69a571829b9b6f89efb0b65e66e59e5a26b2eb72cdfce949e0aec5e0037357bd": "0xf872a0323d89d4ba0f8b56a459710de4b44820d73e93736cfc0667f35cdd5142b70f0db84ff84d8089056bc75e2d63100000a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "7b184ca9e86ac8499d2cde865d80d191cbbeca4393fd2b74df5972f5426e0895": "0xf8d1a06e94ede82e8c381d422f010130a4c2ed35805be58e6783d800fbb37d000090e280808080a0ac59032c139346dba6925ea119f110bc037a945991f7349e218edbe12d6d43e9808080a0b57eae55d1d898a1388d3065de9102d0f6ade3423b29be2482e1626394acd99f8080a069a571829b9b6f89efb0b65e66e59e5a26b2eb72cdfce949e0aec5e0037357bda0acc98ed24983a10e645870d5b47d42f6a1c47d94ac9165221722626a99b3660c80a05f1ef1b2e89b5ed4e71249e76600493c718bc6c6030189bfab281c7b85389a2c80", + "0968480c83b67f0eb2cafc1df82dbf6dcac0811f36fbd405f20c46f158da5315": "0xf872a03c22adb6b75b7a618594eacef369bc4f0ec06380e8630fd7580f9bf0ea413ca8b84ff84d8089056bc75e2d63100000a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "b955e456c73a5460828b40c246ac4e09b60c899b969e7a9520783863649f104a": "0xf8f1a06e94ede82e8c381d422f010130a4c2ed35805be58e6783d800fbb37d000090e2a00968480c83b67f0eb2cafc1df82dbf6dcac0811f36fbd405f20c46f158da5315808080a0ac59032c139346dba6925ea119f110bc037a945991f7349e218edbe12d6d43e9808080a0b57eae55d1d898a1388d3065de9102d0f6ade3423b29be2482e1626394acd99f8080a069a571829b9b6f89efb0b65e66e59e5a26b2eb72cdfce949e0aec5e0037357bda0acc98ed24983a10e645870d5b47d42f6a1c47d94ac9165221722626a99b3660c80a05f1ef1b2e89b5ed4e71249e76600493c718bc6c6030189bfab281c7b85389a2c80", + "70f09e0afc485ee4555a5c2bcb5380fe4745dfb619c97ce55ca368555f4c0358": "0xf872a03b9f0f05f155b5df3bbdd079fa47bedd6da0e32966c72f92264d98e80248858eb84ff84d8089056bc75e2d63100000a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "e628eda7692102d1123972b085e483fb81586793e6e4bb395f356f319785b924": "0xf90111a06e94ede82e8c381d422f010130a4c2ed35805be58e6783d800fbb37d000090e2a00968480c83b67f0eb2cafc1df82dbf6dcac0811f36fbd405f20c46f158da5315808080a0ac59032c139346dba6925ea119f110bc037a945991f7349e218edbe12d6d43e9808080a0b57eae55d1d898a1388d3065de9102d0f6ade3423b29be2482e1626394acd99f80a070f09e0afc485ee4555a5c2bcb5380fe4745dfb619c97ce55ca368555f4c0358a069a571829b9b6f89efb0b65e66e59e5a26b2eb72cdfce949e0aec5e0037357bda0acc98ed24983a10e645870d5b47d42f6a1c47d94ac9165221722626a99b3660c80a05f1ef1b2e89b5ed4e71249e76600493c718bc6c6030189bfab281c7b85389a2c80", + "021eda8d86f1724d84a155e5e0227744e3fb2f570089a70ae65750d24410fe10": "0xf872a0209bf57501565dbd2fdcea36efa2b9aef8340a8901e3459f4a4c926275d36cdbb84ff84d8089056bc75e2d63100000a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "35196d12c07e2405a02d095f74880568965618e95b50e64e8690594aa6bb5ea2": "0xf872a0207839edeb5b3ee9a2dee69954b24aeb3f91b8ff4c608efd90618351fe77152fb84ff84d8089056bc75e2d63100000a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "f4ae3d0d998ac3c8f5118c8ef3ce2ef3dc0440a900323177580df0f212f8b363": "0xf85180808080a035196d12c07e2405a02d095f74880568965618e95b50e64e8690594aa6bb5ea280808080a0021eda8d86f1724d84a155e5e0227744e3fb2f570089a70ae65750d24410fe1080808080808080", + "4b7be564e069212c8c0dd694ce21c7051e5cb7bbb527e3af73faf7e61de082c0": "0xf90111a06e94ede82e8c381d422f010130a4c2ed35805be58e6783d800fbb37d000090e2a00968480c83b67f0eb2cafc1df82dbf6dcac0811f36fbd405f20c46f158da5315808080a0ac59032c139346dba6925ea119f110bc037a945991f7349e218edbe12d6d43e9808080a0f4ae3d0d998ac3c8f5118c8ef3ce2ef3dc0440a900323177580df0f212f8b36380a070f09e0afc485ee4555a5c2bcb5380fe4745dfb619c97ce55ca368555f4c0358a069a571829b9b6f89efb0b65e66e59e5a26b2eb72cdfce949e0aec5e0037357bda0acc98ed24983a10e645870d5b47d42f6a1c47d94ac9165221722626a99b3660c80a05f1ef1b2e89b5ed4e71249e76600493c718bc6c6030189bfab281c7b85389a2c80", + "c3165ef5b21e80c163531f807c25789fef8810eda00ae7ca5ced381ff9a9515a": "0xf872a03aea7c8c479e9ff598fc761670d034e3eff2ebadb1e3769b349b2d1663d23913b84ff84d8089056bc75e2d63100000a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "1b83601c6f891d16b1422e65ed3cd47bcbe1342010db6168a0508de8597ac327": "0xf90131a06e94ede82e8c381d422f010130a4c2ed35805be58e6783d800fbb37d000090e2a00968480c83b67f0eb2cafc1df82dbf6dcac0811f36fbd405f20c46f158da5315808080a0ac59032c139346dba6925ea119f110bc037a945991f7349e218edbe12d6d43e9808080a0f4ae3d0d998ac3c8f5118c8ef3ce2ef3dc0440a900323177580df0f212f8b363a0c3165ef5b21e80c163531f807c25789fef8810eda00ae7ca5ced381ff9a9515aa070f09e0afc485ee4555a5c2bcb5380fe4745dfb619c97ce55ca368555f4c0358a069a571829b9b6f89efb0b65e66e59e5a26b2eb72cdfce949e0aec5e0037357bda0acc98ed24983a10e645870d5b47d42f6a1c47d94ac9165221722626a99b3660c80a05f1ef1b2e89b5ed4e71249e76600493c718bc6c6030189bfab281c7b85389a2c80", + "82f6e0ef9d3ec62e68c811432d52e6e0c907d604aed5a2a561d95e393f487d68": "0xf872a0209f0f05f155b5df3bbdd079fa47bedd6da0e32966c72f92264d98e80248858eb84ff84d8089056bc75e2d63100000a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "cdeaf028a7a2894d4778d6c412bfb95e81b23c2e6044f4c5d6de2ed8a50f78f3": "0xf872a020591967aed668a4b27645ff40c444892d91bf5951b382995d4d4f6ee3a2ce03b84ff84d8089056bc75e2d63100000a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "9d1b5f3c8944300dda9eec33376308282aa06c11d3fdc640669ce5e506edb797": "0xf85180a0cdeaf028a7a2894d4778d6c412bfb95e81b23c2e6044f4c5d6de2ed8a50f78f3808080808080808080a082f6e0ef9d3ec62e68c811432d52e6e0c907d604aed5a2a561d95e393f487d688080808080", + "0733321bda3c83f42aeeb32f8dcad18bb4f4c2b80fa60dee4b6eb25f0952524c": "0xf90131a06e94ede82e8c381d422f010130a4c2ed35805be58e6783d800fbb37d000090e2a00968480c83b67f0eb2cafc1df82dbf6dcac0811f36fbd405f20c46f158da5315808080a0ac59032c139346dba6925ea119f110bc037a945991f7349e218edbe12d6d43e9808080a0f4ae3d0d998ac3c8f5118c8ef3ce2ef3dc0440a900323177580df0f212f8b363a0c3165ef5b21e80c163531f807c25789fef8810eda00ae7ca5ced381ff9a9515aa09d1b5f3c8944300dda9eec33376308282aa06c11d3fdc640669ce5e506edb797a069a571829b9b6f89efb0b65e66e59e5a26b2eb72cdfce949e0aec5e0037357bda0acc98ed24983a10e645870d5b47d42f6a1c47d94ac9165221722626a99b3660c80a05f1ef1b2e89b5ed4e71249e76600493c718bc6c6030189bfab281c7b85389a2c80", + "0932e0165ad0cabdfe9d8fb6a70150033d789cd07caaf499c8a37141495499c3": "0xf872a020a258265696d227eef589fd6cd14671a82aa2963ec2214eb048fca5441c4a7eb84ff84d8089056bc75e2d63100000a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "aff16a3ca0d6e3544a2d4deb40842cebaf9325e6a98f2d6edc4cdce5d853e5d8": "0xf87180808080a035196d12c07e2405a02d095f74880568965618e95b50e64e8690594aa6bb5ea280808080a0021eda8d86f1724d84a155e5e0227744e3fb2f570089a70ae65750d24410fe10808080a00932e0165ad0cabdfe9d8fb6a70150033d789cd07caaf499c8a37141495499c3808080", + "a137d310a084b364dfbf0de1114f64e94253e42baa0297980c4a88db4e7d9aa8": "0xf90131a06e94ede82e8c381d422f010130a4c2ed35805be58e6783d800fbb37d000090e2a00968480c83b67f0eb2cafc1df82dbf6dcac0811f36fbd405f20c46f158da5315808080a0ac59032c139346dba6925ea119f110bc037a945991f7349e218edbe12d6d43e9808080a0aff16a3ca0d6e3544a2d4deb40842cebaf9325e6a98f2d6edc4cdce5d853e5d8a0c3165ef5b21e80c163531f807c25789fef8810eda00ae7ca5ced381ff9a9515aa09d1b5f3c8944300dda9eec33376308282aa06c11d3fdc640669ce5e506edb797a069a571829b9b6f89efb0b65e66e59e5a26b2eb72cdfce949e0aec5e0037357bda0acc98ed24983a10e645870d5b47d42f6a1c47d94ac9165221722626a99b3660c80a05f1ef1b2e89b5ed4e71249e76600493c718bc6c6030189bfab281c7b85389a2c80", + "9aceb391e41ce30a6ee2c0c568b850f9fde2e425b767f72e7f4d9cc76e8271ec": "0xf872a020be3e504ac4e35541bebad4d0e7574668e16fefa26cd4172f93e18b59ce9486b84ff84d8089056bc75e2d63100000a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "090d9dec4c66aadc432a96de820eb6fb44489111b3b6f1f397cd9a44a0014882": "0xf872a0209ae219c4bbc2c5eaa1cd472f76bd0211bbf31053549dd7771cc573d3ed197fb84ff84d8089056bc75e2d63100000a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "819c926feb18dee3be8e9daa7ab62abe91febb2caceac5e8038b048d7a4bed0d": "0xf851808080808080808080808080a0090d9dec4c66aadc432a96de820eb6fb44489111b3b6f1f397cd9a44a00148828080a09aceb391e41ce30a6ee2c0c568b850f9fde2e425b767f72e7f4d9cc76e8271ec80", + "53ac286d5d31f0a7f768060b7f9f198956d75c903a698ae4fbb3dcc9f9d5e0b8": "0xf90131a06e94ede82e8c381d422f010130a4c2ed35805be58e6783d800fbb37d000090e2a00968480c83b67f0eb2cafc1df82dbf6dcac0811f36fbd405f20c46f158da5315808080a0ac59032c139346dba6925ea119f110bc037a945991f7349e218edbe12d6d43e9808080a0aff16a3ca0d6e3544a2d4deb40842cebaf9325e6a98f2d6edc4cdce5d853e5d8a0c3165ef5b21e80c163531f807c25789fef8810eda00ae7ca5ced381ff9a9515aa09d1b5f3c8944300dda9eec33376308282aa06c11d3fdc640669ce5e506edb797a069a571829b9b6f89efb0b65e66e59e5a26b2eb72cdfce949e0aec5e0037357bda0819c926feb18dee3be8e9daa7ab62abe91febb2caceac5e8038b048d7a4bed0d80a05f1ef1b2e89b5ed4e71249e76600493c718bc6c6030189bfab281c7b85389a2c80", + "1a0e275dfddaeead8d1fa18c665c7e19b15dc769d3ede56c4a85377edc877110": "0xf8719f20e219c4bbc2c5eaa1cd472f76bd0211bbf31053549dd7771cc573d3ed197fb84ff84d8089056bc75e2d63100000a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "ff695f1ea854ce96ed9c761374f9cc42179fddef3c76a01c05f7f1bb19725ef8": "0xf8719f201e8c4eba798a431ca40726ca69bda8c7067f1690340e5b0a08d83d00d9cbb84ff84d8089056bc75e2d63100000a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "f96f3afee8124cd65bfb12ead5b9bd737c7def4cb7f7c71b82b00d5da23cd77c": "0xf85180808080a0ff695f1ea854ce96ed9c761374f9cc42179fddef3c76a01c05f7f1bb19725ef88080808080a01a0e275dfddaeead8d1fa18c665c7e19b15dc769d3ede56c4a85377edc877110808080808080", + "d8394fa4bbb65976fe11ee9de67bd6f0fb3fa3d7b36ee09f1421dae79b17b95f": "0xe219a0f96f3afee8124cd65bfb12ead5b9bd737c7def4cb7f7c71b82b00d5da23cd77c", + "853082590f798e998c021e6cf314a77c9a9fa6321048ad84cd12210b7aca706a": "0xf851808080808080808080808080a0d8394fa4bbb65976fe11ee9de67bd6f0fb3fa3d7b36ee09f1421dae79b17b95f8080a09aceb391e41ce30a6ee2c0c568b850f9fde2e425b767f72e7f4d9cc76e8271ec80", + "29a7ea17591b34ca73ee13832a64db6d8565d9ab4dbafea03842fabe139016fa": "0xf90131a06e94ede82e8c381d422f010130a4c2ed35805be58e6783d800fbb37d000090e2a00968480c83b67f0eb2cafc1df82dbf6dcac0811f36fbd405f20c46f158da5315808080a0ac59032c139346dba6925ea119f110bc037a945991f7349e218edbe12d6d43e9808080a0aff16a3ca0d6e3544a2d4deb40842cebaf9325e6a98f2d6edc4cdce5d853e5d8a0c3165ef5b21e80c163531f807c25789fef8810eda00ae7ca5ced381ff9a9515aa09d1b5f3c8944300dda9eec33376308282aa06c11d3fdc640669ce5e506edb797a069a571829b9b6f89efb0b65e66e59e5a26b2eb72cdfce949e0aec5e0037357bda0853082590f798e998c021e6cf314a77c9a9fa6321048ad84cd12210b7aca706a80a05f1ef1b2e89b5ed4e71249e76600493c718bc6c6030189bfab281c7b85389a2c80", + "48e73baa24091198f9b69f9c7d27ba256fc19dddebf64448a7a0fd3df28d727d": "0xf872a020ea7c8c479e9ff598fc761670d034e3eff2ebadb1e3769b349b2d1663d23913b84ff84d8089056bc75e2d63100000a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "dc3d58bdcff5ea646a823bebe53ec4ab457ca425e952485f0da477b44fd7bacd": "0xf872a020e7c546eb582218cf94b848c36f3b058e2518876240ae6100c4ef23d38f3e07b84ff84d8089056bc75e2d63100000a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "bff66d9133cff6e91fe1878473b09aee9458c323efa078340d914a82de546bab": "0xf85180808080808080808080a048e73baa24091198f9b69f9c7d27ba256fc19dddebf64448a7a0fd3df28d727d80808080a0dc3d58bdcff5ea646a823bebe53ec4ab457ca425e952485f0da477b44fd7bacd80", + "c87ee106e21de6f375b1424af09b5235d42f0524163ba739aa52ff49cf6e0fb9": "0xf90131a06e94ede82e8c381d422f010130a4c2ed35805be58e6783d800fbb37d000090e2a00968480c83b67f0eb2cafc1df82dbf6dcac0811f36fbd405f20c46f158da5315808080a0ac59032c139346dba6925ea119f110bc037a945991f7349e218edbe12d6d43e9808080a0aff16a3ca0d6e3544a2d4deb40842cebaf9325e6a98f2d6edc4cdce5d853e5d8a0bff66d9133cff6e91fe1878473b09aee9458c323efa078340d914a82de546baba09d1b5f3c8944300dda9eec33376308282aa06c11d3fdc640669ce5e506edb797a069a571829b9b6f89efb0b65e66e59e5a26b2eb72cdfce949e0aec5e0037357bda0853082590f798e998c021e6cf314a77c9a9fa6321048ad84cd12210b7aca706a80a05f1ef1b2e89b5ed4e71249e76600493c718bc6c6030189bfab281c7b85389a2c80", + "465ac2797ac8828138ad632344c4e349f027f0dc13f2f224451a1f2539b53217": "0xf838a120290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5639594c5f6a39480968b8d09315d749375855b550cf5d2", + "bf40a9d1703e12b6e9adbdd4b52bf85a3bbfaab8a48efdeb37183698aee5c470": "0xf872a03931b4ed56ace4c46b68524cb5bcbf4195f1bbaacbe5228fbd090546c88dd229b84ff84d8089056bc75e2d57243e00a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "1958a370471369a2e1d116023894797927853141dd11d84f7439422ac1886f11": "0xf90131a06e94ede82e8c381d422f010130a4c2ed35805be58e6783d800fbb37d000090e2a00968480c83b67f0eb2cafc1df82dbf6dcac0811f36fbd405f20c46f158da5315808080a0bf40a9d1703e12b6e9adbdd4b52bf85a3bbfaab8a48efdeb37183698aee5c470808080a0aff16a3ca0d6e3544a2d4deb40842cebaf9325e6a98f2d6edc4cdce5d853e5d8a0bff66d9133cff6e91fe1878473b09aee9458c323efa078340d914a82de546baba09d1b5f3c8944300dda9eec33376308282aa06c11d3fdc640669ce5e506edb797a069a571829b9b6f89efb0b65e66e59e5a26b2eb72cdfce949e0aec5e0037357bda0853082590f798e998c021e6cf314a77c9a9fa6321048ad84cd12210b7aca706a80a05f1ef1b2e89b5ed4e71249e76600493c718bc6c6030189bfab281c7b85389a2c80", + "5492888cc7c534f4fd1f9f803a9c0c9b14a3aa268d7aa1a226c0b5a2df295078": "0xf872a03931b4ed56ace4c46b68524cb5bcbf4195f1bbaacbe5228fbd090546c88dd229b84ff84d0189056bc75e2d57243e00a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "3385f209bb45a8787ae9ab5792cff76e64c0e643c5b2af01da3825e1418e5c22": "0xf90131a06e94ede82e8c381d422f010130a4c2ed35805be58e6783d800fbb37d000090e2a00968480c83b67f0eb2cafc1df82dbf6dcac0811f36fbd405f20c46f158da5315808080a05492888cc7c534f4fd1f9f803a9c0c9b14a3aa268d7aa1a226c0b5a2df295078808080a0aff16a3ca0d6e3544a2d4deb40842cebaf9325e6a98f2d6edc4cdce5d853e5d8a0bff66d9133cff6e91fe1878473b09aee9458c323efa078340d914a82de546baba09d1b5f3c8944300dda9eec33376308282aa06c11d3fdc640669ce5e506edb797a069a571829b9b6f89efb0b65e66e59e5a26b2eb72cdfce949e0aec5e0037357bda0853082590f798e998c021e6cf314a77c9a9fa6321048ad84cd12210b7aca706a80a05f1ef1b2e89b5ed4e71249e76600493c718bc6c6030189bfab281c7b85389a2c80", + "57ec08b8f040499409fb0220f538477790d4f010c4bb51a8dbae5da3537a86a4": "0xf872a020d82c545c22b72034803633d3dda2b28e89fb704f3c111355ac43e10612aedcb84ff84d8089056bc75e2d63100000a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "9b5e595475007074a246b52a8b850b6a55a1ca47751ed6d715c290926ece7d10": "0xf869a0204b24eae4a02d3987ca887631704554f37941d36d88eba3861c6e365c7804a5b846f8448080a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "8ebfa1bb8d7f17c4c7b061298856df0d764d78874df9bbee0e2607b97a282e6f": "0xf851808080808080a057ec08b8f040499409fb0220f538477790d4f010c4bb51a8dbae5da3537a86a480a09b5e595475007074a246b52a8b850b6a55a1ca47751ed6d715c290926ece7d108080808080808080", + "d4f7345b04cb4e371827c71c4dab83da5e48ebee74d977ff4d485b2fb8acccfe": "0xf90131a06e94ede82e8c381d422f010130a4c2ed35805be58e6783d800fbb37d000090e2a00968480c83b67f0eb2cafc1df82dbf6dcac0811f36fbd405f20c46f158da5315808080a05492888cc7c534f4fd1f9f803a9c0c9b14a3aa268d7aa1a226c0b5a2df295078808080a0aff16a3ca0d6e3544a2d4deb40842cebaf9325e6a98f2d6edc4cdce5d853e5d8a0bff66d9133cff6e91fe1878473b09aee9458c323efa078340d914a82de546baba09d1b5f3c8944300dda9eec33376308282aa06c11d3fdc640669ce5e506edb797a069a571829b9b6f89efb0b65e66e59e5a26b2eb72cdfce949e0aec5e0037357bda0853082590f798e998c021e6cf314a77c9a9fa6321048ad84cd12210b7aca706a80a08ebfa1bb8d7f17c4c7b061298856df0d764d78874df9bbee0e2607b97a282e6f80", + "bb6ee835518e56b6623af794f7aa4fc29ad48c4def725b8a2ff64b38bd22c789": "0xf869a0204b24eae4a02d3987ca887631704554f37941d36d88eba3861c6e365c7804a5b846f8440180a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "78411d2196a2e4c560372788d3e499d0b71f36204f1961a41ef216a7fd574e95": "0xf851808080808080a057ec08b8f040499409fb0220f538477790d4f010c4bb51a8dbae5da3537a86a480a0bb6ee835518e56b6623af794f7aa4fc29ad48c4def725b8a2ff64b38bd22c7898080808080808080", + "66aedbb3dc39b3a989497ee17099845b4807ba47e50b82de95f0da0f6274d60c": "0xf90131a06e94ede82e8c381d422f010130a4c2ed35805be58e6783d800fbb37d000090e2a00968480c83b67f0eb2cafc1df82dbf6dcac0811f36fbd405f20c46f158da5315808080a05492888cc7c534f4fd1f9f803a9c0c9b14a3aa268d7aa1a226c0b5a2df295078808080a0aff16a3ca0d6e3544a2d4deb40842cebaf9325e6a98f2d6edc4cdce5d853e5d8a0bff66d9133cff6e91fe1878473b09aee9458c323efa078340d914a82de546baba09d1b5f3c8944300dda9eec33376308282aa06c11d3fdc640669ce5e506edb797a069a571829b9b6f89efb0b65e66e59e5a26b2eb72cdfce949e0aec5e0037357bda0853082590f798e998c021e6cf314a77c9a9fa6321048ad84cd12210b7aca706a80a078411d2196a2e4c560372788d3e499d0b71f36204f1961a41ef216a7fd574e9580", + "77c1a71be8305f61512f584aa4efe53e798b08a9bde9c34815250f3865c5c998": "0xf869a0204b24eae4a02d3987ca887631704554f37941d36d88eba3861c6e365c7804a5b846f8440180a0465ac2797ac8828138ad632344c4e349f027f0dc13f2f224451a1f2539b53217a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "784e5369c0f78373b69df73b8f6b82440ed0629de04c3de77bf53693a175c19c": "0xf851808080808080a057ec08b8f040499409fb0220f538477790d4f010c4bb51a8dbae5da3537a86a480a077c1a71be8305f61512f584aa4efe53e798b08a9bde9c34815250f3865c5c9988080808080808080", + "3e4feb692f284da6916854dd4bd71895541f80aa30cb8c2ae44670f35db2729c": "0xf90131a06e94ede82e8c381d422f010130a4c2ed35805be58e6783d800fbb37d000090e2a00968480c83b67f0eb2cafc1df82dbf6dcac0811f36fbd405f20c46f158da5315808080a05492888cc7c534f4fd1f9f803a9c0c9b14a3aa268d7aa1a226c0b5a2df295078808080a0aff16a3ca0d6e3544a2d4deb40842cebaf9325e6a98f2d6edc4cdce5d853e5d8a0bff66d9133cff6e91fe1878473b09aee9458c323efa078340d914a82de546baba09d1b5f3c8944300dda9eec33376308282aa06c11d3fdc640669ce5e506edb797a069a571829b9b6f89efb0b65e66e59e5a26b2eb72cdfce949e0aec5e0037357bda0853082590f798e998c021e6cf314a77c9a9fa6321048ad84cd12210b7aca706a80a0784e5369c0f78373b69df73b8f6b82440ed0629de04c3de77bf53693a175c19c80", + "63129aadc37672a5f1d1e205a93d572bf711feca4f8e533762115053a4528db30a": "0x60806040526004361015610011575f80fd5b5f803560e01c806306fdde03146138d75780630d6a03be146138af578063200d2ed21461388b5780632bb2f44e1461324f578063365a86fc14613228578063447ef0c0146130b4578063540218e214612f8c57806354fd4d5014612f4757806355a373d614612f1e5780635c40f6f414612edc57806361fbddc214612eb3578063639a86a314612e8a5780636577454814612e61578063686d487314612c5c5780636b838a5a14612c335780636d6da80c146125b65780637356c4d114611fd25780637b1d97d914611ea35780637cba7353146116735780638129fc1c14611016578063823e2bc714610fed578063953adf8a14610fc4578063996642a514610401578063b518a00e146103d8578063c86da6f8146103af578063e1c94d0a14610365578063f11abfd81461033c578063f42cb038146103135763f94d315b14610159575f80fd5b346102715760203660031901126102715761017261393e565b9061017c826152ef565b60075460405160016245764560e11b031981526001600160481b0384166004820152906001600160a01b0316606082602481845afa93841561030857839284956102cf575b506001600160601b038316156102c0578442106102a857839450813b156102a357838361020392604051938492839263718835e960e11b845260048401613a73565b038183865af1908115610298578491610283575b5050803b1561027f57604051636f6d60d760e11b81523360048201526001600160601b03909216602483015282908290818381604481015b03925af18015610274576102605750f35b8161026a91613954565b6102715780f35b80fd5b6040513d84823e3d90fd5b5050fd5b8161028d91613954565b61027f57825f610217565b6040513d86823e3d90fd5b505050fd5b636bfbbc4560e01b8452426004526024859052604484fd5b63ef96b69b60e01b8452600484fd5b9094506102f591925060603d606011610301575b6102ed8183613954565b8101906139cc565b9291905091935f6101c1565b503d6102e3565b6040513d85823e3d90fd5b50346102715780600319360112610271576006546040516001600160a01b039091168152602090f35b50346102715780600319360112610271576004546040516001600160a01b039091168152602090f35b50346102715760603660031901126102715761037f61393e565b6044356001600160a01b03811681036103ab578161039f6103a8936148b0565b60243590613b7d565b80f35b8280fd5b50346102715780600319360112610271576001546040516001600160a01b039091168152602090f35b50346102715780600319360112610271576007546040516001600160a01b039091168152602090f35b50346102715760603660031901126102715761041b61393e565b906024356001600160481b0381168082036103ab576044356001600160601b03811692838203610b345761044e866148b0565b610457816148b0565b6007546001546001600160a01b03918216976001600160481b038116949092909116858514610f74578615610f655760405160208101903360601b8252601481526104a3603482613954565b5190206104b0338561492b565b600b54604051635cbeecf160e11b815290602090829060049082906001600160a01b03165afa8015610b99578583918c90610f2d575b6104f09350614d23565b50600b54604051635cbeecf160e11b815290602090829060049082906001600160a01b03165afa908115610b99578a91610efb575b505f198101908111610ee757600854604051634bb6ae1560e11b81526001600160a01b03909116919060208180610560338c60048401613aae565b0381865afa908115610cc5576105b391858f928f92610ec7575b5060405163c690956160e01b81526001600160481b038c1660048201526024810191909152929091602091849190829081906044820190565b03915afa918215610ebc578d92610e7c575b5015610e12576001600160601b039192501615610d9d575b505b6105e9338661492b565b600b54604051635cbeecf160e11b815290602090829060049082906001600160a01b03165afa8015610b99578683918c90610d61575b6106299350614d23565b5060405163c690956160e01b81526001600160481b0385166004820152602481018290529960208b604481845afa9a8b15610b99578a9b610d25575b506001600160601b038b16808a11610d0e575060055460405163b5c6b45360e01b815290602090829060049082906001600160a01b03165afa908115610bbd578b91610cd0575b506040516304c49bbd60e21b8152600481018a9052602081602481865afa908115610cc5579086918d91610c74575b506106f06001600160601b03939284926139f5565b91169182911611610c62575061070c848b9c9b98999a9b613a29565b936040516304c49bbd60e21b8152896004820152602081602481865afa8015610c575782908a90610c1a575b6107429250613a29565b926040516304c49bbd60e21b81528b6004820152602081602481875afa8015610b995783908b90610bdd575b61077892506139f5565b93833b15610bb9576040516345b8d37560e01b81528a818061079f8b878e60048501613a49565b038183895af1908115610bbd578b91610bc8575b5050833b15610bb95760405163298a690b60e01b81528a81806107da858d60048401613a73565b038183895af1908115610bbd578b91610ba4575b50506107fa908861543d565b843b15610b80576040516207ee5360e61b81528981600481838a5af1908115610b99578a91610b84575b5050823b15610b8057604051636ca3585d60e11b81529189918391829161085091908c60048501613a49565b038183865af1908115610b75578891610b60575b5050803b15610b5c5786604051809263298a690b60e01b825281838161088e888d60048401613a73565b03925af1908115610b51578791610b38575b50506108ac90856150d6565b803b15610b34578480916004604051809481936207ee5360e61b83525af1908115610b29578591610b14575b50506001600160601b031615610aad575b506008546040516331110b9160e01b81526001600160a01b039091169060208180610918338760048401613aae565b0381855afa908115610298578491610a8e575b5015610a39575b50600854604051634bb6ae1560e11b81526001600160a01b03909116916020908290819061096590339060048401613aae565b0381855afa908115610308578391610a0a575b50156109b0575b50506040519283527f326b1ff11f9cd7ab8813bdd65fa011661686e6fd1d3704a128e9f4baea315eb960203394a480f35b803b15610a065781809160646040518094819363f7f2b2c360e01b8352896004840152336024840152600160448401525af18015610274571561097f57816109f791613954565b610a0257835f61097f565b8380fd5b5080fd5b610a2c915060203d602011610a32575b610a248183613954565b810190613a96565b5f610978565b503d610a1a565b803b156103ab5782604051809263743e62bb60e11b8252818381610a61338960048401613aae565b03925af1908115610308578391610a79575b50610932565b81610a8391613954565b610a0657815f610a73565b610aa7915060203d602011610a3257610a248183613954565b5f61092b565b6008546001600160a01b0316803b15610a0257604051633be5af8f60e21b81529184918391829084908290610ae790339060048401613aae565b03925af1908115610308578391610aff575b506108e9565b81610b0991613954565b610a0657815f610af9565b81610b1e91613954565b610a0257835f6108d8565b6040513d87823e3d90fd5b8480fd5b81610b4291613954565b610b4d57855f6108a0565b8580fd5b6040513d89823e3d90fd5b8680fd5b81610b6a91613954565b610b5c57865f610864565b6040513d8a823e3d90fd5b8880fd5b81610b8e91613954565b610b8057885f610824565b6040513d8c823e3d90fd5b81610bae91613954565b610bb957895f6107ee565b8980fd5b6040513d8d823e3d90fd5b81610bd291613954565b610bb957895f6107b3565b50506020813d602011610c12575b81610bf860209383613954565b81010312610bb95782610c0d610778926139b8565b61076e565b3d9150610beb565b50506020813d602011610c4f575b81610c3560209383613954565b81010312610b805781610c4a610742926139b8565b610738565b3d9150610c28565b6040513d8b823e3d90fd5b633fc3853b60e01b8b5260045260248afd5b9150506020813d602011610cbd575b81610c9060209383613954565b81010312610cb957906001600160601b036106f087610caf83956139b8565b92509293506106db565b8b80fd5b3d9150610c83565b6040513d8e823e3d90fd5b90506020813d602011610d06575b81610ceb60209383613954565b81010312610d0257610cfc906139b8565b5f6106ac565b8a80fd5b3d9150610cde565b63177265ed60e01b8b52600452602489905260448afd5b909a506020813d602011610d59575b81610d4160209383613954565b81010312610bb957610d52906139b8565b995f610665565b3d9150610d34565b5050506020813d602011610d95575b81610d7d60209383613954565b81010312610d91578186610629925161061f565b5f80fd5b3d9150610d70565b6008546001600160a01b031690813b15610d025760405163058f15c160e21b81526001600160481b03881660048201523360248201526044810191909152908a908290606490829084905af18015610b9957908a91610dfd575b506105dd565b81610e0791613954565b610b8057885f610df7565b50813b15610d025760405163058f15c160e21b81526001600160481b03881660048201523360248201526044810191909152908a908290606490829084905af18015610b9957908a91610e67575b50506105df565b81610e7191613954565b610b8057885f610e60565b9091506020813d602011610eb4575b81610e9860209383613954565b81010312610eb057610ea9906139b8565b905f6105c5565b8c80fd5b3d9150610e8b565b6040513d8f823e3d90fd5b60209250610ee190833d8511610a3257610a248183613954565b9161057a565b634e487b7160e01b8a52601160045260248afd5b90506020813d602011610f25575b81610f1660209383613954565b81010312610d9157515f610525565b3d9150610f09565b5050506020813d602011610f5d575b81610f4960209383613954565b81010312610d915781856104f092516104e6565b3d9150610f3c565b6382c4a8c960e01b8852600488fd5b60405162461bcd60e51b815260206004820152602260248201527f43616e6e6f7420726564656c656761746520746f207468652073616d65206e6f604482015261646560f01b6064820152608490fd5b5034610271578060031936011261027157600a546040516001600160a01b039091168152602090f35b50346102715780600319360112610271576002546040516001600160a01b039091168152602090f35b503461027157806003193601126102715761102f615395565b8054604051630110ceef60e21b8152602060048201819052600360248301526241736b60e81b60448301526001600160a01b039092169181606481855afa908115610308578391611654575b5060018060a01b03166001600160601b0360a01b6001541617600155604051630110ceef60e21b81526020600482015260146024820152735368617264696e675461626c6553746f7261676560601b6044820152602081606481855afa908115610308578391611635575b5060018060a01b03166001600160601b0360a01b6002541617600255604051630110ceef60e21b815260206004820152600d60248201526c5368617264696e675461626c6560981b6044820152602081606481855afa908115610308578391611616575b5060018060a01b03166001600160601b0360a01b6003541617600355604051630110ceef60e21b815260206004820152600f60248201526e4964656e7469747953746f7261676560881b6044820152602081606481855afa9081156103085783916115f7575b5060018060a01b03166001600160601b0360a01b6004541617600455604051630110ceef60e21b8152602060048201526011602482015270506172616d657465727353746f7261676560781b6044820152602081606481855afa9081156103085783916115d8575b5060018060a01b03166001600160601b0360a01b6005541617600555604051630110ceef60e21b815260206004820152600e60248201526d50726f66696c6553746f7261676560901b6044820152602081606481855afa9081156103085783916115b9575b5060018060a01b03166001600160601b0360a01b6006541617600655604051630110ceef60e21b815260206004820152600e60248201526d5374616b696e6753746f7261676560901b6044820152602081606481855afa90811561030857839161159a575b5060018060a01b03166001600160601b0360a01b6007541617600755604051630110ceef60e21b815260206004820152600e60248201526d44656c656761746f7273496e666f60901b6044820152602081606481855afa90811561030857839161157b575b5060018060a01b03166001600160601b0360a01b6008541617600855604051630110ceef60e21b81526020600482015260056024820152642a37b5b2b760d91b6044820152602081606481855afa90811561030857839161155c575b5060018060a01b03166001600160601b0360a01b6009541617600955604051630110ceef60e21b815260206004820152601560248201527452616e646f6d53616d706c696e6753746f7261676560581b6044820152602081606481855afa90811561030857839161153d575b5060018060a01b03166001600160601b0360a01b600a541617600a55604051630110ceef60e21b81526020600482015260076024820152664368726f6e6f7360c81b6044820152602081606481855afa918215610308576064926020928591611520575b5060018060a01b03166001600160601b0360a01b600b541617600b5560405192838092630110ceef60e21b8252846004830152600c60248301526b45706f636853746f7261676560a01b60448301525afa9081156102745782916114f1575b5060018060a01b03166001600160601b0360a01b600c541617600c5580f35b611513915060203d602011611519575b61150b8183613954565b810190613b06565b5f6114d2565b503d611501565b6115379150833d85116115195761150b8183613954565b5f611473565b611556915060203d6020116115195761150b8183613954565b5f61140f565b611575915060203d6020116115195761150b8183613954565b5f6113a3565b611594915060203d6020116115195761150b8183613954565b5f611347565b6115b3915060203d6020116115195761150b8183613954565b5f6112e2565b6115d2915060203d6020116115195761150b8183613954565b5f61127d565b6115f1915060203d6020116115195761150b8183613954565b5f611218565b611610915060203d6020116115195761150b8183613954565b5f6111b0565b61162f915060203d6020116115195761150b8183613954565b5f61114a565b61164e915060203d6020116115195761150b8183613954565b5f6110e6565b61166d915060203d6020116115195761150b8183613954565b5f61107b565b50346102715760403660031901126102715761168d61393e565b906116966139a2565b916116a0816148b0565b6009546007546001600160a01b03918216949116916001600160601b038216918215611e9457604051636eb1769f60e11b81523360048201523060248201526020816044818a5afa908115611dd0579084918791611e5f575b5010611ddb576040516370a0823160e01b81523360048201526020816024818a5afa908115611dd0579084918791611d9b575b5010611d1d579084959491611741338361492b565b60405160208101903360601b82526014815261175e603482613954565b519020600b54604051635cbeecf160e11b815290602090829060049082906001600160a01b03165afa908115610b29578591611ce6575b5081846117a192614d23565b5060075460405163c690956160e01b81526001600160481b0385166004820152602481018390529190602090839060449082906001600160a01b03165afa918215610b29578592611caa575b506040516304c49bbd60e21b81526001600160481b0385166004820181905293906020816024818c5afa8015610b515782908890611c6d575b61183092506139f5565b9260018060a01b036005541660405163b5c6b45360e01b8152602081600481855afa8015610c57578990611c2d575b6001600160601b039150166001600160601b03861611611ba3575090611884916139f5565b90873b15610b4d576040516345b8d37560e01b8152918691839182916118af91908960048501613a49565b0381838b5af1908115610b29578591611b8e575b5050853b15610a025760405163298a690b60e01b81528481806118ea858860048401613a73565b0381838b5af1908115610b29578591611b79575b5050853b15610a0257604051633ada6a6360e01b8152600481018690528481602481838b5af1908115610b29578591611b64575b505061193e90836150d6565b6001546001600160a01b0316803b15610a02578380916004604051809481936207ee5360e61b83525af1908115610298578491611b4f575b50506008546040516331110b9160e01b81526001600160a01b0390911690602081806119a6338860048401613aae565b0381855afa908115610b29578591611b30575b5015611adb575b50600854604051634bb6ae1560e11b81526001600160a01b0390911692602090829081906119f390339060048401613aae565b0381865afa908115610298578491611abc575b5015611a63575b505060209260649160405195869485936323b872dd60e01b8552336004860152602485015260448401525af1801561027457611a47575080f35b611a5f9060203d602011610a3257610a248183613954565b5080f35b813b156103ab57829160648392604051948593849263f7f2b2c360e01b84526004840152336024840152600160448401525af1801561027457611aa7575b80611a0d565b81611ab191613954565b610a0257835f611aa1565b611ad5915060203d602011610a3257610a248183613954565b5f611a06565b803b15610a025783604051809263743e62bb60e11b8252818381611b03338a60048401613aae565b03925af1908115610298578491611b1b575b506119c0565b81611b2591613954565b6103ab57825f611b15565b611b49915060203d602011610a3257610a248183613954565b5f6119b9565b81611b5991613954565b6103ab57825f611976565b81611b6e91613954565b610a0257835f611932565b81611b8391613954565b610a0257835f6118fe565b81611b9891613954565b610a0257835f6118c3565b6004602089926040519283809263b5c6b45360e01b82525afa908115610274578291611be6575b633fc3853b60e01b83526001600160601b038216600452602483fd5b90506020813d602011611c25575b81611c0160209383613954565b81010312610a0657906001600160601b03611c1d6024936139b8565b919250611bca565b3d9150611bf4565b506020813d602011611c65575b81611c4760209383613954565b81010312610b8057611c606001600160601b03916139b8565b61185f565b3d9150611c3a565b50506020813d602011611ca2575b81611c8860209383613954565b81010312610b5c5781611c9d611830926139b8565b611826565b3d9150611c7b565b9091506020813d602011611cde575b81611cc660209383613954565b81010312610b3457611cd7906139b8565b905f6117ed565b3d9150611cb9565b9450506020843d602011611d15575b81611d0260209383613954565b81010312610d9157925187939081611795565b3d9150611cf5565b50506040516370a0823160e01b815233600482015293909150602084602481845afa908115610308578391611d66575b631f32daeb60e21b845260045260245260445260649150fd5b90506020843d602011611d93575b81611d8160209383613954565b81010312610d91576064935190611d4d565b3d9150611d74565b9150506020813d602011611dc8575b81611db760209383613954565b81010312610d91578390515f61172c565b3d9150611daa565b6040513d88823e3d90fd5b5050604051636eb1769f60e11b815233600482015230602482015293909150602084604481845afa908115610308578391611e2a575b637000ca7760e01b845260045260245260445260649150fd5b90506020843d602011611e57575b81611e4560209383613954565b81010312610d91576064935190611e11565b3d9150611e38565b9150506020813d602011611e8c575b81611e7b60209383613954565b81010312610d91578390515f6116f9565b3d9150611e6e565b6382c4a8c960e01b8552600485fd5b503461027157602036600319011261027157611ebd61393e565b90611ec7826148b0565b60018060a01b036007541660405160208101903360601b825260148152611eef603482613954565b5190206040516337e50bf160e01b81526001600160481b0385166004820152602481018290529190606083604481855afa9485156102985784938596611fa9575b506001600160601b03841615611f9a57854210611f8257849550823b15610b34576040516308962e4760e21b81526001600160481b039091166004820152602481019190915283818060448101610203565b636bfbbc4560e01b8552426004526024869052604485fd5b63ef96b69b60e01b8552600485fd5b909550611fc691935060603d606011610301576102ed8183613954565b9391905092945f611f30565b503461027157604036600319011261027157611fec61393e565b90611ff56139a2565b611ffe836148b0565b60018060a01b03600754166001600160601b0382169384156125a757612024338261492b565b60405160208101903360601b825260148152612041603482613954565b519020600b54604051635cbeecf160e11b815291929190602090829060049082906001600160a01b03165afa8015611dd057828491889061256f575b6120879350614d23565b5060405163c690956160e01b81526001600160481b03821660048201526024810183905295602087604481875afa968715611dd0578697612533575b506001600160601b03871680821161251e57506120e1858798613a29565b6040516304c49bbd60e21b81526001600160481b0384166004820152602081602481895afa8015610b7557879089906124e1575b61211f9250613a29565b91853b1561241f576040516345b8d37560e01b8152888180612146868a8a60048501613a49565b0381838b5af1908115610c575789916124cc575b5050853b1561241f5760405163298a690b60e01b8152888180612181878960048401613a73565b0381838b5af1908115610c575789916124b7575b5050853b1561241f576040519063e1d78b2b60e01b825260048201528781602481838a5af1908115610b755788916124a2575b50506121d4828461543d565b6001546001600160a01b0316803b1561241f578780916004604051809481936207ee5360e61b83525af1908115610b7557889161248d575b50506001600160601b03161561242b575b60055460405163b5c6b45360e01b81526001600160a01b039091169190602081600481865afa908115610b755788916123e3575b506001600160601b039081169116106122b057505050803b1561027f57604051636f6d60d760e11b81523360048201526001600160601b03909216602483015282908290818381604481015b03925af180156102745761026057505080f35b6040516337e50bf160e01b81526001600160481b0383166004820152602481018490529294919390929091606082604481865afa918215610b5157600492602092612302928a926123c0575b506139f5565b936040519283809263151db1b960e01b82525afa908115611dd0578691612388575b5061232f9042613af9565b93813b15610b4d57604051630185e24960e31b81526001600160481b03909416600485015260248401526001600160601b0390911660448301525f60648301526084820192909252908290829081838160a4810161229d565b9550506020853d6020116123b8575b816123a460209383613954565b81010312610d915761232f86955190612324565b3d9150612397565b6123da91925060603d606011610301576102ed8183613954565b5050905f6122fc565b90506020813d602011612423575b816123fe60209383613954565b8101031261241f576001600160601b0361241881926139b8565b9150612251565b8780fd5b3d91506123f1565b6008546001600160a01b0316803b15610b5c57866040518092633be5af8f60e21b825281838161245f338a60048401613aae565b03925af1908115610b51578791612478575b505061221d565b8161248291613954565b610b4d57855f612471565b8161249791613954565b610b5c57865f61220c565b816124ac91613954565b610b5c57865f6121c8565b816124c191613954565b61241f57875f612195565b816124d691613954565b61241f57875f61215a565b50506020813d602011612516575b816124fc60209383613954565b8101031261241f578661251161211f926139b8565b612115565b3d91506124ef565b63177265ed60e01b8752600452602452604485fd5b9096506020813d602011612567575b8161254f60209383613954565b81010312610b4d57612560906139b8565b955f6120c3565b3d9150612542565b5050506020813d60201161259f575b8161258b60209383613954565b81010312610d91578282612087925161207d565b3d915061257e565b6382c4a8c960e01b8452600484fd5b5034610271576040366003190112610271576125d061393e565b906125d96139a2565b916125e3816152ef565b6007546001600160a01b03166001600160601b03841680156125a75760405191637946927960e11b83526001600160481b03841691826004850152602084602481855afa938415611dd0578694612bf7575b506001600160601b03841696878211612be0579086939291612657338861492b565b60405160208101903360601b825260148152612674603482613954565b519020600b54604051635cbeecf160e11b815291979190602090829060049082906001600160a01b03165afa908115610b515788918a918991612ba3575b5084926126c994926126c392614d23565b50613a29565b833b15610b4d57856126f091604051809381926357a46be960e11b83528c60048401613a73565b038183885af1908115611dd0578691612b8e575b505060405163c690956160e01b81526001600160481b03881660048201526024810187905295602087604481875afa968715611dd0578697612b52575b506040516304c49bbd60e21b815260048101869052602081602481885afa8015610b515783908890612b15575b61277892506139f5565b9660018060a01b036005541660405163b5c6b45360e01b8152602081600481855afa8015610c57578990612ad5575b6001600160601b039150166001600160601b038a1611611ba35750826127cc916139f5565b90843b15610b5c576040516345b8d37560e01b8152918791839182916127f791908d60048501613a49565b038183885af1908115611dd0578691612ac0575b5050823b15610b345760405163298a690b60e01b81528581806128328a8c60048401613a73565b038183885af1908115611dd0578691612aab575b5050823b15610b34578461286f916040518093819263718835e960e11b83528b60048401613a73565b038183875af1908115610b29578591612a96575b5050813b15610a02578391602483926040519485938492633ada6a6360e01b845260048401525af1908115610308578391612a81575b50506008546040516331110b9160e01b81526001600160a01b0390911690602081806128e9338a60048401613aae565b0381855afa908115610298578491612a62575b5015612a0d575b50600854604051634bb6ae1560e11b81526001600160a01b03909116919060208180612933338a60048401613aae565b0381865afa9081156102985784916129ee575b5015612995575b505050612959916150d6565b60015481906001600160a01b0316803b15612992578180916004604051809481936207ee5360e61b83525af18015610274576102605750f35b50fd5b813b156103ab57829160648392604051948593849263f7f2b2c360e01b84526004840152336024840152600160448401525af18015610274576129d9575b8061294d565b816129e391613954565b6103ab5782846129d3565b612a07915060203d602011610a3257610a248183613954565b87612946565b803b156103ab5782604051809263743e62bb60e11b8252818381612a35338c60048401613aae565b03925af1908115610308578391612a4d575b50612903565b81612a5791613954565b610a06578186612a47565b612a7b915060203d602011610a3257610a248183613954565b876128fc565b81612a8b91613954565b610a065781866128b9565b81612aa091613954565b610a02578388612883565b81612ab591613954565b610b34578489612846565b81612aca91613954565b610b3457848961280b565b506020813d602011612b0d575b81612aef60209383613954565b81010312610b8057612b086001600160601b03916139b8565b6127a7565b3d9150612ae2565b50506020813d602011612b4a575b81612b3060209383613954565b81010312610b5c5782612b45612778926139b8565b61276e565b3d9150612b23565b9096506020813d602011612b86575b81612b6e60209383613954565b81010312610b4d57612b7f906139b8565b9589612741565b3d9150612b61565b81612b9891613954565b610b34578489612704565b98505050506020863d602011612bd8575b81612bc160209383613954565b81010312610d9157945188959087908990846126b2565b3d9150612bb4565b604487838a63b354dd2d60e01b8352600452602452fd5b9093506020813d602011612c2b575b81612c1360209383613954565b81010312610b4d57612c24906139b8565b925f612635565b3d9150612c06565b50346102715780600319360112610271576003546040516001600160a01b039091168152602090f35b503461027157604036600319011261027157612c7661393e565b90612c7f6139a2565b91612c89816152ef565b6007546001600160a01b0316906001600160601b03841680156125a75760405192637946927960e11b84526001600160481b03831692836004860152602085602481855afa948515611dd0578695612e25575b506001600160601b03851696878411612e0e5760055460405163151db1b960e01b8152979850889790602090829060049082906001600160a01b03165afa908115610b75578891612dd5575b5090612d37612d3d9242613af9565b96613a29565b90823b15610b5c576040516357a46be960e11b815291879183918291612d67919060048401613a73565b038183865af1908115611dd0578691612dc0575b5050803b15610b345784928360849260405196879586946355b2622160e01b86526004860152602485015282604485015260648401525af18015610274576102605750f35b81612dca91613954565b610b3457845f612d7b565b919750506020813d602011612e06575b81612df260209383613954565b81010312610d915751879690612d37612d28565b3d9150612de5565b604487858a63b354dd2d60e01b8352600452602452fd5b9094506020813d602011612e59575b81612e4160209383613954565b81010312610b4d57612e52906139b8565b935f612cdc565b3d9150612e34565b5034610271578060031936011261027157600b546040516001600160a01b039091168152602090f35b50346102715780600319360112610271576005546040516001600160a01b039091168152602090f35b50346102715780600319360112610271576008546040516001600160a01b039091168152602090f35b503461027157602036600319011261027157600435801515809103610a0657612f03615395565b815460ff60a01b191660a09190911b60ff60a01b1617815580f35b50346102715780600319360112610271576009546040516001600160a01b039091168152602090f35b503461027157806003193601126102715750612f88604051612f6a604082613954565b6005815264312e302e3160d81b602082015260405191829182613914565b0390f35b503461027157602036600319011261027157612fa661393e565b90612fb0826152ef565b6007546040516327ac00d160e01b81526001600160481b03841660048201819052936001600160a01b039092169190602081602481865afa90811561029857849161307a575b506001600160601b038116156102c0578394833b15610b345760405190639bd1c02b60e01b82526004820152848160248183885af1908115610b29578591613065575b5050823b156102a35761024f9284928360405180968195829463216972d760e11b845260048401613a73565b8161306f91613954565b6102a357835f613039565b90506020813d6020116130ac575b8161309560209383613954565b81010312610a02576130a6906139b8565b5f612ff6565b3d9150613088565b5034610271576060366003190112610271576130ce61393e565b60243567ffffffffffffffff81116103ab57366023820112156103ab578060040135906130fa8261398a565b916131086040519384613954565b8083526024602084019160051b83010191368311610b4d57602401905b828210613218575050506044359167ffffffffffffffff8311610a025736602384011215610a0257826004013561315b8161398a565b936131696040519586613954565b8185526024602086019260051b82010190368211610b5c57602401915b8183106131f857505050613199816148b0565b83925b82518410156131f457845b81518110156131e9576001906131e36131c08787613ad1565b51838060a01b036131d18487613ad1565b5116906131dd876148b0565b86613b7d565b016131a7565b50926001019261319c565b8480f35b82356001600160a01b038116810361241f57815260209283019201613186565b8135815260209182019101613125565b5034610271578060031936011261027157546040516001600160a01b039091168152602090f35b5034610d91576020366003190112610d915761326961393e565b90613273826148b0565b60018060a01b036007541660405160208101903360601b82526014815261329b603482613954565b5190206040516337e50bf160e01b81526001600160481b0385166004820152602481018290529390606085604481865afa8015613759575f955f91613864575b506001600160601b03861615613855576132f5338461492b565b600b54604051635cbeecf160e11b815290602090829060049082906001600160a01b03165afa8015613759578484915f9061381d575b6133359350614d23565b506040516304c49bbd60e21b81526001600160481b038416600482018190529290602081602481895afa908115613759575f916137e3575b5060055460405163b5c6b45360e01b815290602090829060049082906001600160a01b03165afa908115613759575f916137a9575b505f6133ae8a846139f5565b6001600160601b03838116911611156137a157506133cf826133d692613a29565b8099613a29565b905b6001600160601b038916908161354a575b50508697506001600160601b0381979495969716155f146134d057509050843b15610a06576040516308962e4760e21b81526001600160481b03851660048201526024810191909152818160448183895af18015610274576134bb575b50506020905b6024604051809581936304c49bbd60e21b835260048301525afa90811561030857839161347e575b61295992506150d6565b90506020823d6020116134b3575b8161349960209383613954565b810103126103ab576134ad612959926139b8565b90613474565b3d915061348c565b816134c591613954565b610a0257835f613446565b863b15610a0257604051630185e24960e31b81526001600160481b038716600482015260248101929092526001600160601b031660448201525f60648201526084810191909152818160a48183895af1801561027457613535575b505060209061344c565b8161353f91613954565b610a0257835f61352b565b60405163c690956160e01b81526001600160481b0388166004820152602481018590526020816044818c5afa8015613759578b905f90613764575b61358f92506139f5565b883b15610d91575f6135b791604051809381926345b8d37560e01b8352898d60048501613a49565b0381838d5af180156137595761373c575b5088996135d99199969798996139f5565b883b15610b4d5785613600916040518093819263298a690b60e01b83528c60048401613a73565b0381838d5af1908115611dd0578691613727575b5050873b15610b345760405190633ada6a6360e01b825260048201528481602481838c5af1908115610b29578591613712575b50506008546040516331110b9160e01b81526001600160a01b039091169060208180613677338c60048401613aae565b0381855afa908115611dd05786916136f3575b501561369c575b8097969594976133e9565b803b15610b345760405163743e62bb60e11b815290859082908183816136c6338e60048401613aae565b03925af1908115610b295785916136de575b50613691565b816136e891613954565b610a0257835f6136d8565b61370c915060203d602011610a3257610a248183613954565b5f61368a565b8161371c91613954565b610a0257835f613647565b8161373191613954565b610b3457845f613614565b61374c9196979899505f90613954565b5f979695946135d96135c8565b6040513d5f823e3d90fd5b50506020813d602011613799575b8161377f60209383613954565b81010312610d91578a61379461358f926139b8565b613585565b3d9150613772565b9190506133d8565b90506020813d6020116137db575b816137c460209383613954565b81010312610d91576137d5906139b8565b5f6133a2565b3d91506137b7565b90506020813d602011613815575b816137fe60209383613954565b81010312610d915761380f906139b8565b5f61336d565b3d91506137f1565b5050506020813d60201161384d575b8161383960209383613954565b81010312610d91578284613335925161332b565b3d915061382c565b63ef96b69b60e01b5f5260045ffd5b905061388091955060603d606011610301576102ed8183613954565b95919050945f6132db565b34610d91575f366003190112610d9157602060ff5f5460a01c166040519015158152f35b34610d91575f366003190112610d9157600c546040516001600160a01b039091168152602090f35b34610d91575f366003190112610d9157612f886040516138f8604082613954565b60078152665374616b696e6760c81b6020820152604051918291825b602060409281835280519182918282860152018484015e5f828201840152601f01601f1916010190565b600435906001600160481b0382168203610d9157565b90601f8019910116810190811067ffffffffffffffff82111761397657604052565b634e487b7160e01b5f52604160045260245ffd5b67ffffffffffffffff81116139765760051b60200190565b602435906001600160601b0382168203610d9157565b51906001600160601b0382168203610d9157565b90816060910312610d91576139e0816139b8565b9160406139ef602084016139b8565b92015190565b906001600160601b03809116911601906001600160601b038211613a1557565b634e487b7160e01b5f52601160045260245ffd5b906001600160601b03809116911603906001600160601b038211613a1557565b9160409194936001600160601b03916001600160481b036060860197168552602085015216910152565b6001600160481b0390911681526001600160601b03909116602082015260400190565b90816020910312610d9157518015158103610d915790565b6001600160481b0390911681526001600160a01b03909116602082015260400190565b8051821015613ae55760209160051b010190565b634e487b7160e01b5f52603260045260245ffd5b91908201809211613a1557565b90816020910312610d9157516001600160a01b0381168103610d915790565b91908203918211613a1557565b90816020910312610d91575161ffff81168103610d915790565b81810292918115918404141715613a1557565b8115613b69570490565b634e487b7160e01b5f52601260045260245ffd5b600b54604051635cbeecf160e11b81525f94929390929091602090849060049082906001600160a01b03165afa928315613759575f9361487c575b5082821015614841576008546040516331110b9160e01b81526001600160a01b03909116939060208180613bf0868a60048401613aae565b0381885afa908115613759575f91614822575b50156147e75760405163f893880360e01b815260208180613c28868a60048401613aae565b0381885afa908115613759575f916147b5575b505f198201918211613a155781811461476457808411156147275760018101809111613a155783116146e25760405160208101906001600160601b03198460601b16825260148152613c8e603482613954565b519020604051633fec9e3560e11b8152600481018590526001600160481b0387166024820152604481018290529094602090829060649082905afa908115613759575f916146c3575b5061466f57613ce7848685614d23565b600a54604051638458435760e01b8152600481018690526001600160481b03881660248201526001600160a01b0390911691602082604481865afa918215613759575f9261463b575b5060085460405163c939043d60e01b81526001600160481b038a166004820152602481018890525f94916001600160a01b0316602082604481845afa80156137595789925f9161461c575b506145a057505060065460405163275acb7b60e11b81526001600160481b038b1660048201819052929091602090839060249082906001600160a01b03165afa918215613759575f9261456b575b50602060249160405192838092630bdcdc1560e01b82528d60048301525afa908115613759575f91614539575b5080614467575b506001600160601b03612710613e1a61ffff613e23941688613b4c565b04168095613b25565b6007549094906001600160a01b0316803b15610d9157613e5d915f918c8360405180968195829463216972d760e11b845260048401613a73565b03925af1801561375957614452575b506008546001600160a01b0316803b15610d02578a8091606460405180948193636d9f29b360e01b83528760048401528d6024840152600160448401525af18015610bbd57908b9161443d575b50506008546001600160a01b0316803b15610d0257604051632e077a3760e01b81526001600160481b038b16600482015260248101899052908b908290604490829084905af18015610bbd57908b91614428575b50506008546001600160a01b031690813b15610d02578a916064839260405194859384926382b98cc360e01b845260048401528c60248401528960448401525af18015610b9957908a91614413575b50505b8015801561440b575b8015614403575b156143eb5750505085925b6008546001600160a01b031690813b1561241f5760405163329a834360e11b81528160048201528881608481836001600160481b038d16978860248401528c6044840152600160648401525af18015610c57579089916143d6575b505060085460405163f893880360e01b815291906001600160a01b031660208380614004898d60048401613aae565b0381845afa928315610b99578a936143a2575b50803b15610bb95760405163058f15c160e21b81526001600160481b038a1660048201526001600160a01b0387166024820152604481019290925289908290606490829084905af18015610c575790899161438d575b50508415614383576008546040516340cd9d3960e11b8152936001600160a01b039091169190602085806140a5898d60048401613aae565b0381865afa948515610b99578a9561434e575b506001916140c591613b25565b11156141bc5750506008546001600160a01b0316906140e5908490613af9565b91813b15610b5c57604051638c436ca360e01b81526001600160481b03871660048201526001600160a01b03919091166024820152604481019290925285908290606490829084905af18015610b29579085916141a7575b50505b6007546001600160a01b031690813b15610b3457906001600160601b0385809493614183604051978896879586946303341fc160e11b8652169160048501613a49565b03925af1801561027457614195575050565b6141a0828092613954565b6102715750565b816141b191613954565b610a0257835f61413d565b916141ca9085949294613af9565b92823b1561241f579060648892836040519586948593638c436ca360e01b8552600485015260018060a01b031660248401528160448401525af18015611dd057908691614339575b50506007546001600160601b0391909116906001600160a01b0316803b15610b4d57856040518092636ca3585d60e11b8252818381614256888b8d60048501613a49565b03925af18015611dd057908691614324575b50506007546001600160a01b0316803b15610b4d578560405180926397d2904f60e01b825281838161429e888c60048401613a73565b03925af18015611dd05790869161430f575b50506007546001600160a01b031690813b15610b4d578591602483926040519485938492633ada6a6360e01b845260048401525af18015610b29579085916142fa575b5050614140565b8161430491613954565b610a0257835f6142f3565b8161431991613954565b610b3457845f6142b0565b8161432e91613954565b610b3457845f614268565b8161434391613954565b610b3457845f614212565b9094506020813d60201161437b575b8161436a60209383613954565b81010312610d9157519360016140b8565b3d915061435d565b5050505050505050565b8161439791613954565b61241f57875f61406d565b9092506020813d6020116143ce575b816143be60209383613954565b81010312610d915751915f614017565b3d91506143b1565b816143e091613954565b61241f57875f613fd5565b6143fd926143f891613b4c565b613b5f565b92613f7a565b508215613f6f565b508115613f68565b8161441d91613954565b610b8057885f613f5c565b8161443291613954565b610bb957895f613f0d565b8161444791613954565b610bb957895f613eb9565b61445f919a505f90613954565b5f985f613e6c565b9094506044602060018060a01b03600c5416604051928380926305e8e33560e51b8252600160048301528d60248301525afa80156137595785915f916144d8575b50613e1a61ffff6144cd613e23956143f86001600160601b0396876127109716613b4c565b989450505050613dfd565b9150506020813d602011614531575b816144f460209383613954565b81010312610d9157612710613e1a61ffff6144cd613e23956143f88a6001600160601b0361452281996139b8565b975050965050955050506144a8565b3d91506144e7565b90506020813d602011614563575b8161455460209383613954565b81010312610d9157515f613df6565b3d9150614547565b6024919250614591602091823d8411614599575b6145898183613954565b810190613b32565b929150613dc9565b503d61457f565b604051631b6cef6360e31b81526001600160481b038c16600482015260248101929092529294509160209150829060449082905afa908115613759575f916145ea575b5091613f5f565b90506020813d602011614614575b8161460560209383613954565b81010312610d9157515f6145e3565b3d91506145f8565b614635915060203d602011610a3257610a248183613954565b5f613d7b565b9091506020813d602011614667575b8161465760209383613954565b81010312610d915751905f613d30565b3d915061464a565b60405162461bcd60e51b815260206004820152602660248201527f416c726561647920636c61696d6564207265776172647320666f722074686973604482015265040cae0dec6d60d31b6064820152608490fd5b6146dc915060203d602011610a3257610a248183613954565b5f613cd7565b60405162461bcd60e51b815260206004820152601d60248201527f4d75737420636c61696d206f6c6465722065706f6368732066697273740000006044820152606490fd5b60405162461bcd60e51b8152602060048201526015602482015274115c1bd8da08185b1c9958591e4818db185a5b5959605a1b6044820152606490fd5b60405162461bcd60e51b8152602060048201526024808201527f416c726561647920636c61696d656420616c6c2066696e616c697365642065706044820152636f63687360e01b6064820152608490fd5b90506020813d6020116147df575b816147d060209383613954565b81010312610d9157515f613c3b565b3d91506147c3565b60405162461bcd60e51b815260206004820152601360248201527211195b1959d85d1bdc881b9bdd08199bdd5b99606a1b6044820152606490fd5b61483b915060203d602011610a3257610a248183613954565b5f613c03565b60405162461bcd60e51b8152602060048201526013602482015272115c1bd8da081b9bdd08199a5b985b1a5cd959606a1b6044820152606490fd5b9092506020813d6020116148a8575b8161489860209383613954565b81010312610d915751915f613bb8565b3d915061488b565b6001600160481b03602060018060a01b03600654169260246040518094819363c04d7dcf60e01b835216958660048301525afa908115613759575f9161490c575b50156148fa5750565b63054202f760e51b5f5260045260245ffd5b614925915060203d602011610a3257610a248183613954565b5f6148f1565b600460405160208101906001600160601b03198560601b16825260148152614954603482613954565b519020600b54604051635cbeecf160e11b81529260209184919082906001600160a01b03165afa918215613759575f92614cef575b5060085460405163f893880360e01b8152926001600160a01b039091169190602084806149ba898960048401613aae565b0381865afa938415613759575f94614cbb575b505f19810193818511613a1557848114614cb2576001198201918211613a155710614c4757600a54604051630ee1bfcd60e01b8152600481018590526001600160481b0386166024820152604481018390526001600160a01b039091169190602081606481865afa908115613759575f91614c15575b50604051632a95743f60e01b8152600481018690526001600160481b038716602482015291602083604481875afa928315613759575f93614be0575b50604051622b987b60e31b8152600481018790526001600160481b038816602482015260448101919091529192602090839060649082905afa918215613759575f92614bac575b50159182614ba2575b5050614b405760405162461bcd60e51b815260206004820152603b60248201527f4d75737420636c61696d207468652070726576696f75732065706f636820726560448201527f7761726473206265666f7265206368616e67696e67207374616b6500000000006064820152608490fd5b803b15610d915760405163058f15c160e21b81526001600160481b0390931660048401526001600160a01b0390931660248301526044820152905f9082908183816064810103925af1801561375957614b965750565b5f614ba091613954565b565b1490505f80614acf565b9091506020813d602011614bd8575b81614bc860209383613954565b81010312610d915751905f614ac6565b3d9150614bbb565b9092506020813d602011614c0d575b81614bfc60209383613954565b81010312610d915751916020614a7f565b3d9150614bef565b90506020813d602011614c3f575b81614c3060209383613954565b81010312610d9157515f614a43565b3d9150614c23565b60405162461bcd60e51b815260206004820152603b60248201527f4d75737420636c61696d20616c6c2070726576696f75732065706f636820726560448201527f7761726473206265666f7265206368616e67696e67207374616b6500000000006064820152608490fd5b50505050505050565b9093506020813d602011614ce7575b81614cd760209383613954565b81010312610d915751925f6149cd565b3d9150614cca565b9091506020813d602011614d1b575b81614d0b60209383613954565b81010312610d915751905f614989565b3d9150614cfe565b600a54604051632a95743f60e01b8152600481018390526001600160481b03841660248201525f95946001600160a01b0390921692909190602083604481875afa928315613759575f936150a2575b50604051630ee1bfcd60e01b8152600481018290526001600160481b03861660248201526044810183905293602085606481845afa948515613759575f9561506e575b50604051622b987b60e31b8152600481018390526001600160481b038716602482015260448101849052602081606481855afa908115613759575f9161503c575b508085146150315760075460405163c690956160e01b81526001600160481b03891660048201526024810186905290602090829060449082906001600160a01b03165afa8015613759575f90614ff1575b6001600160601b03915016918215614f875750614e7a89949392614e74670de0b6b3a76400009388613b25565b90613b4c565b049586614f0b575b600a546001600160a01b031691823b15610b34578490614ed860405197889687958694635ed45e5360e11b865260048601909493926001600160481b036060936080840197845216602083015260408201520152565b03925af18015610b2957614ef6575b50614ef3929350613af9565b90565b614f01858092613954565b610a025783614ee7565b600a546001600160a01b0316803b15610b345760405163cdddd01f60e01b8152600481018490526001600160481b038316602482015260448101859052606481018990529085908290608490829084905af1908115610b29578591614f72575b5050614e82565b81614f7c91613954565b610a0257835f614f6b565b93949692959798505050813b15610d9157604051635ed45e5360e11b815260048101949094526001600160481b0316602484015260448301919091526064820192909252905f908290608490829084905af1801561375957614fe7575090565b5f614ef391613954565b506020813d602011615029575b8161500b60209383613954565b81010312610d91576150246001600160601b03916139b8565b614e47565b3d9150614ffe565b509396505050505050565b90506020813d602011615066575b8161505760209383613954565b81010312610d9157515f614df6565b3d915061504a565b9094506020813d60201161509a575b8161508a60209383613954565b81010312610d915751935f614db5565b3d915061507d565b9092506020813d6020116150ce575b816150be60209383613954565b81010312610d915751915f614d72565b3d91506150b1565b60025460055460405163175a11e760e21b81526001600160481b0390931660048401819052936001600160a01b0392831693919092169190602081602481875afa908115613759575f916152d0575b5015908161524f575b5061513857505050565b60206004926040519384809263f1a3c5b360e01b82525afa918215613759575f9261520a575b5060206004916040519283809263192663ed60e11b82525afa908115613759576001600160481b039161ffff915f916151eb575b5016911610156151dc576003546001600160a01b031690813b15610d91575f9160248392604051948593849263090444a160e41b845260048401525af1801561375957614b965750565b6310aff3b760e31b5f5260045ffd5b615204915060203d602011614599576145898183613954565b5f615192565b9091506020813d602011615247575b8161522660209383613954565b81010312610d9157516001600160481b0381168103610d915790602061515e565b3d9150615219565b60405163762ffd6160e11b8152909150602081600481865afa908115613759575f9161528c575b506001600160601b03809116911610155f61512e565b90506020813d6020116152c8575b816152a760209383613954565b81010312610d91576001600160601b036152c181926139b8565b9150615276565b3d915061529a565b6152e9915060203d602011610a3257610a248183613954565b5f615125565b60206001600160481b03606460018060a01b036004541693604051848101903360601b825260148152615323603482613954565b519020946040519586948593631af27dbd60e11b85521660048401526024830152600160448301525afa908115613759575f91615376575b501561536357565b63024ac36b60e21b5f523360045260245ffd5b61538f915060203d602011610a3257610a248183613954565b5f61535b565b60018060a01b035f54168033141590816153e2575b506153b157565b60405163f0b1bddb60e01b815260206004820152600860248201526727b7363c90243ab160c11b6044820152606490fd5b604051638da5cb5b60e01b81529150602090829060049082905afa908115613759575f9161541e575b506001600160a01b03163314155f6153aa565b615437915060203d6020116115195761150b8183613954565b5f61540b565b60025460405163175a11e760e21b81526001600160481b03909216600483018190529290602090839060249082906001600160a01b03165afa918215613759575f92615562575b50816154d3575b506154935750565b6003546001600160a01b031690813b15610d91575f916024839260405194859384926357ce0f6360e11b845260048401525af1801561375957614b965750565b60055460405163762ffd6160e11b8152919250602090829060049082906001600160a01b03165afa908115613759575f9161551e575b506001600160601b038091169116105f61548b565b90506020813d60201161555a575b8161553960209383613954565b81010312610d91576001600160601b0361555381926139b8565b9150615509565b3d915061552c565b61557c91925060203d602011610a3257610a248183613954565b905f61548456fea264697066735822122032affa1a855a001ebf795eba95bdca806c2a5b87290d1595764ac3244ce12d7e64736f6c634300081a0033", + "dc868039c523a30bce129ca33c955ef0320f696b13c4edcfac6b5c655cc562c1": "0xf869a0204b24eae4a02d3987ca887631704554f37941d36d88eba3861c6e365c7804a5b846f8440180a0465ac2797ac8828138ad632344c4e349f027f0dc13f2f224451a1f2539b53217a0129aadc37672a5f1d1e205a93d572bf711feca4f8e533762115053a4528db30a", + "715776c523b9dfb920257c942c90f6dd6243df3f3c38c79db9023d0b587581fe": "0xf851808080808080a057ec08b8f040499409fb0220f538477790d4f010c4bb51a8dbae5da3537a86a480a0dc868039c523a30bce129ca33c955ef0320f696b13c4edcfac6b5c655cc562c18080808080808080", + "7b2fcbc84ae21c15bd950082bea4e7d20e73a30355e5929bd83d34f857a1ff4e": "0xf90131a06e94ede82e8c381d422f010130a4c2ed35805be58e6783d800fbb37d000090e2a00968480c83b67f0eb2cafc1df82dbf6dcac0811f36fbd405f20c46f158da5315808080a05492888cc7c534f4fd1f9f803a9c0c9b14a3aa268d7aa1a226c0b5a2df295078808080a0aff16a3ca0d6e3544a2d4deb40842cebaf9325e6a98f2d6edc4cdce5d853e5d8a0bff66d9133cff6e91fe1878473b09aee9458c323efa078340d914a82de546baba09d1b5f3c8944300dda9eec33376308282aa06c11d3fdc640669ce5e506edb797a069a571829b9b6f89efb0b65e66e59e5a26b2eb72cdfce949e0aec5e0037357bda0853082590f798e998c021e6cf314a77c9a9fa6321048ad84cd12210b7aca706a80a0715776c523b9dfb920257c942c90f6dd6243df3f3c38c79db9023d0b587581fe80", + "38eff982fb71f349966cfcd9e9ba8d67ede4adc14838facce557d327f7ff275d": "0xf872a03931b4ed56ace4c46b68524cb5bcbf4195f1bbaacbe5228fbd090546c88dd229b84ff84d0189056bc75e2d627cc432a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "a90c7f122718293fad4f73a65d951031d8f780da3a953247b7cc532528540de4": "0xf90131a06e94ede82e8c381d422f010130a4c2ed35805be58e6783d800fbb37d000090e2a00968480c83b67f0eb2cafc1df82dbf6dcac0811f36fbd405f20c46f158da5315808080a038eff982fb71f349966cfcd9e9ba8d67ede4adc14838facce557d327f7ff275d808080a0aff16a3ca0d6e3544a2d4deb40842cebaf9325e6a98f2d6edc4cdce5d853e5d8a0bff66d9133cff6e91fe1878473b09aee9458c323efa078340d914a82de546baba09d1b5f3c8944300dda9eec33376308282aa06c11d3fdc640669ce5e506edb797a069a571829b9b6f89efb0b65e66e59e5a26b2eb72cdfce949e0aec5e0037357bda0853082590f798e998c021e6cf314a77c9a9fa6321048ad84cd12210b7aca706a80a0715776c523b9dfb920257c942c90f6dd6243df3f3c38c79db9023d0b587581fe80", + "d18501ed1922bd1738209ea58431c2d9097cc909b3fe8f634bfbe765402574f9": "0xf86ca020a40a9004224e397238839b469142c546607ee7a8b114ded86182fceae00e35b849f8478083499de7a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "e264b5e39e42d803daf083612a51719d5680cf5e1914c50e514277b1627eba34": "0xf87180a0cdeaf028a7a2894d4778d6c412bfb95e81b23c2e6044f4c5d6de2ed8a50f78f3808080808080808080a082f6e0ef9d3ec62e68c811432d52e6e0c907d604aed5a2a561d95e393f487d688080a0d18501ed1922bd1738209ea58431c2d9097cc909b3fe8f634bfbe765402574f98080", + "29855e855ed63e162cbc39881279a43d9978877d89a69a2a6bac0a8db9cd5f66": "0xf90131a06e94ede82e8c381d422f010130a4c2ed35805be58e6783d800fbb37d000090e2a00968480c83b67f0eb2cafc1df82dbf6dcac0811f36fbd405f20c46f158da5315808080a038eff982fb71f349966cfcd9e9ba8d67ede4adc14838facce557d327f7ff275d808080a0aff16a3ca0d6e3544a2d4deb40842cebaf9325e6a98f2d6edc4cdce5d853e5d8a0bff66d9133cff6e91fe1878473b09aee9458c323efa078340d914a82de546baba0e264b5e39e42d803daf083612a51719d5680cf5e1914c50e514277b1627eba34a069a571829b9b6f89efb0b65e66e59e5a26b2eb72cdfce949e0aec5e0037357bda0853082590f798e998c021e6cf314a77c9a9fa6321048ad84cd12210b7aca706a80a0715776c523b9dfb920257c942c90f6dd6243df3f3c38c79db9023d0b587581fe80", + "46f7a284fe0e90ae8a7c0b33560aedbd71ff2363e18d5634eda5f5a3b379a33b": "0xf872a03931b4ed56ace4c46b68524cb5bcbf4195f1bbaacbe5228fbd090546c88dd229b84ff84d8089056bc75e2d6266ae6ca056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "60bb01aa1843a8e4f56e2afe0aeae94b57bbb36a9c7bd4fcaa6e0dcff08d06a1": "0xf90131a06e94ede82e8c381d422f010130a4c2ed35805be58e6783d800fbb37d000090e2a00968480c83b67f0eb2cafc1df82dbf6dcac0811f36fbd405f20c46f158da5315808080a046f7a284fe0e90ae8a7c0b33560aedbd71ff2363e18d5634eda5f5a3b379a33b808080a0aff16a3ca0d6e3544a2d4deb40842cebaf9325e6a98f2d6edc4cdce5d853e5d8a0bff66d9133cff6e91fe1878473b09aee9458c323efa078340d914a82de546baba09d1b5f3c8944300dda9eec33376308282aa06c11d3fdc640669ce5e506edb797a069a571829b9b6f89efb0b65e66e59e5a26b2eb72cdfce949e0aec5e0037357bda0853082590f798e998c021e6cf314a77c9a9fa6321048ad84cd12210b7aca706a80a05f1ef1b2e89b5ed4e71249e76600493c718bc6c6030189bfab281c7b85389a2c80", + "aca65528ac4c2bcb286a222756ff16c2b68a91d151e699e4826826c54dab019e": "0xf872a03931b4ed56ace4c46b68524cb5bcbf4195f1bbaacbe5228fbd090546c88dd229b84ff84d0189056bc75e2d6266ae6ca056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "c4d9af7901d6c29e2671d8287cc136d7ce14daa8e8fc03eb46798809521200de": "0xf90131a06e94ede82e8c381d422f010130a4c2ed35805be58e6783d800fbb37d000090e2a00968480c83b67f0eb2cafc1df82dbf6dcac0811f36fbd405f20c46f158da5315808080a0aca65528ac4c2bcb286a222756ff16c2b68a91d151e699e4826826c54dab019e808080a0aff16a3ca0d6e3544a2d4deb40842cebaf9325e6a98f2d6edc4cdce5d853e5d8a0bff66d9133cff6e91fe1878473b09aee9458c323efa078340d914a82de546baba09d1b5f3c8944300dda9eec33376308282aa06c11d3fdc640669ce5e506edb797a069a571829b9b6f89efb0b65e66e59e5a26b2eb72cdfce949e0aec5e0037357bda0853082590f798e998c021e6cf314a77c9a9fa6321048ad84cd12210b7aca706a80a05f1ef1b2e89b5ed4e71249e76600493c718bc6c6030189bfab281c7b85389a2c80", + "7912f3028eba82c206a042c58cdbbecde8b050d179799141fce696b7093b1cf0": "0xf90131a06e94ede82e8c381d422f010130a4c2ed35805be58e6783d800fbb37d000090e2a00968480c83b67f0eb2cafc1df82dbf6dcac0811f36fbd405f20c46f158da5315808080a0aca65528ac4c2bcb286a222756ff16c2b68a91d151e699e4826826c54dab019e808080a0aff16a3ca0d6e3544a2d4deb40842cebaf9325e6a98f2d6edc4cdce5d853e5d8a0bff66d9133cff6e91fe1878473b09aee9458c323efa078340d914a82de546baba09d1b5f3c8944300dda9eec33376308282aa06c11d3fdc640669ce5e506edb797a069a571829b9b6f89efb0b65e66e59e5a26b2eb72cdfce949e0aec5e0037357bda0853082590f798e998c021e6cf314a77c9a9fa6321048ad84cd12210b7aca706a80a08ebfa1bb8d7f17c4c7b061298856df0d764d78874df9bbee0e2607b97a282e6f80", + "d7952a2d31854588b78136120f9ccc60bc639dd671e2f982831136791d8c439d": "0xf90131a06e94ede82e8c381d422f010130a4c2ed35805be58e6783d800fbb37d000090e2a00968480c83b67f0eb2cafc1df82dbf6dcac0811f36fbd405f20c46f158da5315808080a0aca65528ac4c2bcb286a222756ff16c2b68a91d151e699e4826826c54dab019e808080a0aff16a3ca0d6e3544a2d4deb40842cebaf9325e6a98f2d6edc4cdce5d853e5d8a0bff66d9133cff6e91fe1878473b09aee9458c323efa078340d914a82de546baba09d1b5f3c8944300dda9eec33376308282aa06c11d3fdc640669ce5e506edb797a069a571829b9b6f89efb0b65e66e59e5a26b2eb72cdfce949e0aec5e0037357bda0853082590f798e998c021e6cf314a77c9a9fa6321048ad84cd12210b7aca706a80a078411d2196a2e4c560372788d3e499d0b71f36204f1961a41ef216a7fd574e9580", + "b3c053e194e44bacc25667eeff5b5409ca38f02328ba580a500eaebb9f66fdc8": "0xf90131a06e94ede82e8c381d422f010130a4c2ed35805be58e6783d800fbb37d000090e2a00968480c83b67f0eb2cafc1df82dbf6dcac0811f36fbd405f20c46f158da5315808080a0aca65528ac4c2bcb286a222756ff16c2b68a91d151e699e4826826c54dab019e808080a0aff16a3ca0d6e3544a2d4deb40842cebaf9325e6a98f2d6edc4cdce5d853e5d8a0bff66d9133cff6e91fe1878473b09aee9458c323efa078340d914a82de546baba09d1b5f3c8944300dda9eec33376308282aa06c11d3fdc640669ce5e506edb797a069a571829b9b6f89efb0b65e66e59e5a26b2eb72cdfce949e0aec5e0037357bda0853082590f798e998c021e6cf314a77c9a9fa6321048ad84cd12210b7aca706a80a0784e5369c0f78373b69df73b8f6b82440ed0629de04c3de77bf53693a175c19c80", + "da440b9b364246fb445bcf6c1772d1257972a37df7ef06f37339131bdcb6e6fc": "0xf90131a06e94ede82e8c381d422f010130a4c2ed35805be58e6783d800fbb37d000090e2a00968480c83b67f0eb2cafc1df82dbf6dcac0811f36fbd405f20c46f158da5315808080a0aca65528ac4c2bcb286a222756ff16c2b68a91d151e699e4826826c54dab019e808080a0aff16a3ca0d6e3544a2d4deb40842cebaf9325e6a98f2d6edc4cdce5d853e5d8a0bff66d9133cff6e91fe1878473b09aee9458c323efa078340d914a82de546baba09d1b5f3c8944300dda9eec33376308282aa06c11d3fdc640669ce5e506edb797a069a571829b9b6f89efb0b65e66e59e5a26b2eb72cdfce949e0aec5e0037357bda0853082590f798e998c021e6cf314a77c9a9fa6321048ad84cd12210b7aca706a80a0715776c523b9dfb920257c942c90f6dd6243df3f3c38c79db9023d0b587581fe80", + "df2c3b703f91e444f166d9a90068fb8894c5b2189635ebd3eb298a86792de61e": "0xf872a03931b4ed56ace4c46b68524cb5bcbf4195f1bbaacbe5228fbd090546c88dd229b84ff84d0189056bc75e2d56910232a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "c58b98007c09d36f1cc9225a3bfb73b71c7b2cc4ff49b38a9cebf6fc21fb14fa": "0xf90131a06e94ede82e8c381d422f010130a4c2ed35805be58e6783d800fbb37d000090e2a00968480c83b67f0eb2cafc1df82dbf6dcac0811f36fbd405f20c46f158da5315808080a0df2c3b703f91e444f166d9a90068fb8894c5b2189635ebd3eb298a86792de61e808080a0aff16a3ca0d6e3544a2d4deb40842cebaf9325e6a98f2d6edc4cdce5d853e5d8a0bff66d9133cff6e91fe1878473b09aee9458c323efa078340d914a82de546baba0e264b5e39e42d803daf083612a51719d5680cf5e1914c50e514277b1627eba34a069a571829b9b6f89efb0b65e66e59e5a26b2eb72cdfce949e0aec5e0037357bda0853082590f798e998c021e6cf314a77c9a9fa6321048ad84cd12210b7aca706a80a0715776c523b9dfb920257c942c90f6dd6243df3f3c38c79db9023d0b587581fe80", + "ae89d3dbac04cc9b94c2f3676cc74460749b816a66348621957d1e9c842edc7b": "0xf872a03931b4ed56ace4c46b68524cb5bcbf4195f1bbaacbe5228fbd090546c88dd229b84ff84d0289056bc75e2d56910232a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "6a972d522960b74d29a77955177d33bc2f45767e7df812ff19385662b731241b": "0xf90131a06e94ede82e8c381d422f010130a4c2ed35805be58e6783d800fbb37d000090e2a00968480c83b67f0eb2cafc1df82dbf6dcac0811f36fbd405f20c46f158da5315808080a0ae89d3dbac04cc9b94c2f3676cc74460749b816a66348621957d1e9c842edc7b808080a0aff16a3ca0d6e3544a2d4deb40842cebaf9325e6a98f2d6edc4cdce5d853e5d8a0bff66d9133cff6e91fe1878473b09aee9458c323efa078340d914a82de546baba0e264b5e39e42d803daf083612a51719d5680cf5e1914c50e514277b1627eba34a069a571829b9b6f89efb0b65e66e59e5a26b2eb72cdfce949e0aec5e0037357bda0853082590f798e998c021e6cf314a77c9a9fa6321048ad84cd12210b7aca706a80a0715776c523b9dfb920257c942c90f6dd6243df3f3c38c79db9023d0b587581fe80", + "92dec9b3beeaaba9a04347df05e2c77cb15ef3e784e28fbc09baa2f5520037a7": "0xf872a03931b4ed56ace4c46b68524cb5bcbf4195f1bbaacbe5228fbd090546c88dd229b84ff84d0289056bc75e2d627bf3c6a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "7b6b910858e86872e6838deb9711ecefeea74965e869c981e3d9e24acd9f1780": "0xf90131a06e94ede82e8c381d422f010130a4c2ed35805be58e6783d800fbb37d000090e2a00968480c83b67f0eb2cafc1df82dbf6dcac0811f36fbd405f20c46f158da5315808080a092dec9b3beeaaba9a04347df05e2c77cb15ef3e784e28fbc09baa2f5520037a7808080a0aff16a3ca0d6e3544a2d4deb40842cebaf9325e6a98f2d6edc4cdce5d853e5d8a0bff66d9133cff6e91fe1878473b09aee9458c323efa078340d914a82de546baba0e264b5e39e42d803daf083612a51719d5680cf5e1914c50e514277b1627eba34a069a571829b9b6f89efb0b65e66e59e5a26b2eb72cdfce949e0aec5e0037357bda0853082590f798e998c021e6cf314a77c9a9fa6321048ad84cd12210b7aca706a80a0715776c523b9dfb920257c942c90f6dd6243df3f3c38c79db9023d0b587581fe80", + "0ab1bd40c3bd2aa3649b4ade3e0cf3e30af02bcc9241f34f3d89befaa3496741": "0xf86ba03af97556eedd035d0c1b80182155e5f5148b950fe7547a1253e2e74d703b365eb848f84680826836a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "300233b3ac87231aa036f96f3deffc4df9230b74ae7065833f966e0ef7e70aa4": "0xf90151a06e94ede82e8c381d422f010130a4c2ed35805be58e6783d800fbb37d000090e2a00968480c83b67f0eb2cafc1df82dbf6dcac0811f36fbd405f20c46f158da5315808080a092dec9b3beeaaba9a04347df05e2c77cb15ef3e784e28fbc09baa2f5520037a780a00ab1bd40c3bd2aa3649b4ade3e0cf3e30af02bcc9241f34f3d89befaa349674180a0aff16a3ca0d6e3544a2d4deb40842cebaf9325e6a98f2d6edc4cdce5d853e5d8a0bff66d9133cff6e91fe1878473b09aee9458c323efa078340d914a82de546baba0e264b5e39e42d803daf083612a51719d5680cf5e1914c50e514277b1627eba34a069a571829b9b6f89efb0b65e66e59e5a26b2eb72cdfce949e0aec5e0037357bda0853082590f798e998c021e6cf314a77c9a9fa6321048ad84cd12210b7aca706a80a0715776c523b9dfb920257c942c90f6dd6243df3f3c38c79db9023d0b587581fe80", + "b45db2ac1a53a447608cdab23c62fe9b42b0557652dfe0d235f2e1cbcd9d3eb6": "0xf872a03931b4ed56ace4c46b68524cb5bcbf4195f1bbaacbe5228fbd090546c88dd229b84ff84d0189056bc75e2d622136b2a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "adc75175125e86fa85add840e873e1ca2a53d90ed2c796ee800c66ade6facd7f": "0xf90131a06e94ede82e8c381d422f010130a4c2ed35805be58e6783d800fbb37d000090e2a00968480c83b67f0eb2cafc1df82dbf6dcac0811f36fbd405f20c46f158da5315808080a0b45db2ac1a53a447608cdab23c62fe9b42b0557652dfe0d235f2e1cbcd9d3eb6808080a0aff16a3ca0d6e3544a2d4deb40842cebaf9325e6a98f2d6edc4cdce5d853e5d8a0bff66d9133cff6e91fe1878473b09aee9458c323efa078340d914a82de546baba0e264b5e39e42d803daf083612a51719d5680cf5e1914c50e514277b1627eba34a069a571829b9b6f89efb0b65e66e59e5a26b2eb72cdfce949e0aec5e0037357bda0853082590f798e998c021e6cf314a77c9a9fa6321048ad84cd12210b7aca706a80a0715776c523b9dfb920257c942c90f6dd6243df3f3c38c79db9023d0b587581fe80", + "4b8934c03fc577086aa936d15e1219626704f5f221c68fc18bc1d883f1f797e4": "0xf872a03931b4ed56ace4c46b68524cb5bcbf4195f1bbaacbe5228fbd090546c88dd229b84ff84d0289056bc75e2d622136b2a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "8bdb8c8ab449981c4461d0b27bce8b142eb43f8c988bfee5432db371c11c6ce1": "0xf90131a06e94ede82e8c381d422f010130a4c2ed35805be58e6783d800fbb37d000090e2a00968480c83b67f0eb2cafc1df82dbf6dcac0811f36fbd405f20c46f158da5315808080a04b8934c03fc577086aa936d15e1219626704f5f221c68fc18bc1d883f1f797e4808080a0aff16a3ca0d6e3544a2d4deb40842cebaf9325e6a98f2d6edc4cdce5d853e5d8a0bff66d9133cff6e91fe1878473b09aee9458c323efa078340d914a82de546baba0e264b5e39e42d803daf083612a51719d5680cf5e1914c50e514277b1627eba34a069a571829b9b6f89efb0b65e66e59e5a26b2eb72cdfce949e0aec5e0037357bda0853082590f798e998c021e6cf314a77c9a9fa6321048ad84cd12210b7aca706a80a0715776c523b9dfb920257c942c90f6dd6243df3f3c38c79db9023d0b587581fe80", + "ab91dd3275c5eab7fae01e865627f9a0830d9ee07ca4ff77a843e191fd383d5c": "0xf872a03931b4ed56ace4c46b68524cb5bcbf4195f1bbaacbe5228fbd090546c88dd229b84ff84d0289056bc75e2d569031c6a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "32682f7c615cf9fcd09ae75a875b8fbde6399328d9bdd600242e8d09d49e8f85": "0xf90151a06e94ede82e8c381d422f010130a4c2ed35805be58e6783d800fbb37d000090e2a00968480c83b67f0eb2cafc1df82dbf6dcac0811f36fbd405f20c46f158da5315808080a0ab91dd3275c5eab7fae01e865627f9a0830d9ee07ca4ff77a843e191fd383d5c80a00ab1bd40c3bd2aa3649b4ade3e0cf3e30af02bcc9241f34f3d89befaa349674180a0aff16a3ca0d6e3544a2d4deb40842cebaf9325e6a98f2d6edc4cdce5d853e5d8a0bff66d9133cff6e91fe1878473b09aee9458c323efa078340d914a82de546baba0e264b5e39e42d803daf083612a51719d5680cf5e1914c50e514277b1627eba34a069a571829b9b6f89efb0b65e66e59e5a26b2eb72cdfce949e0aec5e0037357bda0853082590f798e998c021e6cf314a77c9a9fa6321048ad84cd12210b7aca706a80a0715776c523b9dfb920257c942c90f6dd6243df3f3c38c79db9023d0b587581fe80", + "4b12e162dc61d92893448d57cd2a7780bac0e0aea0761d94618586e8bd82e7ab": "0xf872a03931b4ed56ace4c46b68524cb5bcbf4195f1bbaacbe5228fbd090546c88dd229b84ff84d0389056bc75e2d569031c6a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "678efcd13487711ef647b9a453912e5f9646bde79f6014c1c8c01cde3c54ed31": "0xf90151a06e94ede82e8c381d422f010130a4c2ed35805be58e6783d800fbb37d000090e2a00968480c83b67f0eb2cafc1df82dbf6dcac0811f36fbd405f20c46f158da5315808080a04b12e162dc61d92893448d57cd2a7780bac0e0aea0761d94618586e8bd82e7ab80a00ab1bd40c3bd2aa3649b4ade3e0cf3e30af02bcc9241f34f3d89befaa349674180a0aff16a3ca0d6e3544a2d4deb40842cebaf9325e6a98f2d6edc4cdce5d853e5d8a0bff66d9133cff6e91fe1878473b09aee9458c323efa078340d914a82de546baba0e264b5e39e42d803daf083612a51719d5680cf5e1914c50e514277b1627eba34a069a571829b9b6f89efb0b65e66e59e5a26b2eb72cdfce949e0aec5e0037357bda0853082590f798e998c021e6cf314a77c9a9fa6321048ad84cd12210b7aca706a80a0715776c523b9dfb920257c942c90f6dd6243df3f3c38c79db9023d0b587581fe80", + "7bef1a9e39dc8d479b5c9ebaddcf641827de12f2957766b23c8661e4dde7315c": "0xf872a03931b4ed56ace4c46b68524cb5bcbf4195f1bbaacbe5228fbd090546c88dd229b84ff84d0389056bc75e2d627b235aa056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "1d15282838edb756a2dcbf57df91b379fdd223ffa8d9078580e7c3e3da9c66fa": "0xf90151a06e94ede82e8c381d422f010130a4c2ed35805be58e6783d800fbb37d000090e2a00968480c83b67f0eb2cafc1df82dbf6dcac0811f36fbd405f20c46f158da5315808080a07bef1a9e39dc8d479b5c9ebaddcf641827de12f2957766b23c8661e4dde7315c80a00ab1bd40c3bd2aa3649b4ade3e0cf3e30af02bcc9241f34f3d89befaa349674180a0aff16a3ca0d6e3544a2d4deb40842cebaf9325e6a98f2d6edc4cdce5d853e5d8a0bff66d9133cff6e91fe1878473b09aee9458c323efa078340d914a82de546baba0e264b5e39e42d803daf083612a51719d5680cf5e1914c50e514277b1627eba34a069a571829b9b6f89efb0b65e66e59e5a26b2eb72cdfce949e0aec5e0037357bda0853082590f798e998c021e6cf314a77c9a9fa6321048ad84cd12210b7aca706a80a0715776c523b9dfb920257c942c90f6dd6243df3f3c38c79db9023d0b587581fe80", + "74b7bd6ce95c16b26c13fc914bc8b885234f8c94a621e0e3942cce38b021526c": "0xf86ba03c76d49790cfa3f0c5e6fc28e31afd97efcab3ccef5b50ddc3276fdd9f50c730b848f84680826836a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "69a59897e251b144ccd5b93bf3ee7193dc4e3ba6ceec8376536127d3e01c2216": "0xf90171a06e94ede82e8c381d422f010130a4c2ed35805be58e6783d800fbb37d000090e2a00968480c83b67f0eb2cafc1df82dbf6dcac0811f36fbd405f20c46f158da5315808080a07bef1a9e39dc8d479b5c9ebaddcf641827de12f2957766b23c8661e4dde7315ca074b7bd6ce95c16b26c13fc914bc8b885234f8c94a621e0e3942cce38b021526ca00ab1bd40c3bd2aa3649b4ade3e0cf3e30af02bcc9241f34f3d89befaa349674180a0aff16a3ca0d6e3544a2d4deb40842cebaf9325e6a98f2d6edc4cdce5d853e5d8a0bff66d9133cff6e91fe1878473b09aee9458c323efa078340d914a82de546baba0e264b5e39e42d803daf083612a51719d5680cf5e1914c50e514277b1627eba34a069a571829b9b6f89efb0b65e66e59e5a26b2eb72cdfce949e0aec5e0037357bda0853082590f798e998c021e6cf314a77c9a9fa6321048ad84cd12210b7aca706a80a0715776c523b9dfb920257c942c90f6dd6243df3f3c38c79db9023d0b587581fe80", + "64ac290a355bc5b7454a3c4f8fe76ec652e8fa388b4748988c7e6e7dad323408": "0xf872a03931b4ed56ace4c46b68524cb5bcbf4195f1bbaacbe5228fbd090546c88dd229b84ff84d0289056bc75e2d62206646a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "014a8f7e35781b2e9bc808634e90ca385d7dae74cb6d927820d4a029237f23da": "0xf90151a06e94ede82e8c381d422f010130a4c2ed35805be58e6783d800fbb37d000090e2a00968480c83b67f0eb2cafc1df82dbf6dcac0811f36fbd405f20c46f158da5315808080a064ac290a355bc5b7454a3c4f8fe76ec652e8fa388b4748988c7e6e7dad32340880a00ab1bd40c3bd2aa3649b4ade3e0cf3e30af02bcc9241f34f3d89befaa349674180a0aff16a3ca0d6e3544a2d4deb40842cebaf9325e6a98f2d6edc4cdce5d853e5d8a0bff66d9133cff6e91fe1878473b09aee9458c323efa078340d914a82de546baba0e264b5e39e42d803daf083612a51719d5680cf5e1914c50e514277b1627eba34a069a571829b9b6f89efb0b65e66e59e5a26b2eb72cdfce949e0aec5e0037357bda0853082590f798e998c021e6cf314a77c9a9fa6321048ad84cd12210b7aca706a80a0715776c523b9dfb920257c942c90f6dd6243df3f3c38c79db9023d0b587581fe80", + "6820e0a161f137b3d76c540e78379618b6a0be31e108544a04ff203d772396c0": "0xf872a03931b4ed56ace4c46b68524cb5bcbf4195f1bbaacbe5228fbd090546c88dd229b84ff84d0389056bc75e2d62206646a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "99d552bb8a020ea16dc7d8b2d650b6ed037526c6a8cfb311fc235e470f4062d0": "0xf90151a06e94ede82e8c381d422f010130a4c2ed35805be58e6783d800fbb37d000090e2a00968480c83b67f0eb2cafc1df82dbf6dcac0811f36fbd405f20c46f158da5315808080a06820e0a161f137b3d76c540e78379618b6a0be31e108544a04ff203d772396c080a00ab1bd40c3bd2aa3649b4ade3e0cf3e30af02bcc9241f34f3d89befaa349674180a0aff16a3ca0d6e3544a2d4deb40842cebaf9325e6a98f2d6edc4cdce5d853e5d8a0bff66d9133cff6e91fe1878473b09aee9458c323efa078340d914a82de546baba0e264b5e39e42d803daf083612a51719d5680cf5e1914c50e514277b1627eba34a069a571829b9b6f89efb0b65e66e59e5a26b2eb72cdfce949e0aec5e0037357bda0853082590f798e998c021e6cf314a77c9a9fa6321048ad84cd12210b7aca706a80a0715776c523b9dfb920257c942c90f6dd6243df3f3c38c79db9023d0b587581fe80", + "9e4e83b5dec7e446f7820b94d75a1d71fdbe521035cca8c602cbd5ad6ee85c5c": "0xf872a03931b4ed56ace4c46b68524cb5bcbf4195f1bbaacbe5228fbd090546c88dd229b84ff84d0389056bc75e2d568f615aa056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "cf7b3dd357ee067e8e112d4877700e003ba185156539a42e0f40df8b90a12574": "0xf90171a06e94ede82e8c381d422f010130a4c2ed35805be58e6783d800fbb37d000090e2a00968480c83b67f0eb2cafc1df82dbf6dcac0811f36fbd405f20c46f158da5315808080a09e4e83b5dec7e446f7820b94d75a1d71fdbe521035cca8c602cbd5ad6ee85c5ca074b7bd6ce95c16b26c13fc914bc8b885234f8c94a621e0e3942cce38b021526ca00ab1bd40c3bd2aa3649b4ade3e0cf3e30af02bcc9241f34f3d89befaa349674180a0aff16a3ca0d6e3544a2d4deb40842cebaf9325e6a98f2d6edc4cdce5d853e5d8a0bff66d9133cff6e91fe1878473b09aee9458c323efa078340d914a82de546baba0e264b5e39e42d803daf083612a51719d5680cf5e1914c50e514277b1627eba34a069a571829b9b6f89efb0b65e66e59e5a26b2eb72cdfce949e0aec5e0037357bda0853082590f798e998c021e6cf314a77c9a9fa6321048ad84cd12210b7aca706a80a0715776c523b9dfb920257c942c90f6dd6243df3f3c38c79db9023d0b587581fe80", + "b84ad35c0da25851a7b07a2ef64191f7e99d4bd0d5835d3b53efc3ea01d71759": "0xf872a03931b4ed56ace4c46b68524cb5bcbf4195f1bbaacbe5228fbd090546c88dd229b84ff84d0489056bc75e2d568f615aa056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "da509856ef5224b1fe95baad8ec29f72ce0d14c960bf40adfb47ad8e9f2152d6": "0xf90171a06e94ede82e8c381d422f010130a4c2ed35805be58e6783d800fbb37d000090e2a00968480c83b67f0eb2cafc1df82dbf6dcac0811f36fbd405f20c46f158da5315808080a0b84ad35c0da25851a7b07a2ef64191f7e99d4bd0d5835d3b53efc3ea01d71759a074b7bd6ce95c16b26c13fc914bc8b885234f8c94a621e0e3942cce38b021526ca00ab1bd40c3bd2aa3649b4ade3e0cf3e30af02bcc9241f34f3d89befaa349674180a0aff16a3ca0d6e3544a2d4deb40842cebaf9325e6a98f2d6edc4cdce5d853e5d8a0bff66d9133cff6e91fe1878473b09aee9458c323efa078340d914a82de546baba0e264b5e39e42d803daf083612a51719d5680cf5e1914c50e514277b1627eba34a069a571829b9b6f89efb0b65e66e59e5a26b2eb72cdfce949e0aec5e0037357bda0853082590f798e998c021e6cf314a77c9a9fa6321048ad84cd12210b7aca706a80a0715776c523b9dfb920257c942c90f6dd6243df3f3c38c79db9023d0b587581fe80", + "106b2b1deaa6cf733e066c7150ca51729a6188157f868663e5c76fe52cb7b894": "0xf872a03931b4ed56ace4c46b68524cb5bcbf4195f1bbaacbe5228fbd090546c88dd229b84ff84d0489056bc75e2d627a52eea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "cd774994d71bab207f2921ea640fa2f9dc577c4a97a5165fd6f16a947d12a2b9": "0xf90171a06e94ede82e8c381d422f010130a4c2ed35805be58e6783d800fbb37d000090e2a00968480c83b67f0eb2cafc1df82dbf6dcac0811f36fbd405f20c46f158da5315808080a0106b2b1deaa6cf733e066c7150ca51729a6188157f868663e5c76fe52cb7b894a074b7bd6ce95c16b26c13fc914bc8b885234f8c94a621e0e3942cce38b021526ca00ab1bd40c3bd2aa3649b4ade3e0cf3e30af02bcc9241f34f3d89befaa349674180a0aff16a3ca0d6e3544a2d4deb40842cebaf9325e6a98f2d6edc4cdce5d853e5d8a0bff66d9133cff6e91fe1878473b09aee9458c323efa078340d914a82de546baba0e264b5e39e42d803daf083612a51719d5680cf5e1914c50e514277b1627eba34a069a571829b9b6f89efb0b65e66e59e5a26b2eb72cdfce949e0aec5e0037357bda0853082590f798e998c021e6cf314a77c9a9fa6321048ad84cd12210b7aca706a80a0715776c523b9dfb920257c942c90f6dd6243df3f3c38c79db9023d0b587581fe80", + "63be4496bc01abd7bfbb76842ea140f9038b151a0628a3f425ffd3004fa59b1c": "0xf86ca020a40a9004224e397238839b469142c546607ee7a8b114ded86182fceae00e35b849f84780834a061da056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "0f411887f21d0abfcb573be96434685d25f2f7af8a783a911f42439945860a8f": "0xf87180a0cdeaf028a7a2894d4778d6c412bfb95e81b23c2e6044f4c5d6de2ed8a50f78f3808080808080808080a082f6e0ef9d3ec62e68c811432d52e6e0c907d604aed5a2a561d95e393f487d688080a063be4496bc01abd7bfbb76842ea140f9038b151a0628a3f425ffd3004fa59b1c8080", + "388b1ee9613a71d8c39a450aff71e7fb9da72089e93ef5c8a28a40df8627abd5": "0xf90171a06e94ede82e8c381d422f010130a4c2ed35805be58e6783d800fbb37d000090e2a00968480c83b67f0eb2cafc1df82dbf6dcac0811f36fbd405f20c46f158da5315808080a0106b2b1deaa6cf733e066c7150ca51729a6188157f868663e5c76fe52cb7b894a074b7bd6ce95c16b26c13fc914bc8b885234f8c94a621e0e3942cce38b021526ca00ab1bd40c3bd2aa3649b4ade3e0cf3e30af02bcc9241f34f3d89befaa349674180a0aff16a3ca0d6e3544a2d4deb40842cebaf9325e6a98f2d6edc4cdce5d853e5d8a0bff66d9133cff6e91fe1878473b09aee9458c323efa078340d914a82de546baba00f411887f21d0abfcb573be96434685d25f2f7af8a783a911f42439945860a8fa069a571829b9b6f89efb0b65e66e59e5a26b2eb72cdfce949e0aec5e0037357bda0853082590f798e998c021e6cf314a77c9a9fa6321048ad84cd12210b7aca706a80a0715776c523b9dfb920257c942c90f6dd6243df3f3c38c79db9023d0b587581fe80", + "74013b8163241f286d823a52a5eb47e457344434334603f8e4eef9266cd7ceda": "0xf872a03931b4ed56ace4c46b68524cb5bcbf4195f1bbaacbe5228fbd090546c88dd229b84ff84d0389056bc75e2d621f95daa056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "1a1e4f1cd89dc0d1f722ffed4147195428da24de3dfb82a16a80dc0b9cff6db9": "0xf90171a06e94ede82e8c381d422f010130a4c2ed35805be58e6783d800fbb37d000090e2a00968480c83b67f0eb2cafc1df82dbf6dcac0811f36fbd405f20c46f158da5315808080a074013b8163241f286d823a52a5eb47e457344434334603f8e4eef9266cd7cedaa074b7bd6ce95c16b26c13fc914bc8b885234f8c94a621e0e3942cce38b021526ca00ab1bd40c3bd2aa3649b4ade3e0cf3e30af02bcc9241f34f3d89befaa349674180a0aff16a3ca0d6e3544a2d4deb40842cebaf9325e6a98f2d6edc4cdce5d853e5d8a0bff66d9133cff6e91fe1878473b09aee9458c323efa078340d914a82de546baba0e264b5e39e42d803daf083612a51719d5680cf5e1914c50e514277b1627eba34a069a571829b9b6f89efb0b65e66e59e5a26b2eb72cdfce949e0aec5e0037357bda0853082590f798e998c021e6cf314a77c9a9fa6321048ad84cd12210b7aca706a80a0715776c523b9dfb920257c942c90f6dd6243df3f3c38c79db9023d0b587581fe80", + "0f8c707a70d0763d58f7cba4829ad80c8965c928c9d2c6b72af0ead92e42c24b": "0xf872a03931b4ed56ace4c46b68524cb5bcbf4195f1bbaacbe5228fbd090546c88dd229b84ff84d0489056bc75e2d621f95daa056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "6d7fb74df9a5aa7132ef0c457e6824d6d85a0f792face1686214c3b7394c2781": "0xf90171a06e94ede82e8c381d422f010130a4c2ed35805be58e6783d800fbb37d000090e2a00968480c83b67f0eb2cafc1df82dbf6dcac0811f36fbd405f20c46f158da5315808080a00f8c707a70d0763d58f7cba4829ad80c8965c928c9d2c6b72af0ead92e42c24ba074b7bd6ce95c16b26c13fc914bc8b885234f8c94a621e0e3942cce38b021526ca00ab1bd40c3bd2aa3649b4ade3e0cf3e30af02bcc9241f34f3d89befaa349674180a0aff16a3ca0d6e3544a2d4deb40842cebaf9325e6a98f2d6edc4cdce5d853e5d8a0bff66d9133cff6e91fe1878473b09aee9458c323efa078340d914a82de546baba0e264b5e39e42d803daf083612a51719d5680cf5e1914c50e514277b1627eba34a069a571829b9b6f89efb0b65e66e59e5a26b2eb72cdfce949e0aec5e0037357bda0853082590f798e998c021e6cf314a77c9a9fa6321048ad84cd12210b7aca706a80a0715776c523b9dfb920257c942c90f6dd6243df3f3c38c79db9023d0b587581fe80" + }, + "blocks": [ + "0xf90260f9025aa00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940e9281e9c6a0808672eaba6bd1220e144c9bb07aa00000000000000000000000000000000000000000000000000000000000000000a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008080837a120080846842ae3a80a0000000000000000000000000000000000000000000000000000000000000000088000000000000000007a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a00000000000000000000000000000000000000000000000000000000000000000a0e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855c0c0c0", + "0xf9592ff9025aa09fde6c23289d7ec4ad19b4fca5641fca72198c55f160f8eee7fcbfb9835e49d9a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948945a1288dc78a6d8952a92c77aee6730b414778a00000000000000000000000000000000000000000000000000000000000000000a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080018354a8ca80846842af6480a0000000000000000000000000000000000000000000000000000000000000000088000000000000000001a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a00000000000000000000000000000000000000000000000000000000000000000a0e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855f956cdb956ca02f956c6018001078354a8ca8080b95675608034608357601f61565538819003918201601f19168301916001600160401b03831184841017608757808492602094604052833981010312608357516001600160a01b0381169081900360835780156074575f80546001600160a01b0319169190911790556040516155b9908161009c8239f35b63a10d827b60e01b5f5260045ffd5b5f80fd5b634e487b7160e01b5f52604160045260245ffdfe60806040526004361015610011575f80fd5b5f803560e01c806306fdde03146138d75780630d6a03be146138af578063200d2ed21461388b5780632bb2f44e1461324f578063365a86fc14613228578063447ef0c0146130b4578063540218e214612f8c57806354fd4d5014612f4757806355a373d614612f1e5780635c40f6f414612edc57806361fbddc214612eb3578063639a86a314612e8a5780636577454814612e61578063686d487314612c5c5780636b838a5a14612c335780636d6da80c146125b65780637356c4d114611fd25780637b1d97d914611ea35780637cba7353146116735780638129fc1c14611016578063823e2bc714610fed578063953adf8a14610fc4578063996642a514610401578063b518a00e146103d8578063c86da6f8146103af578063e1c94d0a14610365578063f11abfd81461033c578063f42cb038146103135763f94d315b14610159575f80fd5b346102715760203660031901126102715761017261393e565b9061017c826152ef565b60075460405160016245764560e11b031981526001600160481b0384166004820152906001600160a01b0316606082602481845afa93841561030857839284956102cf575b506001600160601b038316156102c0578442106102a857839450813b156102a357838361020392604051938492839263718835e960e11b845260048401613a73565b038183865af1908115610298578491610283575b5050803b1561027f57604051636f6d60d760e11b81523360048201526001600160601b03909216602483015282908290818381604481015b03925af18015610274576102605750f35b8161026a91613954565b6102715780f35b80fd5b6040513d84823e3d90fd5b5050fd5b8161028d91613954565b61027f57825f610217565b6040513d86823e3d90fd5b505050fd5b636bfbbc4560e01b8452426004526024859052604484fd5b63ef96b69b60e01b8452600484fd5b9094506102f591925060603d606011610301575b6102ed8183613954565b8101906139cc565b9291905091935f6101c1565b503d6102e3565b6040513d85823e3d90fd5b50346102715780600319360112610271576006546040516001600160a01b039091168152602090f35b50346102715780600319360112610271576004546040516001600160a01b039091168152602090f35b50346102715760603660031901126102715761037f61393e565b6044356001600160a01b03811681036103ab578161039f6103a8936148b0565b60243590613b7d565b80f35b8280fd5b50346102715780600319360112610271576001546040516001600160a01b039091168152602090f35b50346102715780600319360112610271576007546040516001600160a01b039091168152602090f35b50346102715760603660031901126102715761041b61393e565b906024356001600160481b0381168082036103ab576044356001600160601b03811692838203610b345761044e866148b0565b610457816148b0565b6007546001546001600160a01b03918216976001600160481b038116949092909116858514610f74578615610f655760405160208101903360601b8252601481526104a3603482613954565b5190206104b0338561492b565b600b54604051635cbeecf160e11b815290602090829060049082906001600160a01b03165afa8015610b99578583918c90610f2d575b6104f09350614d23565b50600b54604051635cbeecf160e11b815290602090829060049082906001600160a01b03165afa908115610b99578a91610efb575b505f198101908111610ee757600854604051634bb6ae1560e11b81526001600160a01b03909116919060208180610560338c60048401613aae565b0381865afa908115610cc5576105b391858f928f92610ec7575b5060405163c690956160e01b81526001600160481b038c1660048201526024810191909152929091602091849190829081906044820190565b03915afa918215610ebc578d92610e7c575b5015610e12576001600160601b039192501615610d9d575b505b6105e9338661492b565b600b54604051635cbeecf160e11b815290602090829060049082906001600160a01b03165afa8015610b99578683918c90610d61575b6106299350614d23565b5060405163c690956160e01b81526001600160481b0385166004820152602481018290529960208b604481845afa9a8b15610b99578a9b610d25575b506001600160601b038b16808a11610d0e575060055460405163b5c6b45360e01b815290602090829060049082906001600160a01b03165afa908115610bbd578b91610cd0575b506040516304c49bbd60e21b8152600481018a9052602081602481865afa908115610cc5579086918d91610c74575b506106f06001600160601b03939284926139f5565b91169182911611610c62575061070c848b9c9b98999a9b613a29565b936040516304c49bbd60e21b8152896004820152602081602481865afa8015610c575782908a90610c1a575b6107429250613a29565b926040516304c49bbd60e21b81528b6004820152602081602481875afa8015610b995783908b90610bdd575b61077892506139f5565b93833b15610bb9576040516345b8d37560e01b81528a818061079f8b878e60048501613a49565b038183895af1908115610bbd578b91610bc8575b5050833b15610bb95760405163298a690b60e01b81528a81806107da858d60048401613a73565b038183895af1908115610bbd578b91610ba4575b50506107fa908861543d565b843b15610b80576040516207ee5360e61b81528981600481838a5af1908115610b99578a91610b84575b5050823b15610b8057604051636ca3585d60e11b81529189918391829161085091908c60048501613a49565b038183865af1908115610b75578891610b60575b5050803b15610b5c5786604051809263298a690b60e01b825281838161088e888d60048401613a73565b03925af1908115610b51578791610b38575b50506108ac90856150d6565b803b15610b34578480916004604051809481936207ee5360e61b83525af1908115610b29578591610b14575b50506001600160601b031615610aad575b506008546040516331110b9160e01b81526001600160a01b039091169060208180610918338760048401613aae565b0381855afa908115610298578491610a8e575b5015610a39575b50600854604051634bb6ae1560e11b81526001600160a01b03909116916020908290819061096590339060048401613aae565b0381855afa908115610308578391610a0a575b50156109b0575b50506040519283527f326b1ff11f9cd7ab8813bdd65fa011661686e6fd1d3704a128e9f4baea315eb960203394a480f35b803b15610a065781809160646040518094819363f7f2b2c360e01b8352896004840152336024840152600160448401525af18015610274571561097f57816109f791613954565b610a0257835f61097f565b8380fd5b5080fd5b610a2c915060203d602011610a32575b610a248183613954565b810190613a96565b5f610978565b503d610a1a565b803b156103ab5782604051809263743e62bb60e11b8252818381610a61338960048401613aae565b03925af1908115610308578391610a79575b50610932565b81610a8391613954565b610a0657815f610a73565b610aa7915060203d602011610a3257610a248183613954565b5f61092b565b6008546001600160a01b0316803b15610a0257604051633be5af8f60e21b81529184918391829084908290610ae790339060048401613aae565b03925af1908115610308578391610aff575b506108e9565b81610b0991613954565b610a0657815f610af9565b81610b1e91613954565b610a0257835f6108d8565b6040513d87823e3d90fd5b8480fd5b81610b4291613954565b610b4d57855f6108a0565b8580fd5b6040513d89823e3d90fd5b8680fd5b81610b6a91613954565b610b5c57865f610864565b6040513d8a823e3d90fd5b8880fd5b81610b8e91613954565b610b8057885f610824565b6040513d8c823e3d90fd5b81610bae91613954565b610bb957895f6107ee565b8980fd5b6040513d8d823e3d90fd5b81610bd291613954565b610bb957895f6107b3565b50506020813d602011610c12575b81610bf860209383613954565b81010312610bb95782610c0d610778926139b8565b61076e565b3d9150610beb565b50506020813d602011610c4f575b81610c3560209383613954565b81010312610b805781610c4a610742926139b8565b610738565b3d9150610c28565b6040513d8b823e3d90fd5b633fc3853b60e01b8b5260045260248afd5b9150506020813d602011610cbd575b81610c9060209383613954565b81010312610cb957906001600160601b036106f087610caf83956139b8565b92509293506106db565b8b80fd5b3d9150610c83565b6040513d8e823e3d90fd5b90506020813d602011610d06575b81610ceb60209383613954565b81010312610d0257610cfc906139b8565b5f6106ac565b8a80fd5b3d9150610cde565b63177265ed60e01b8b52600452602489905260448afd5b909a506020813d602011610d59575b81610d4160209383613954565b81010312610bb957610d52906139b8565b995f610665565b3d9150610d34565b5050506020813d602011610d95575b81610d7d60209383613954565b81010312610d91578186610629925161061f565b5f80fd5b3d9150610d70565b6008546001600160a01b031690813b15610d025760405163058f15c160e21b81526001600160481b03881660048201523360248201526044810191909152908a908290606490829084905af18015610b9957908a91610dfd575b506105dd565b81610e0791613954565b610b8057885f610df7565b50813b15610d025760405163058f15c160e21b81526001600160481b03881660048201523360248201526044810191909152908a908290606490829084905af18015610b9957908a91610e67575b50506105df565b81610e7191613954565b610b8057885f610e60565b9091506020813d602011610eb4575b81610e9860209383613954565b81010312610eb057610ea9906139b8565b905f6105c5565b8c80fd5b3d9150610e8b565b6040513d8f823e3d90fd5b60209250610ee190833d8511610a3257610a248183613954565b9161057a565b634e487b7160e01b8a52601160045260248afd5b90506020813d602011610f25575b81610f1660209383613954565b81010312610d9157515f610525565b3d9150610f09565b5050506020813d602011610f5d575b81610f4960209383613954565b81010312610d915781856104f092516104e6565b3d9150610f3c565b6382c4a8c960e01b8852600488fd5b60405162461bcd60e51b815260206004820152602260248201527f43616e6e6f7420726564656c656761746520746f207468652073616d65206e6f604482015261646560f01b6064820152608490fd5b5034610271578060031936011261027157600a546040516001600160a01b039091168152602090f35b50346102715780600319360112610271576002546040516001600160a01b039091168152602090f35b503461027157806003193601126102715761102f615395565b8054604051630110ceef60e21b8152602060048201819052600360248301526241736b60e81b60448301526001600160a01b039092169181606481855afa908115610308578391611654575b5060018060a01b03166001600160601b0360a01b6001541617600155604051630110ceef60e21b81526020600482015260146024820152735368617264696e675461626c6553746f7261676560601b6044820152602081606481855afa908115610308578391611635575b5060018060a01b03166001600160601b0360a01b6002541617600255604051630110ceef60e21b815260206004820152600d60248201526c5368617264696e675461626c6560981b6044820152602081606481855afa908115610308578391611616575b5060018060a01b03166001600160601b0360a01b6003541617600355604051630110ceef60e21b815260206004820152600f60248201526e4964656e7469747953746f7261676560881b6044820152602081606481855afa9081156103085783916115f7575b5060018060a01b03166001600160601b0360a01b6004541617600455604051630110ceef60e21b8152602060048201526011602482015270506172616d657465727353746f7261676560781b6044820152602081606481855afa9081156103085783916115d8575b5060018060a01b03166001600160601b0360a01b6005541617600555604051630110ceef60e21b815260206004820152600e60248201526d50726f66696c6553746f7261676560901b6044820152602081606481855afa9081156103085783916115b9575b5060018060a01b03166001600160601b0360a01b6006541617600655604051630110ceef60e21b815260206004820152600e60248201526d5374616b696e6753746f7261676560901b6044820152602081606481855afa90811561030857839161159a575b5060018060a01b03166001600160601b0360a01b6007541617600755604051630110ceef60e21b815260206004820152600e60248201526d44656c656761746f7273496e666f60901b6044820152602081606481855afa90811561030857839161157b575b5060018060a01b03166001600160601b0360a01b6008541617600855604051630110ceef60e21b81526020600482015260056024820152642a37b5b2b760d91b6044820152602081606481855afa90811561030857839161155c575b5060018060a01b03166001600160601b0360a01b6009541617600955604051630110ceef60e21b815260206004820152601560248201527452616e646f6d53616d706c696e6753746f7261676560581b6044820152602081606481855afa90811561030857839161153d575b5060018060a01b03166001600160601b0360a01b600a541617600a55604051630110ceef60e21b81526020600482015260076024820152664368726f6e6f7360c81b6044820152602081606481855afa918215610308576064926020928591611520575b5060018060a01b03166001600160601b0360a01b600b541617600b5560405192838092630110ceef60e21b8252846004830152600c60248301526b45706f636853746f7261676560a01b60448301525afa9081156102745782916114f1575b5060018060a01b03166001600160601b0360a01b600c541617600c5580f35b611513915060203d602011611519575b61150b8183613954565b810190613b06565b5f6114d2565b503d611501565b6115379150833d85116115195761150b8183613954565b5f611473565b611556915060203d6020116115195761150b8183613954565b5f61140f565b611575915060203d6020116115195761150b8183613954565b5f6113a3565b611594915060203d6020116115195761150b8183613954565b5f611347565b6115b3915060203d6020116115195761150b8183613954565b5f6112e2565b6115d2915060203d6020116115195761150b8183613954565b5f61127d565b6115f1915060203d6020116115195761150b8183613954565b5f611218565b611610915060203d6020116115195761150b8183613954565b5f6111b0565b61162f915060203d6020116115195761150b8183613954565b5f61114a565b61164e915060203d6020116115195761150b8183613954565b5f6110e6565b61166d915060203d6020116115195761150b8183613954565b5f61107b565b50346102715760403660031901126102715761168d61393e565b906116966139a2565b916116a0816148b0565b6009546007546001600160a01b03918216949116916001600160601b038216918215611e9457604051636eb1769f60e11b81523360048201523060248201526020816044818a5afa908115611dd0579084918791611e5f575b5010611ddb576040516370a0823160e01b81523360048201526020816024818a5afa908115611dd0579084918791611d9b575b5010611d1d579084959491611741338361492b565b60405160208101903360601b82526014815261175e603482613954565b519020600b54604051635cbeecf160e11b815290602090829060049082906001600160a01b03165afa908115610b29578591611ce6575b5081846117a192614d23565b5060075460405163c690956160e01b81526001600160481b0385166004820152602481018390529190602090839060449082906001600160a01b03165afa918215610b29578592611caa575b506040516304c49bbd60e21b81526001600160481b0385166004820181905293906020816024818c5afa8015610b515782908890611c6d575b61183092506139f5565b9260018060a01b036005541660405163b5c6b45360e01b8152602081600481855afa8015610c57578990611c2d575b6001600160601b039150166001600160601b03861611611ba3575090611884916139f5565b90873b15610b4d576040516345b8d37560e01b8152918691839182916118af91908960048501613a49565b0381838b5af1908115610b29578591611b8e575b5050853b15610a025760405163298a690b60e01b81528481806118ea858860048401613a73565b0381838b5af1908115610b29578591611b79575b5050853b15610a0257604051633ada6a6360e01b8152600481018690528481602481838b5af1908115610b29578591611b64575b505061193e90836150d6565b6001546001600160a01b0316803b15610a02578380916004604051809481936207ee5360e61b83525af1908115610298578491611b4f575b50506008546040516331110b9160e01b81526001600160a01b0390911690602081806119a6338860048401613aae565b0381855afa908115610b29578591611b30575b5015611adb575b50600854604051634bb6ae1560e11b81526001600160a01b0390911692602090829081906119f390339060048401613aae565b0381865afa908115610298578491611abc575b5015611a63575b505060209260649160405195869485936323b872dd60e01b8552336004860152602485015260448401525af1801561027457611a47575080f35b611a5f9060203d602011610a3257610a248183613954565b5080f35b813b156103ab57829160648392604051948593849263f7f2b2c360e01b84526004840152336024840152600160448401525af1801561027457611aa7575b80611a0d565b81611ab191613954565b610a0257835f611aa1565b611ad5915060203d602011610a3257610a248183613954565b5f611a06565b803b15610a025783604051809263743e62bb60e11b8252818381611b03338a60048401613aae565b03925af1908115610298578491611b1b575b506119c0565b81611b2591613954565b6103ab57825f611b15565b611b49915060203d602011610a3257610a248183613954565b5f6119b9565b81611b5991613954565b6103ab57825f611976565b81611b6e91613954565b610a0257835f611932565b81611b8391613954565b610a0257835f6118fe565b81611b9891613954565b610a0257835f6118c3565b6004602089926040519283809263b5c6b45360e01b82525afa908115610274578291611be6575b633fc3853b60e01b83526001600160601b038216600452602483fd5b90506020813d602011611c25575b81611c0160209383613954565b81010312610a0657906001600160601b03611c1d6024936139b8565b919250611bca565b3d9150611bf4565b506020813d602011611c65575b81611c4760209383613954565b81010312610b8057611c606001600160601b03916139b8565b61185f565b3d9150611c3a565b50506020813d602011611ca2575b81611c8860209383613954565b81010312610b5c5781611c9d611830926139b8565b611826565b3d9150611c7b565b9091506020813d602011611cde575b81611cc660209383613954565b81010312610b3457611cd7906139b8565b905f6117ed565b3d9150611cb9565b9450506020843d602011611d15575b81611d0260209383613954565b81010312610d9157925187939081611795565b3d9150611cf5565b50506040516370a0823160e01b815233600482015293909150602084602481845afa908115610308578391611d66575b631f32daeb60e21b845260045260245260445260649150fd5b90506020843d602011611d93575b81611d8160209383613954565b81010312610d91576064935190611d4d565b3d9150611d74565b9150506020813d602011611dc8575b81611db760209383613954565b81010312610d91578390515f61172c565b3d9150611daa565b6040513d88823e3d90fd5b5050604051636eb1769f60e11b815233600482015230602482015293909150602084604481845afa908115610308578391611e2a575b637000ca7760e01b845260045260245260445260649150fd5b90506020843d602011611e57575b81611e4560209383613954565b81010312610d91576064935190611e11565b3d9150611e38565b9150506020813d602011611e8c575b81611e7b60209383613954565b81010312610d91578390515f6116f9565b3d9150611e6e565b6382c4a8c960e01b8552600485fd5b503461027157602036600319011261027157611ebd61393e565b90611ec7826148b0565b60018060a01b036007541660405160208101903360601b825260148152611eef603482613954565b5190206040516337e50bf160e01b81526001600160481b0385166004820152602481018290529190606083604481855afa9485156102985784938596611fa9575b506001600160601b03841615611f9a57854210611f8257849550823b15610b34576040516308962e4760e21b81526001600160481b039091166004820152602481019190915283818060448101610203565b636bfbbc4560e01b8552426004526024869052604485fd5b63ef96b69b60e01b8552600485fd5b909550611fc691935060603d606011610301576102ed8183613954565b9391905092945f611f30565b503461027157604036600319011261027157611fec61393e565b90611ff56139a2565b611ffe836148b0565b60018060a01b03600754166001600160601b0382169384156125a757612024338261492b565b60405160208101903360601b825260148152612041603482613954565b519020600b54604051635cbeecf160e11b815291929190602090829060049082906001600160a01b03165afa8015611dd057828491889061256f575b6120879350614d23565b5060405163c690956160e01b81526001600160481b03821660048201526024810183905295602087604481875afa968715611dd0578697612533575b506001600160601b03871680821161251e57506120e1858798613a29565b6040516304c49bbd60e21b81526001600160481b0384166004820152602081602481895afa8015610b7557879089906124e1575b61211f9250613a29565b91853b1561241f576040516345b8d37560e01b8152888180612146868a8a60048501613a49565b0381838b5af1908115610c575789916124cc575b5050853b1561241f5760405163298a690b60e01b8152888180612181878960048401613a73565b0381838b5af1908115610c575789916124b7575b5050853b1561241f576040519063e1d78b2b60e01b825260048201528781602481838a5af1908115610b755788916124a2575b50506121d4828461543d565b6001546001600160a01b0316803b1561241f578780916004604051809481936207ee5360e61b83525af1908115610b7557889161248d575b50506001600160601b03161561242b575b60055460405163b5c6b45360e01b81526001600160a01b039091169190602081600481865afa908115610b755788916123e3575b506001600160601b039081169116106122b057505050803b1561027f57604051636f6d60d760e11b81523360048201526001600160601b03909216602483015282908290818381604481015b03925af180156102745761026057505080f35b6040516337e50bf160e01b81526001600160481b0383166004820152602481018490529294919390929091606082604481865afa918215610b5157600492602092612302928a926123c0575b506139f5565b936040519283809263151db1b960e01b82525afa908115611dd0578691612388575b5061232f9042613af9565b93813b15610b4d57604051630185e24960e31b81526001600160481b03909416600485015260248401526001600160601b0390911660448301525f60648301526084820192909252908290829081838160a4810161229d565b9550506020853d6020116123b8575b816123a460209383613954565b81010312610d915761232f86955190612324565b3d9150612397565b6123da91925060603d606011610301576102ed8183613954565b5050905f6122fc565b90506020813d602011612423575b816123fe60209383613954565b8101031261241f576001600160601b0361241881926139b8565b9150612251565b8780fd5b3d91506123f1565b6008546001600160a01b0316803b15610b5c57866040518092633be5af8f60e21b825281838161245f338a60048401613aae565b03925af1908115610b51578791612478575b505061221d565b8161248291613954565b610b4d57855f612471565b8161249791613954565b610b5c57865f61220c565b816124ac91613954565b610b5c57865f6121c8565b816124c191613954565b61241f57875f612195565b816124d691613954565b61241f57875f61215a565b50506020813d602011612516575b816124fc60209383613954565b8101031261241f578661251161211f926139b8565b612115565b3d91506124ef565b63177265ed60e01b8752600452602452604485fd5b9096506020813d602011612567575b8161254f60209383613954565b81010312610b4d57612560906139b8565b955f6120c3565b3d9150612542565b5050506020813d60201161259f575b8161258b60209383613954565b81010312610d91578282612087925161207d565b3d915061257e565b6382c4a8c960e01b8452600484fd5b5034610271576040366003190112610271576125d061393e565b906125d96139a2565b916125e3816152ef565b6007546001600160a01b03166001600160601b03841680156125a75760405191637946927960e11b83526001600160481b03841691826004850152602084602481855afa938415611dd0578694612bf7575b506001600160601b03841696878211612be0579086939291612657338861492b565b60405160208101903360601b825260148152612674603482613954565b519020600b54604051635cbeecf160e11b815291979190602090829060049082906001600160a01b03165afa908115610b515788918a918991612ba3575b5084926126c994926126c392614d23565b50613a29565b833b15610b4d57856126f091604051809381926357a46be960e11b83528c60048401613a73565b038183885af1908115611dd0578691612b8e575b505060405163c690956160e01b81526001600160481b03881660048201526024810187905295602087604481875afa968715611dd0578697612b52575b506040516304c49bbd60e21b815260048101869052602081602481885afa8015610b515783908890612b15575b61277892506139f5565b9660018060a01b036005541660405163b5c6b45360e01b8152602081600481855afa8015610c57578990612ad5575b6001600160601b039150166001600160601b038a1611611ba35750826127cc916139f5565b90843b15610b5c576040516345b8d37560e01b8152918791839182916127f791908d60048501613a49565b038183885af1908115611dd0578691612ac0575b5050823b15610b345760405163298a690b60e01b81528581806128328a8c60048401613a73565b038183885af1908115611dd0578691612aab575b5050823b15610b34578461286f916040518093819263718835e960e11b83528b60048401613a73565b038183875af1908115610b29578591612a96575b5050813b15610a02578391602483926040519485938492633ada6a6360e01b845260048401525af1908115610308578391612a81575b50506008546040516331110b9160e01b81526001600160a01b0390911690602081806128e9338a60048401613aae565b0381855afa908115610298578491612a62575b5015612a0d575b50600854604051634bb6ae1560e11b81526001600160a01b03909116919060208180612933338a60048401613aae565b0381865afa9081156102985784916129ee575b5015612995575b505050612959916150d6565b60015481906001600160a01b0316803b15612992578180916004604051809481936207ee5360e61b83525af18015610274576102605750f35b50fd5b813b156103ab57829160648392604051948593849263f7f2b2c360e01b84526004840152336024840152600160448401525af18015610274576129d9575b8061294d565b816129e391613954565b6103ab5782846129d3565b612a07915060203d602011610a3257610a248183613954565b87612946565b803b156103ab5782604051809263743e62bb60e11b8252818381612a35338c60048401613aae565b03925af1908115610308578391612a4d575b50612903565b81612a5791613954565b610a06578186612a47565b612a7b915060203d602011610a3257610a248183613954565b876128fc565b81612a8b91613954565b610a065781866128b9565b81612aa091613954565b610a02578388612883565b81612ab591613954565b610b34578489612846565b81612aca91613954565b610b3457848961280b565b506020813d602011612b0d575b81612aef60209383613954565b81010312610b8057612b086001600160601b03916139b8565b6127a7565b3d9150612ae2565b50506020813d602011612b4a575b81612b3060209383613954565b81010312610b5c5782612b45612778926139b8565b61276e565b3d9150612b23565b9096506020813d602011612b86575b81612b6e60209383613954565b81010312610b4d57612b7f906139b8565b9589612741565b3d9150612b61565b81612b9891613954565b610b34578489612704565b98505050506020863d602011612bd8575b81612bc160209383613954565b81010312610d9157945188959087908990846126b2565b3d9150612bb4565b604487838a63b354dd2d60e01b8352600452602452fd5b9093506020813d602011612c2b575b81612c1360209383613954565b81010312610b4d57612c24906139b8565b925f612635565b3d9150612c06565b50346102715780600319360112610271576003546040516001600160a01b039091168152602090f35b503461027157604036600319011261027157612c7661393e565b90612c7f6139a2565b91612c89816152ef565b6007546001600160a01b0316906001600160601b03841680156125a75760405192637946927960e11b84526001600160481b03831692836004860152602085602481855afa948515611dd0578695612e25575b506001600160601b03851696878411612e0e5760055460405163151db1b960e01b8152979850889790602090829060049082906001600160a01b03165afa908115610b75578891612dd5575b5090612d37612d3d9242613af9565b96613a29565b90823b15610b5c576040516357a46be960e11b815291879183918291612d67919060048401613a73565b038183865af1908115611dd0578691612dc0575b5050803b15610b345784928360849260405196879586946355b2622160e01b86526004860152602485015282604485015260648401525af18015610274576102605750f35b81612dca91613954565b610b3457845f612d7b565b919750506020813d602011612e06575b81612df260209383613954565b81010312610d915751879690612d37612d28565b3d9150612de5565b604487858a63b354dd2d60e01b8352600452602452fd5b9094506020813d602011612e59575b81612e4160209383613954565b81010312610b4d57612e52906139b8565b935f612cdc565b3d9150612e34565b5034610271578060031936011261027157600b546040516001600160a01b039091168152602090f35b50346102715780600319360112610271576005546040516001600160a01b039091168152602090f35b50346102715780600319360112610271576008546040516001600160a01b039091168152602090f35b503461027157602036600319011261027157600435801515809103610a0657612f03615395565b815460ff60a01b191660a09190911b60ff60a01b1617815580f35b50346102715780600319360112610271576009546040516001600160a01b039091168152602090f35b503461027157806003193601126102715750612f88604051612f6a604082613954565b6005815264312e302e3160d81b602082015260405191829182613914565b0390f35b503461027157602036600319011261027157612fa661393e565b90612fb0826152ef565b6007546040516327ac00d160e01b81526001600160481b03841660048201819052936001600160a01b039092169190602081602481865afa90811561029857849161307a575b506001600160601b038116156102c0578394833b15610b345760405190639bd1c02b60e01b82526004820152848160248183885af1908115610b29578591613065575b5050823b156102a35761024f9284928360405180968195829463216972d760e11b845260048401613a73565b8161306f91613954565b6102a357835f613039565b90506020813d6020116130ac575b8161309560209383613954565b81010312610a02576130a6906139b8565b5f612ff6565b3d9150613088565b5034610271576060366003190112610271576130ce61393e565b60243567ffffffffffffffff81116103ab57366023820112156103ab578060040135906130fa8261398a565b916131086040519384613954565b8083526024602084019160051b83010191368311610b4d57602401905b828210613218575050506044359167ffffffffffffffff8311610a025736602384011215610a0257826004013561315b8161398a565b936131696040519586613954565b8185526024602086019260051b82010190368211610b5c57602401915b8183106131f857505050613199816148b0565b83925b82518410156131f457845b81518110156131e9576001906131e36131c08787613ad1565b51838060a01b036131d18487613ad1565b5116906131dd876148b0565b86613b7d565b016131a7565b50926001019261319c565b8480f35b82356001600160a01b038116810361241f57815260209283019201613186565b8135815260209182019101613125565b5034610271578060031936011261027157546040516001600160a01b039091168152602090f35b5034610d91576020366003190112610d915761326961393e565b90613273826148b0565b60018060a01b036007541660405160208101903360601b82526014815261329b603482613954565b5190206040516337e50bf160e01b81526001600160481b0385166004820152602481018290529390606085604481865afa8015613759575f955f91613864575b506001600160601b03861615613855576132f5338461492b565b600b54604051635cbeecf160e11b815290602090829060049082906001600160a01b03165afa8015613759578484915f9061381d575b6133359350614d23565b506040516304c49bbd60e21b81526001600160481b038416600482018190529290602081602481895afa908115613759575f916137e3575b5060055460405163b5c6b45360e01b815290602090829060049082906001600160a01b03165afa908115613759575f916137a9575b505f6133ae8a846139f5565b6001600160601b03838116911611156137a157506133cf826133d692613a29565b8099613a29565b905b6001600160601b038916908161354a575b50508697506001600160601b0381979495969716155f146134d057509050843b15610a06576040516308962e4760e21b81526001600160481b03851660048201526024810191909152818160448183895af18015610274576134bb575b50506020905b6024604051809581936304c49bbd60e21b835260048301525afa90811561030857839161347e575b61295992506150d6565b90506020823d6020116134b3575b8161349960209383613954565b810103126103ab576134ad612959926139b8565b90613474565b3d915061348c565b816134c591613954565b610a0257835f613446565b863b15610a0257604051630185e24960e31b81526001600160481b038716600482015260248101929092526001600160601b031660448201525f60648201526084810191909152818160a48183895af1801561027457613535575b505060209061344c565b8161353f91613954565b610a0257835f61352b565b60405163c690956160e01b81526001600160481b0388166004820152602481018590526020816044818c5afa8015613759578b905f90613764575b61358f92506139f5565b883b15610d91575f6135b791604051809381926345b8d37560e01b8352898d60048501613a49565b0381838d5af180156137595761373c575b5088996135d99199969798996139f5565b883b15610b4d5785613600916040518093819263298a690b60e01b83528c60048401613a73565b0381838d5af1908115611dd0578691613727575b5050873b15610b345760405190633ada6a6360e01b825260048201528481602481838c5af1908115610b29578591613712575b50506008546040516331110b9160e01b81526001600160a01b039091169060208180613677338c60048401613aae565b0381855afa908115611dd05786916136f3575b501561369c575b8097969594976133e9565b803b15610b345760405163743e62bb60e11b815290859082908183816136c6338e60048401613aae565b03925af1908115610b295785916136de575b50613691565b816136e891613954565b610a0257835f6136d8565b61370c915060203d602011610a3257610a248183613954565b5f61368a565b8161371c91613954565b610a0257835f613647565b8161373191613954565b610b3457845f613614565b61374c9196979899505f90613954565b5f979695946135d96135c8565b6040513d5f823e3d90fd5b50506020813d602011613799575b8161377f60209383613954565b81010312610d91578a61379461358f926139b8565b613585565b3d9150613772565b9190506133d8565b90506020813d6020116137db575b816137c460209383613954565b81010312610d91576137d5906139b8565b5f6133a2565b3d91506137b7565b90506020813d602011613815575b816137fe60209383613954565b81010312610d915761380f906139b8565b5f61336d565b3d91506137f1565b5050506020813d60201161384d575b8161383960209383613954565b81010312610d91578284613335925161332b565b3d915061382c565b63ef96b69b60e01b5f5260045ffd5b905061388091955060603d606011610301576102ed8183613954565b95919050945f6132db565b34610d91575f366003190112610d9157602060ff5f5460a01c166040519015158152f35b34610d91575f366003190112610d9157600c546040516001600160a01b039091168152602090f35b34610d91575f366003190112610d9157612f886040516138f8604082613954565b60078152665374616b696e6760c81b6020820152604051918291825b602060409281835280519182918282860152018484015e5f828201840152601f01601f1916010190565b600435906001600160481b0382168203610d9157565b90601f8019910116810190811067ffffffffffffffff82111761397657604052565b634e487b7160e01b5f52604160045260245ffd5b67ffffffffffffffff81116139765760051b60200190565b602435906001600160601b0382168203610d9157565b51906001600160601b0382168203610d9157565b90816060910312610d91576139e0816139b8565b9160406139ef602084016139b8565b92015190565b906001600160601b03809116911601906001600160601b038211613a1557565b634e487b7160e01b5f52601160045260245ffd5b906001600160601b03809116911603906001600160601b038211613a1557565b9160409194936001600160601b03916001600160481b036060860197168552602085015216910152565b6001600160481b0390911681526001600160601b03909116602082015260400190565b90816020910312610d9157518015158103610d915790565b6001600160481b0390911681526001600160a01b03909116602082015260400190565b8051821015613ae55760209160051b010190565b634e487b7160e01b5f52603260045260245ffd5b91908201809211613a1557565b90816020910312610d9157516001600160a01b0381168103610d915790565b91908203918211613a1557565b90816020910312610d91575161ffff81168103610d915790565b81810292918115918404141715613a1557565b8115613b69570490565b634e487b7160e01b5f52601260045260245ffd5b600b54604051635cbeecf160e11b81525f94929390929091602090849060049082906001600160a01b03165afa928315613759575f9361487c575b5082821015614841576008546040516331110b9160e01b81526001600160a01b03909116939060208180613bf0868a60048401613aae565b0381885afa908115613759575f91614822575b50156147e75760405163f893880360e01b815260208180613c28868a60048401613aae565b0381885afa908115613759575f916147b5575b505f198201918211613a155781811461476457808411156147275760018101809111613a155783116146e25760405160208101906001600160601b03198460601b16825260148152613c8e603482613954565b519020604051633fec9e3560e11b8152600481018590526001600160481b0387166024820152604481018290529094602090829060649082905afa908115613759575f916146c3575b5061466f57613ce7848685614d23565b600a54604051638458435760e01b8152600481018690526001600160481b03881660248201526001600160a01b0390911691602082604481865afa918215613759575f9261463b575b5060085460405163c939043d60e01b81526001600160481b038a166004820152602481018890525f94916001600160a01b0316602082604481845afa80156137595789925f9161461c575b506145a057505060065460405163275acb7b60e11b81526001600160481b038b1660048201819052929091602090839060249082906001600160a01b03165afa918215613759575f9261456b575b50602060249160405192838092630bdcdc1560e01b82528d60048301525afa908115613759575f91614539575b5080614467575b506001600160601b03612710613e1a61ffff613e23941688613b4c565b04168095613b25565b6007549094906001600160a01b0316803b15610d9157613e5d915f918c8360405180968195829463216972d760e11b845260048401613a73565b03925af1801561375957614452575b506008546001600160a01b0316803b15610d02578a8091606460405180948193636d9f29b360e01b83528760048401528d6024840152600160448401525af18015610bbd57908b9161443d575b50506008546001600160a01b0316803b15610d0257604051632e077a3760e01b81526001600160481b038b16600482015260248101899052908b908290604490829084905af18015610bbd57908b91614428575b50506008546001600160a01b031690813b15610d02578a916064839260405194859384926382b98cc360e01b845260048401528c60248401528960448401525af18015610b9957908a91614413575b50505b8015801561440b575b8015614403575b156143eb5750505085925b6008546001600160a01b031690813b1561241f5760405163329a834360e11b81528160048201528881608481836001600160481b038d16978860248401528c6044840152600160648401525af18015610c57579089916143d6575b505060085460405163f893880360e01b815291906001600160a01b031660208380614004898d60048401613aae565b0381845afa928315610b99578a936143a2575b50803b15610bb95760405163058f15c160e21b81526001600160481b038a1660048201526001600160a01b0387166024820152604481019290925289908290606490829084905af18015610c575790899161438d575b50508415614383576008546040516340cd9d3960e11b8152936001600160a01b039091169190602085806140a5898d60048401613aae565b0381865afa948515610b99578a9561434e575b506001916140c591613b25565b11156141bc5750506008546001600160a01b0316906140e5908490613af9565b91813b15610b5c57604051638c436ca360e01b81526001600160481b03871660048201526001600160a01b03919091166024820152604481019290925285908290606490829084905af18015610b29579085916141a7575b50505b6007546001600160a01b031690813b15610b3457906001600160601b0385809493614183604051978896879586946303341fc160e11b8652169160048501613a49565b03925af1801561027457614195575050565b6141a0828092613954565b6102715750565b816141b191613954565b610a0257835f61413d565b916141ca9085949294613af9565b92823b1561241f579060648892836040519586948593638c436ca360e01b8552600485015260018060a01b031660248401528160448401525af18015611dd057908691614339575b50506007546001600160601b0391909116906001600160a01b0316803b15610b4d57856040518092636ca3585d60e11b8252818381614256888b8d60048501613a49565b03925af18015611dd057908691614324575b50506007546001600160a01b0316803b15610b4d578560405180926397d2904f60e01b825281838161429e888c60048401613a73565b03925af18015611dd05790869161430f575b50506007546001600160a01b031690813b15610b4d578591602483926040519485938492633ada6a6360e01b845260048401525af18015610b29579085916142fa575b5050614140565b8161430491613954565b610a0257835f6142f3565b8161431991613954565b610b3457845f6142b0565b8161432e91613954565b610b3457845f614268565b8161434391613954565b610b3457845f614212565b9094506020813d60201161437b575b8161436a60209383613954565b81010312610d9157519360016140b8565b3d915061435d565b5050505050505050565b8161439791613954565b61241f57875f61406d565b9092506020813d6020116143ce575b816143be60209383613954565b81010312610d915751915f614017565b3d91506143b1565b816143e091613954565b61241f57875f613fd5565b6143fd926143f891613b4c565b613b5f565b92613f7a565b508215613f6f565b508115613f68565b8161441d91613954565b610b8057885f613f5c565b8161443291613954565b610bb957895f613f0d565b8161444791613954565b610bb957895f613eb9565b61445f919a505f90613954565b5f985f613e6c565b9094506044602060018060a01b03600c5416604051928380926305e8e33560e51b8252600160048301528d60248301525afa80156137595785915f916144d8575b50613e1a61ffff6144cd613e23956143f86001600160601b0396876127109716613b4c565b989450505050613dfd565b9150506020813d602011614531575b816144f460209383613954565b81010312610d9157612710613e1a61ffff6144cd613e23956143f88a6001600160601b0361452281996139b8565b975050965050955050506144a8565b3d91506144e7565b90506020813d602011614563575b8161455460209383613954565b81010312610d9157515f613df6565b3d9150614547565b6024919250614591602091823d8411614599575b6145898183613954565b810190613b32565b929150613dc9565b503d61457f565b604051631b6cef6360e31b81526001600160481b038c16600482015260248101929092529294509160209150829060449082905afa908115613759575f916145ea575b5091613f5f565b90506020813d602011614614575b8161460560209383613954565b81010312610d9157515f6145e3565b3d91506145f8565b614635915060203d602011610a3257610a248183613954565b5f613d7b565b9091506020813d602011614667575b8161465760209383613954565b81010312610d915751905f613d30565b3d915061464a565b60405162461bcd60e51b815260206004820152602660248201527f416c726561647920636c61696d6564207265776172647320666f722074686973604482015265040cae0dec6d60d31b6064820152608490fd5b6146dc915060203d602011610a3257610a248183613954565b5f613cd7565b60405162461bcd60e51b815260206004820152601d60248201527f4d75737420636c61696d206f6c6465722065706f6368732066697273740000006044820152606490fd5b60405162461bcd60e51b8152602060048201526015602482015274115c1bd8da08185b1c9958591e4818db185a5b5959605a1b6044820152606490fd5b60405162461bcd60e51b8152602060048201526024808201527f416c726561647920636c61696d656420616c6c2066696e616c697365642065706044820152636f63687360e01b6064820152608490fd5b90506020813d6020116147df575b816147d060209383613954565b81010312610d9157515f613c3b565b3d91506147c3565b60405162461bcd60e51b815260206004820152601360248201527211195b1959d85d1bdc881b9bdd08199bdd5b99606a1b6044820152606490fd5b61483b915060203d602011610a3257610a248183613954565b5f613c03565b60405162461bcd60e51b8152602060048201526013602482015272115c1bd8da081b9bdd08199a5b985b1a5cd959606a1b6044820152606490fd5b9092506020813d6020116148a8575b8161489860209383613954565b81010312610d915751915f613bb8565b3d915061488b565b6001600160481b03602060018060a01b03600654169260246040518094819363c04d7dcf60e01b835216958660048301525afa908115613759575f9161490c575b50156148fa5750565b63054202f760e51b5f5260045260245ffd5b614925915060203d602011610a3257610a248183613954565b5f6148f1565b600460405160208101906001600160601b03198560601b16825260148152614954603482613954565b519020600b54604051635cbeecf160e11b81529260209184919082906001600160a01b03165afa918215613759575f92614cef575b5060085460405163f893880360e01b8152926001600160a01b039091169190602084806149ba898960048401613aae565b0381865afa938415613759575f94614cbb575b505f19810193818511613a1557848114614cb2576001198201918211613a155710614c4757600a54604051630ee1bfcd60e01b8152600481018590526001600160481b0386166024820152604481018390526001600160a01b039091169190602081606481865afa908115613759575f91614c15575b50604051632a95743f60e01b8152600481018690526001600160481b038716602482015291602083604481875afa928315613759575f93614be0575b50604051622b987b60e31b8152600481018790526001600160481b038816602482015260448101919091529192602090839060649082905afa918215613759575f92614bac575b50159182614ba2575b5050614b405760405162461bcd60e51b815260206004820152603b60248201527f4d75737420636c61696d207468652070726576696f75732065706f636820726560448201527f7761726473206265666f7265206368616e67696e67207374616b6500000000006064820152608490fd5b803b15610d915760405163058f15c160e21b81526001600160481b0390931660048401526001600160a01b0390931660248301526044820152905f9082908183816064810103925af1801561375957614b965750565b5f614ba091613954565b565b1490505f80614acf565b9091506020813d602011614bd8575b81614bc860209383613954565b81010312610d915751905f614ac6565b3d9150614bbb565b9092506020813d602011614c0d575b81614bfc60209383613954565b81010312610d915751916020614a7f565b3d9150614bef565b90506020813d602011614c3f575b81614c3060209383613954565b81010312610d9157515f614a43565b3d9150614c23565b60405162461bcd60e51b815260206004820152603b60248201527f4d75737420636c61696d20616c6c2070726576696f75732065706f636820726560448201527f7761726473206265666f7265206368616e67696e67207374616b6500000000006064820152608490fd5b50505050505050565b9093506020813d602011614ce7575b81614cd760209383613954565b81010312610d915751925f6149cd565b3d9150614cca565b9091506020813d602011614d1b575b81614d0b60209383613954565b81010312610d915751905f614989565b3d9150614cfe565b600a54604051632a95743f60e01b8152600481018390526001600160481b03841660248201525f95946001600160a01b0390921692909190602083604481875afa928315613759575f936150a2575b50604051630ee1bfcd60e01b8152600481018290526001600160481b03861660248201526044810183905293602085606481845afa948515613759575f9561506e575b50604051622b987b60e31b8152600481018390526001600160481b038716602482015260448101849052602081606481855afa908115613759575f9161503c575b508085146150315760075460405163c690956160e01b81526001600160481b03891660048201526024810186905290602090829060449082906001600160a01b03165afa8015613759575f90614ff1575b6001600160601b03915016918215614f875750614e7a89949392614e74670de0b6b3a76400009388613b25565b90613b4c565b049586614f0b575b600a546001600160a01b031691823b15610b34578490614ed860405197889687958694635ed45e5360e11b865260048601909493926001600160481b036060936080840197845216602083015260408201520152565b03925af18015610b2957614ef6575b50614ef3929350613af9565b90565b614f01858092613954565b610a025783614ee7565b600a546001600160a01b0316803b15610b345760405163cdddd01f60e01b8152600481018490526001600160481b038316602482015260448101859052606481018990529085908290608490829084905af1908115610b29578591614f72575b5050614e82565b81614f7c91613954565b610a0257835f614f6b565b93949692959798505050813b15610d9157604051635ed45e5360e11b815260048101949094526001600160481b0316602484015260448301919091526064820192909252905f908290608490829084905af1801561375957614fe7575090565b5f614ef391613954565b506020813d602011615029575b8161500b60209383613954565b81010312610d91576150246001600160601b03916139b8565b614e47565b3d9150614ffe565b509396505050505050565b90506020813d602011615066575b8161505760209383613954565b81010312610d9157515f614df6565b3d915061504a565b9094506020813d60201161509a575b8161508a60209383613954565b81010312610d915751935f614db5565b3d915061507d565b9092506020813d6020116150ce575b816150be60209383613954565b81010312610d915751915f614d72565b3d91506150b1565b60025460055460405163175a11e760e21b81526001600160481b0390931660048401819052936001600160a01b0392831693919092169190602081602481875afa908115613759575f916152d0575b5015908161524f575b5061513857505050565b60206004926040519384809263f1a3c5b360e01b82525afa918215613759575f9261520a575b5060206004916040519283809263192663ed60e11b82525afa908115613759576001600160481b039161ffff915f916151eb575b5016911610156151dc576003546001600160a01b031690813b15610d91575f9160248392604051948593849263090444a160e41b845260048401525af1801561375957614b965750565b6310aff3b760e31b5f5260045ffd5b615204915060203d602011614599576145898183613954565b5f615192565b9091506020813d602011615247575b8161522660209383613954565b81010312610d9157516001600160481b0381168103610d915790602061515e565b3d9150615219565b60405163762ffd6160e11b8152909150602081600481865afa908115613759575f9161528c575b506001600160601b03809116911610155f61512e565b90506020813d6020116152c8575b816152a760209383613954565b81010312610d91576001600160601b036152c181926139b8565b9150615276565b3d915061529a565b6152e9915060203d602011610a3257610a248183613954565b5f615125565b60206001600160481b03606460018060a01b036004541693604051848101903360601b825260148152615323603482613954565b519020946040519586948593631af27dbd60e11b85521660048401526024830152600160448301525afa908115613759575f91615376575b501561536357565b63024ac36b60e21b5f523360045260245ffd5b61538f915060203d602011610a3257610a248183613954565b5f61535b565b60018060a01b035f54168033141590816153e2575b506153b157565b60405163f0b1bddb60e01b815260206004820152600860248201526727b7363c90243ab160c11b6044820152606490fd5b604051638da5cb5b60e01b81529150602090829060049082905afa908115613759575f9161541e575b506001600160a01b03163314155f6153aa565b615437915060203d6020116115195761150b8183613954565b5f61540b565b60025460405163175a11e760e21b81526001600160481b03909216600483018190529290602090839060249082906001600160a01b03165afa918215613759575f92615562575b50816154d3575b506154935750565b6003546001600160a01b031690813b15610d91575f916024839260405194859384926357ce0f6360e11b845260048401525af1801561375957614b965750565b60055460405163762ffd6160e11b8152919250602090829060049082906001600160a01b03165afa908115613759575f9161551e575b506001600160601b038091169116105f61548b565b90506020813d60201161555a575b8161553960209383613954565b81010312610d91576001600160601b0361555381926139b8565b9150615509565b3d915061552c565b61557c91925060203d602011610a3257610a248183613954565b905f61548456fea264697066735822122032affa1a855a001ebf795eba95bdca806c2a5b87290d1595764ac3244ce12d7e64736f6c634300081a0033000000000000000000000000c5f6a39480968b8d09315d749375855b550cf5d2c080a05e344f61ca3aee9228adfb50384a117334237e7b78fa0e35f1d379981a164aa1a079ffeecf3cde0a5c747a4b6da1ea5062b8b92082a69754cedcccf7311287bc99c0c0", + "0xf902cdf9025aa0dce87e74d0d56d3d19c815c90bbc55359c6dbc11eb212b0a1de426e49f02f096a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d493479494d76e24f818426ae84aa404140e8d5f60e10e7ea00000000000000000000000000000000000000000000000000000000000000000a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008002832dc6c080846842af9080a0000000000000000000000000000000000000000000000000000000000000000088000000000000000001a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a00000000000000000000000000000000000000000000000000000000000000000a0e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855f86cb86a02f86701010107832dc6c094d9145cce52d386f254917e481eb44e9943f3913880848129fc1cc001a0d66813faa2e9f307d12e9e6d2521ed74b9b3da57c7015862dad9770f702eeafaa02c5628b75093c9822b42b983c8f66f1cec3d195dfc6fb287339134af60c98bb8c0c0", + "0xf902cdf9025aa09dfc54bca3c3949b07d8ecc2d6b15a89a2eb40c9b9d43b61331a07ca06afc5f5a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940e9281e9c6a0808672eaba6bd1220e144c9bb07aa00000000000000000000000000000000000000000000000000000000000000000a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008003832dc6c080846842b34480a0000000000000000000000000000000000000000000000000000000000000000088000000000000000001a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a00000000000000000000000000000000000000000000000000000000000000000a0e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855f86cb86a02f86701020107832dc6c094d9145cce52d386f254917e481eb44e9943f3913880848129fc1cc080a0ab4ee95f7b0876acc0eb851526f77fd4e77051acd8b641a9cd3b3f3184f5b97fa00681e429e831a94d1d2665639568f357a2699e1487f96ee94537e815fac723c3c0c0", + "0xf902cdf9025aa0c2275433366ac04db22f2e39672eea3cd52bb958ab553433d85a69a289a5b8f8a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948945a1288dc78a6d8952a92c77aee6730b414778a00000000000000000000000000000000000000000000000000000000000000000a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008004832dc6c080846842b55280a0000000000000000000000000000000000000000000000000000000000000000088000000000000000001a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b4218080a00000000000000000000000000000000000000000000000000000000000000000a0e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855f86cb86a02f86701030107832dc6c094d9145cce52d386f254917e481eb44e9943f3913880848129fc1cc001a0182eeed5ff0f009cc0f19ea9b63623a655d0590d10b4f863c628d92be592e890a01856033eb47912493a29fdeb3d9015bebd3faa7fa211c12119591f59e2578079c0c0" + ], + "latestBlockNumber": "0x4", + "baseBlockNumber": "0x0" +} diff --git a/README.md b/README.md index fd62bb61..3ba83e9d 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,7 @@ npm install ``` ## NPM Scripts + This project utilizes a variety of NPM scripts to run various tasks and processes. The scripts are defined in the package.json file and are designed to be used with the Hardhat CLI, leveraging Hardhat plugins for additional functionality. Here's a brief description of the scripts: - `clean`: Removes the cache and artifacts folders generated by Hardhat. @@ -65,6 +66,7 @@ npm run compile ``` ## Additional Hardhat tasks + Hardhat has plenty of other useful commands, extended by the installed plugins. Here's a brief description of the most useful tasks: - `decode`: Decodes encoded ABI data (e.g. input data of transaction). @@ -79,14 +81,17 @@ npx hardhat decode --data ``` Usage example of `encode_data` task. Here we want to call ProofManagerV1 function called setReq, and this function can be called only through `forwardCall` in HubController and encoding arguments for this function can be done by using this task: + ```sh npx hardhat encode_data --contract-name ProofManagerV1 --function-name setReq 1 true ``` + Alternatively, encoded data can be produced from Remix by copying prepared calldata from ProofManagerV1 setReq call. ## Contracts deployment on parachains Update environment use NEUROWEB_DEVNET/NEUROWEB_TESTNET/NEUROWEB_MAINNET + ```dotenv RPC_NEUROWEB_DEVNET='' EVM_PRIVATE_KEY_NEUROWEB_DEVNET='<0x_ethereum_private_key>' @@ -96,6 +101,7 @@ ACCOUNT_WITH_NEURO_URI_NEUROWEB_DEVNET=''
OriginTrail Parachain Devnet + ```sh npm run deploy:neuroweb_devnet ``` @@ -103,6 +109,7 @@ npm run deploy:neuroweb_devnet
OriginTrail Parachain Testnet + ```sh npm run deploy:neuroweb_testnet ``` @@ -110,6 +117,7 @@ npm run deploy:neuroweb_testnet
OriginTrail Parachain Mainnet + ```sh npm run deploy:neuroweb_mainnet ``` @@ -117,6 +125,7 @@ npm run deploy:neuroweb_mainnet
Gnosis Chiado Dev + ```sh npm run deploy:gnosis_chiado_dev ``` @@ -124,6 +133,7 @@ npm run deploy:gnosis_chiado_dev
Gnosis Chiado Test + ```sh npm run deploy:gnosis_chiado_test ``` @@ -131,12 +141,29 @@ npm run deploy:gnosis_chiado_test
Gnosis Mainnet + ```sh npm run deploy:gnosis_mainnet ```
+Base Sepolia Test + +```sh +npm run deploy:base_sepolia_test +``` + +
+ +Base Mainnet + +```sh +npm run deploy:base_mainnet +``` + +
+ ### Redeploy contract In order to redeploy desired contract, set `deployed` to `false` in `deployments/_contracts.json`. diff --git a/abi/Ask.json b/abi/Ask.json index 24ea9095..53cb3a38 100644 --- a/abi/Ask.json +++ b/abi/Ask.json @@ -26,6 +26,19 @@ "name": "ZeroAddressHub", "type": "error" }, + { + "inputs": [], + "name": "ASK_SCALING_FACTOR", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "askStorage", diff --git a/abi/DelegatorsInfo.json b/abi/DelegatorsInfo.json new file mode 100644 index 00000000..0fae2a9c --- /dev/null +++ b/abi/DelegatorsInfo.json @@ -0,0 +1,991 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "hubAddress", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "msg", + "type": "string" + } + ], + "name": "UnauthorizedAccess", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddressHub", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "indexed": true, + "internalType": "address", + "name": "delegator", + "type": "address" + } + ], + "name": "DelegatorAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "indexed": true, + "internalType": "address", + "name": "delegator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newLastClaimedEpoch", + "type": "uint256" + } + ], + "name": "DelegatorLastClaimedEpochUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "indexed": true, + "internalType": "address", + "name": "delegator", + "type": "address" + } + ], + "name": "DelegatorRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "indexed": true, + "internalType": "address", + "name": "delegator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalRollingRewards", + "type": "uint256" + } + ], + "name": "DelegatorRollingRewardsUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "delegatorKey", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "bool", + "name": "claimed", + "type": "bool" + } + ], + "name": "HasDelegatorClaimedEpochRewardsUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "indexed": true, + "internalType": "address", + "name": "delegator", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "hasEverDelegatedToNode", + "type": "bool" + } + ], + "name": "HasEverDelegatedToNodeUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bool", + "name": "isClaimed", + "type": "bool" + } + ], + "name": "IsOperatorFeeClaimedForEpochUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "indexed": true, + "internalType": "address", + "name": "delegator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + } + ], + "name": "LastStakeHeldEpochUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "NetNodeEpochRewardsSet", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "internalType": "address", + "name": "delegator", + "type": "address" + } + ], + "name": "addDelegator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "internalType": "address", + "name": "delegator", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "addDelegatorRollingRewards", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint72", + "name": "", + "type": "uint72" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "delegatorRollingRewards", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "internalType": "address", + "name": "delegator", + "type": "address" + } + ], + "name": "getDelegatorIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "internalType": "address", + "name": "delegator", + "type": "address" + } + ], + "name": "getDelegatorRollingRewards", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + } + ], + "name": "getDelegators", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "internalType": "address", + "name": "delegator", + "type": "address" + } + ], + "name": "getLastClaimedEpoch", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "internalType": "address", + "name": "delegator", + "type": "address" + } + ], + "name": "getLastStakeHeldEpoch", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + } + ], + "name": "getNetNodeEpochRewards", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint72", + "name": "", + "type": "uint72" + }, + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "hasDelegatorClaimedEpochRewards", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint72", + "name": "", + "type": "uint72" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "hasEverDelegatedToNode", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "hub", + "outputs": [ + { + "internalType": "contract Hub", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint72", + "name": "", + "type": "uint72" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "isDelegatorMap", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "internalType": "address", + "name": "delegator", + "type": "address" + } + ], + "name": "isNodeDelegator", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint72", + "name": "", + "type": "uint72" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "isOperatorFeeClaimedForEpoch", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint72", + "name": "", + "type": "uint72" + } + ], + "name": "lastClaimedDelegatorsRewardsEpoch", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint72", + "name": "", + "type": "uint72" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "lastClaimedEpoch", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint72", + "name": "", + "type": "uint72" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "lastStakeHeldEpoch", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "newAddresses", + "type": "address[]" + } + ], + "name": "migrate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint72", + "name": "", + "type": "uint72" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "netNodeEpochRewards", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint72", + "name": "", + "type": "uint72" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "nodeDelegatorAddresses", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint72", + "name": "", + "type": "uint72" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "nodeDelegatorIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "internalType": "address", + "name": "delegator", + "type": "address" + } + ], + "name": "removeDelegator", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "internalType": "address", + "name": "delegator", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "setDelegatorRollingRewards", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "internalType": "bytes32", + "name": "delegatorKey", + "type": "bytes32" + }, + { + "internalType": "bool", + "name": "claimed", + "type": "bool" + } + ], + "name": "setHasDelegatorClaimedEpochRewards", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "internalType": "address", + "name": "delegator", + "type": "address" + }, + { + "internalType": "bool", + "name": "_hasEverDelegatedToNode", + "type": "bool" + } + ], + "name": "setHasEverDelegatedToNode", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "isClaimed", + "type": "bool" + } + ], + "name": "setIsOperatorFeeClaimedForEpoch", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "internalType": "address", + "name": "delegator", + "type": "address" + }, + { + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + } + ], + "name": "setLastClaimedEpoch", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "internalType": "address", + "name": "delegator", + "type": "address" + }, + { + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + } + ], + "name": "setLastStakeHeldEpoch", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "setNetNodeEpochRewards", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "_status", + "type": "bool" + } + ], + "name": "setStatus", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "status", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + } +] diff --git a/abi/MigratorM1V8.json b/abi/MigratorM1V8.json new file mode 100644 index 00000000..145fdf26 --- /dev/null +++ b/abi/MigratorM1V8.json @@ -0,0 +1,568 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "hubAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "oldHubAddress", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "internalType": "address", + "name": "delegator", + "type": "address" + } + ], + "name": "DelegatorAlreadyMigrated", + "type": "error" + }, + { + "inputs": [], + "name": "DelegatorsMigrationNotInitiated", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "expected", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "received", + "type": "uint96" + } + ], + "name": "InvalidTotalStake", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "msg", + "type": "string" + } + ], + "name": "UnauthorizedAccess", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddressHub", + "type": "error" + }, + { + "inputs": [], + "name": "askStorage", + "outputs": [ + { + "internalType": "contract AskStorage", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint72", + "name": "", + "type": "uint72" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "delegatorMigrated", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "delegatorsMigrationInitiated", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "epochStorageV6", + "outputs": [ + { + "internalType": "contract EpochStorage", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "finalizeDelegatorsMigration", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "hub", + "outputs": [ + { + "internalType": "contract Hub", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "initializeNewContracts", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "initializeOldContracts", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "initiateDelegatorsMigration", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "internalType": "address", + "name": "delegator", + "type": "address" + } + ], + "name": "migrateDelegatorData", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "migratedNodes", + "outputs": [ + { + "internalType": "uint72", + "name": "", + "type": "uint72" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "migratedStake", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint72", + "name": "", + "type": "uint72" + } + ], + "name": "migratedStakes", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "newIdentityStorage", + "outputs": [ + { + "internalType": "contract IdentityStorage", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "newParametersStorage", + "outputs": [ + { + "internalType": "contract ParametersStorage", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "newProfileStorage", + "outputs": [ + { + "internalType": "contract ProfileStorage", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "newShardingTable", + "outputs": [ + { + "internalType": "contract ShardingTable", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "newStakingStorage", + "outputs": [ + { + "internalType": "contract StakingStorage", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint72", + "name": "", + "type": "uint72" + } + ], + "name": "nodeMigrated", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "oldHub", + "outputs": [ + { + "internalType": "contract IOldHub", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "oldIdentityStorage", + "outputs": [ + { + "internalType": "contract IdentityStorage", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "oldMigratedOperatorFees", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "oldNodeOperatorFeesStorage", + "outputs": [ + { + "internalType": "contract IOldNodeOperatorFeesStorage", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint72", + "name": "", + "type": "uint72" + } + ], + "name": "oldNodeStakes", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "oldNodesCount", + "outputs": [ + { + "internalType": "uint72", + "name": "", + "type": "uint72" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "oldOperatorFees", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "oldProfileStorage", + "outputs": [ + { + "internalType": "contract IOldProfileStorage", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "oldServiceAgreementStorageV1", + "outputs": [ + { + "internalType": "contract IOldServiceAgreementStorage", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "oldServiceAgreementStorageV1U1", + "outputs": [ + { + "internalType": "contract IOldServiceAgreementStorage", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "oldStakingStorage", + "outputs": [ + { + "internalType": "contract IOldStakingStorage", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "oldStakingStorageBalance", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "oldTotalStake", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "oldTotalUnpaidRewards", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint72", + "name": "", + "type": "uint72" + } + ], + "name": "operatorMigrated", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "_status", + "type": "bool" + } + ], + "name": "setStatus", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "status", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "token", + "outputs": [ + { + "internalType": "contract Token", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/abi/ParametersStorage.json b/abi/ParametersStorage.json index b1dfd5f9..9bcb2bd0 100644 --- a/abi/ParametersStorage.json +++ b/abi/ParametersStorage.json @@ -84,6 +84,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "maxOperatorFee", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "maximumStake", @@ -201,6 +214,19 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "maxOperatorFee_", + "type": "uint16" + } + ], + "name": "setMaxOperatorFee", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { diff --git a/abi/Profile.json b/abi/Profile.json index c4931393..c1cfc8b2 100644 --- a/abi/Profile.json +++ b/abi/Profile.json @@ -173,6 +173,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "chronos", + "outputs": [ + { + "internalType": "contract Chronos", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { @@ -206,6 +219,19 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [], + "name": "delegatorsInfo", + "outputs": [ + { + "internalType": "contract DelegatorsInfo", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "hub", diff --git a/abi/RandomSampling.json b/abi/RandomSampling.json new file mode 100644 index 00000000..cf400d82 --- /dev/null +++ b/abi/RandomSampling.json @@ -0,0 +1,429 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "hubAddress", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "computedMerkleRoot", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "expectedMerkleRoot", + "type": "bytes32" + } + ], + "name": "MerkleRootMismatchError", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + } + ], + "name": "ProfileDoesntExist", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "msg", + "type": "string" + } + ], + "name": "UnauthorizedAccess", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddressHub", + "type": "error" + }, + { + "inputs": [], + "name": "SCALE18", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "askStorage", + "outputs": [ + { + "internalType": "contract AskStorage", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + } + ], + "name": "calculateNodeScore", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "chronos", + "outputs": [ + { + "internalType": "contract Chronos", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "createChallenge", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "delegatorsInfo", + "outputs": [ + { + "internalType": "contract DelegatorsInfo", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "epochStorage", + "outputs": [ + { + "internalType": "contract EpochStorage", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getActiveProofPeriodStatus", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "activeProofPeriodStartBlock", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "isValid", + "type": "bool" + } + ], + "internalType": "struct RandomSamplingLib.ProofPeriodStatus", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getActiveProofingPeriodDurationInBlocks", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "proofPeriodStartBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "offset", + "type": "uint256" + } + ], + "name": "getHistoricalProofPeriodStartBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "hub", + "outputs": [ + { + "internalType": "contract Hub", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "identityStorage", + "outputs": [ + { + "internalType": "contract IdentityStorage", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "isPendingProofingPeriodDuration", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "knowledgeCollectionStorage", + "outputs": [ + { + "internalType": "contract KnowledgeCollectionStorage", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "parametersStorage", + "outputs": [ + { + "internalType": "contract ParametersStorage", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "profileStorage", + "outputs": [ + { + "internalType": "contract ProfileStorage", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "randomSamplingStorage", + "outputs": [ + { + "internalType": "contract RandomSamplingStorage", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "durationInBlocks", + "type": "uint16" + } + ], + "name": "setProofingPeriodDurationInBlocks", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "_status", + "type": "bool" + } + ], + "name": "setStatus", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "shardingTableStorage", + "outputs": [ + { + "internalType": "contract ShardingTableStorage", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "stakingStorage", + "outputs": [ + { + "internalType": "contract StakingStorage", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "status", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "chunk", + "type": "string" + }, + { + "internalType": "bytes32[]", + "name": "merkleProof", + "type": "bytes32[]" + } + ], + "name": "submitProof", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "updateAndGetActiveProofPeriodStartBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + } +] diff --git a/abi/RandomSamplingStorage.json b/abi/RandomSamplingStorage.json new file mode 100644 index 00000000..cd125f73 --- /dev/null +++ b/abi/RandomSamplingStorage.json @@ -0,0 +1,1744 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "hubAddress", + "type": "address" + }, + { + "internalType": "uint16", + "name": "_proofingPeriodDurationInBlocks", + "type": "uint16" + }, + { + "internalType": "uint256", + "name": "_w1", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_w2", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "msg", + "type": "string" + } + ], + "name": "UnauthorizedAccess", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddressHub", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "activeProofPeriodStartBlock", + "type": "uint256" + } + ], + "name": "ActiveProofPeriodStartBlockSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "scoreAdded", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalScore", + "type": "uint256" + } + ], + "name": "AllNodesEpochScoreAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newScore", + "type": "uint256" + } + ], + "name": "AllNodesEpochScoreSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "delegatorKey", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newDelegatorLastSettledNodeEpochScorePerStake", + "type": "uint256" + } + ], + "name": "DelegatorLastSettledNodeEpochScorePerStakeSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "delegatorKey", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "scoreAdded", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalScore", + "type": "uint256" + } + ], + "name": "EpochNodeDelegatorScoreAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "delegatorKey", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newScore", + "type": "uint256" + } + ], + "name": "EpochNodeDelegatorScoreSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newCount", + "type": "uint256" + } + ], + "name": "EpochNodeValidProofsCountIncremented", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newCount", + "type": "uint256" + } + ], + "name": "EpochNodeValidProofsCountSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "knowledgeCollectionId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "chunkId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "knowledgeCollectionStorageContract", + "type": "address" + }, + { + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "activeProofPeriodStartBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "proofingPeriodDurationInBlocks", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "solved", + "type": "bool" + } + ], + "indexed": false, + "internalType": "struct RandomSamplingLib.Challenge", + "name": "challenge", + "type": "tuple" + } + ], + "name": "NodeChallengeSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "proofPeriodStartBlock", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "scoreAdded", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalScore", + "type": "uint256" + } + ], + "name": "NodeEpochProofPeriodScoreAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "proofPeriodStartBlock", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newScore", + "type": "uint256" + } + ], + "name": "NodeEpochProofPeriodScoreSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "scoreAdded", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalScore", + "type": "uint256" + } + ], + "name": "NodeEpochScoreAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "scorePerStakeToAdd", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalNodeEpochScorePerStake", + "type": "uint256" + } + ], + "name": "NodeEpochScorePerStakeAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newScorePerStake", + "type": "uint256" + } + ], + "name": "NodeEpochScorePerStakeSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newScore", + "type": "uint256" + } + ], + "name": "NodeEpochScoreSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint16", + "name": "oldDurationInBlocks", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "newDurationInBlocks", + "type": "uint16" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "effectiveEpoch", + "type": "uint256" + } + ], + "name": "PendingProofingPeriodDurationReplaced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint16", + "name": "durationInBlocks", + "type": "uint16" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "effectiveEpoch", + "type": "uint256" + } + ], + "name": "ProofingPeriodDurationAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldW1", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newW1", + "type": "uint256" + } + ], + "name": "W1Set", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldW2", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newW2", + "type": "uint256" + } + ], + "name": "W2Set", + "type": "event" + }, + { + "inputs": [], + "name": "CHUNK_BYTE_SIZE", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "durationInBlocks", + "type": "uint16" + }, + { + "internalType": "uint256", + "name": "effectiveEpoch", + "type": "uint256" + } + ], + "name": "addProofingPeriodDuration", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "score", + "type": "uint256" + } + ], + "name": "addToAllNodesEpochScore", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "internalType": "bytes32", + "name": "delegatorKey", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "score", + "type": "uint256" + } + ], + "name": "addToEpochNodeDelegatorScore", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "proofPeriodStartBlock", + "type": "uint256" + }, + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "internalType": "uint256", + "name": "score", + "type": "uint256" + } + ], + "name": "addToNodeEpochProofPeriodScore", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "internalType": "uint256", + "name": "score", + "type": "uint256" + } + ], + "name": "addToNodeEpochScore", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "internalType": "uint256", + "name": "scorePerStakeToAdd", + "type": "uint256" + } + ], + "name": "addToNodeEpochScorePerStake", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "allNodesEpochScore", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "chronos", + "outputs": [ + { + "internalType": "contract Chronos", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint72", + "name": "", + "type": "uint72" + }, + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "delegatorLastSettledNodeEpochScorePerStake", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint72", + "name": "", + "type": "uint72" + }, + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "name": "epochNodeDelegatorScore", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint72", + "name": "", + "type": "uint72" + } + ], + "name": "epochNodeValidProofsCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getActiveProofPeriodStartBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + } + ], + "name": "getAllNodesEpochScore", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "internalType": "bytes32", + "name": "delegatorKey", + "type": "bytes32" + } + ], + "name": "getDelegatorLastSettledNodeEpochScorePerStake", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "internalType": "bytes32", + "name": "delegatorKey", + "type": "bytes32" + } + ], + "name": "getEpochNodeDelegatorScore", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + } + ], + "name": "getEpochNodeValidProofsCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + } + ], + "name": "getEpochProofingPeriodDurationInBlocks", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getLatestProofingPeriodDurationEffectiveEpoch", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getLatestProofingPeriodDurationInBlocks", + "outputs": [ + { + "internalType": "uint16", + "name": "", + "type": "uint16" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + } + ], + "name": "getNodeChallenge", + "outputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "knowledgeCollectionId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "chunkId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "knowledgeCollectionStorageContract", + "type": "address" + }, + { + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "activeProofPeriodStartBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "proofingPeriodDurationInBlocks", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "solved", + "type": "bool" + } + ], + "internalType": "struct RandomSamplingLib.Challenge", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "proofPeriodStartBlock", + "type": "uint256" + } + ], + "name": "getNodeEpochProofPeriodScore", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + } + ], + "name": "getNodeEpochScore", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + } + ], + "name": "getNodeEpochScorePerStake", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "getProofingPeriodDurationFromIndex", + "outputs": [ + { + "components": [ + { + "internalType": "uint16", + "name": "durationInBlocks", + "type": "uint16" + }, + { + "internalType": "uint256", + "name": "effectiveEpoch", + "type": "uint256" + } + ], + "internalType": "struct RandomSamplingLib.ProofingPeriodDuration", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getProofingPeriodDurationsLength", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getW1", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getW2", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "hub", + "outputs": [ + { + "internalType": "contract Hub", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + } + ], + "name": "incrementEpochNodeValidProofsCount", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint72", + "name": "", + "type": "uint72" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "nodeEpochProofPeriodScore", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint72", + "name": "", + "type": "uint72" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "nodeEpochScore", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint72", + "name": "", + "type": "uint72" + } + ], + "name": "nodeEpochScorePerStake", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint72", + "name": "", + "type": "uint72" + } + ], + "name": "nodesChallenges", + "outputs": [ + { + "internalType": "uint256", + "name": "knowledgeCollectionId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "chunkId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "knowledgeCollectionStorageContract", + "type": "address" + }, + { + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "activeProofPeriodStartBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "proofingPeriodDurationInBlocks", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "solved", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "proofingPeriodDurations", + "outputs": [ + { + "internalType": "uint16", + "name": "durationInBlocks", + "type": "uint16" + }, + { + "internalType": "uint256", + "name": "effectiveEpoch", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "durationInBlocks", + "type": "uint16" + }, + { + "internalType": "uint256", + "name": "effectiveEpoch", + "type": "uint256" + } + ], + "name": "replacePendingProofingPeriodDuration", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "newActiveProofPeriodStartBlock", + "type": "uint256" + } + ], + "name": "setActiveProofPeriodStartBlock", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "score", + "type": "uint256" + } + ], + "name": "setAllNodesEpochScore", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "internalType": "bytes32", + "name": "delegatorKey", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "newNodeEpochScorePerStake", + "type": "uint256" + } + ], + "name": "setDelegatorLastSettledNodeEpochScorePerStake", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "internalType": "bytes32", + "name": "delegatorKey", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "score", + "type": "uint256" + } + ], + "name": "setEpochNodeDelegatorScore", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "internalType": "uint256", + "name": "count", + "type": "uint256" + } + ], + "name": "setEpochNodeValidProofsCount", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "knowledgeCollectionId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "chunkId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "knowledgeCollectionStorageContract", + "type": "address" + }, + { + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "activeProofPeriodStartBlock", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "proofingPeriodDurationInBlocks", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "solved", + "type": "bool" + } + ], + "internalType": "struct RandomSamplingLib.Challenge", + "name": "challenge", + "type": "tuple" + } + ], + "name": "setNodeChallenge", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "proofPeriodStartBlock", + "type": "uint256" + }, + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "internalType": "uint256", + "name": "score", + "type": "uint256" + } + ], + "name": "setNodeEpochProofPeriodScore", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "internalType": "uint256", + "name": "score", + "type": "uint256" + } + ], + "name": "setNodeEpochScore", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "internalType": "uint256", + "name": "scorePerStake", + "type": "uint256" + } + ], + "name": "setNodeEpochScorePerStake", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "_status", + "type": "bool" + } + ], + "name": "setStatus", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_w1", + "type": "uint256" + } + ], + "name": "setW1", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_w2", + "type": "uint256" + } + ], + "name": "setW2", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "status", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "w1", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "w2", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/abi/Staking.json b/abi/Staking.json index 2e08d4d3..14f5ac5b 100644 --- a/abi/Staking.json +++ b/abi/Staking.json @@ -164,30 +164,61 @@ "name": "ZeroTokenAmount", "type": "error" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint72", + "name": "fromIdentityId", + "type": "uint72" + }, + { + "indexed": true, + "internalType": "uint72", + "name": "toIdentityId", + "type": "uint72" + }, + { + "indexed": true, + "internalType": "address", + "name": "delegator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "StakeRedelegated", + "type": "event" + }, { "inputs": [], - "name": "askContract", + "name": "SCALE18", "outputs": [ { - "internalType": "contract Ask", + "internalType": "uint256", "name": "", - "type": "address" + "type": "uint256" } ], "stateMutability": "view", "type": "function" }, { - "inputs": [ + "inputs": [], + "name": "askContract", + "outputs": [ { - "internalType": "uint72", - "name": "identityId", - "type": "uint72" + "internalType": "contract Ask", + "name": "", + "type": "address" } ], - "name": "cancelOperatorFeeWithdrawal", - "outputs": [], - "stateMutability": "nonpayable", + "stateMutability": "view", "type": "function" }, { @@ -196,9 +227,19 @@ "internalType": "uint72", "name": "identityId", "type": "uint72" + }, + { + "internalType": "uint256[]", + "name": "epochs", + "type": "uint256[]" + }, + { + "internalType": "address[]", + "name": "delegators", + "type": "address[]" } ], - "name": "cancelWithdrawal", + "name": "batchClaimDelegatorRewards", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -209,14 +250,9 @@ "internalType": "uint72", "name": "identityId", "type": "uint72" - }, - { - "internalType": "uint96", - "name": "rewardAmount", - "type": "uint96" } ], - "name": "distributeRewards", + "name": "cancelOperatorFeeWithdrawal", "outputs": [], "stateMutability": "nonpayable", "type": "function" @@ -229,22 +265,22 @@ "type": "uint72" } ], - "name": "finalizeOperatorFeeWithdrawal", + "name": "cancelWithdrawal", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { - "inputs": [ + "inputs": [], + "name": "chronos", + "outputs": [ { - "internalType": "uint72", - "name": "identityId", - "type": "uint72" + "internalType": "contract Chronos", + "name": "", + "type": "address" } ], - "name": "finalizeWithdrawal", - "outputs": [], - "stateMutability": "nonpayable", + "stateMutability": "view", "type": "function" }, { @@ -254,57 +290,43 @@ "name": "identityId", "type": "uint72" }, + { + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, { "internalType": "address", "name": "delegator", "type": "address" } ], - "name": "getDelegatorStats", + "name": "claimDelegatorRewards", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "delegatorsInfo", "outputs": [ { - "internalType": "uint96", - "name": "", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "", - "type": "uint96" - }, - { - "internalType": "uint96", + "internalType": "contract DelegatorsInfo", "name": "", - "type": "uint96" + "type": "address" } ], "stateMutability": "view", "type": "function" }, { - "inputs": [ - { - "internalType": "uint72", - "name": "identityId", - "type": "uint72" - } - ], - "name": "getNodeStats", + "inputs": [], + "name": "epochStorage", "outputs": [ { - "internalType": "uint96", - "name": "", - "type": "uint96" - }, - { - "internalType": "uint96", + "internalType": "contract EpochStorage", "name": "", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "", - "type": "uint96" + "type": "address" } ], "stateMutability": "view", @@ -318,25 +340,9 @@ "type": "uint72" } ], - "name": "getOperatorFeeStats", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "view", + "name": "finalizeOperatorFeeWithdrawal", + "outputs": [], + "stateMutability": "nonpayable", "type": "function" }, { @@ -347,25 +353,9 @@ "type": "uint72" } ], - "name": "getOperatorStats", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "view", + "name": "finalizeWithdrawal", + "outputs": [], + "stateMutability": "nonpayable", "type": "function" }, { @@ -440,6 +430,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "randomSamplingStorage", + "outputs": [ + { + "internalType": "contract RandomSamplingStorage", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { @@ -556,40 +559,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [ - { - "internalType": "uint72", - "name": "identityId", - "type": "uint72" - }, - { - "internalType": "bytes32", - "name": "delegatorKey", - "type": "bytes32" - } - ], - "name": "simulateStakeInfoUpdate", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [ { diff --git a/abi/StakingKPI.json b/abi/StakingKPI.json new file mode 100644 index 00000000..09727f93 --- /dev/null +++ b/abi/StakingKPI.json @@ -0,0 +1,350 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "hubAddress", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + } + ], + "name": "ProfileDoesntExist", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "msg", + "type": "string" + } + ], + "name": "UnauthorizedAccess", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddressHub", + "type": "error" + }, + { + "inputs": [], + "name": "SCALE18", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "delegatorsInfo", + "outputs": [ + { + "internalType": "contract DelegatorsInfo", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "epochStorage", + "outputs": [ + { + "internalType": "contract EpochStorage", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + }, + { + "internalType": "address", + "name": "delegator", + "type": "address" + } + ], + "name": "getDelegatorReward", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "internalType": "address", + "name": "delegator", + "type": "address" + } + ], + "name": "getDelegatorStats", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "internalType": "uint256", + "name": "epoch", + "type": "uint256" + } + ], + "name": "getNetNodeRewards", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + } + ], + "name": "getNodeStats", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + } + ], + "name": "getOperatorFeeStats", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + } + ], + "name": "getOperatorStats", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "hub", + "outputs": [ + { + "internalType": "contract Hub", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "identityStorage", + "outputs": [ + { + "internalType": "contract IdentityStorage", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "parametersStorage", + "outputs": [ + { + "internalType": "contract ParametersStorage", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "profileStorage", + "outputs": [ + { + "internalType": "contract ProfileStorage", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "randomSamplingStorage", + "outputs": [ + { + "internalType": "contract RandomSamplingStorage", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "_status", + "type": "bool" + } + ], + "name": "setStatus", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "stakingStorage", + "outputs": [ + { + "internalType": "contract StakingStorage", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "status", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + } +] diff --git a/contracts/Ask.sol b/contracts/Ask.sol index 11df8577..f550f61f 100644 --- a/contracts/Ask.sol +++ b/contracts/Ask.sol @@ -16,6 +16,8 @@ contract Ask is INamed, IVersioned, ContractStatus, IInitializable { string private constant _NAME = "Ask"; string private constant _VERSION = "1.0.0"; + uint256 public constant ASK_SCALING_FACTOR = 1e18; + AskStorage public askStorage; ShardingTableStorage public shardingTableStorage; ParametersStorage public parametersStorage; @@ -76,9 +78,9 @@ contract Ask is INamed, IVersioned, ContractStatus, IInitializable { } stake = stake > maximumStake ? maximumStake : stake; - uint256 nodeAskScaled = uint256(ps.getAsk(nodeIdentityId)) * 1e18; + uint256 nodeAskScaled = uint256(ps.getAsk(nodeIdentityId)) * ASK_SCALING_FACTOR; if (nodeAskScaled >= askLowerBound && nodeAskScaled <= askUpperBound) { - newWeightedActiveAskSum += (nodeAskScaled / 1e18) * stake; + newWeightedActiveAskSum += (nodeAskScaled / ASK_SCALING_FACTOR) * stake; newTotalActiveStake += stake; } } diff --git a/contracts/KnowledgeCollection.sol b/contracts/KnowledgeCollection.sol index a6546b51..45f7ab06 100644 --- a/contracts/KnowledgeCollection.sol +++ b/contracts/KnowledgeCollection.sol @@ -98,7 +98,6 @@ contract KnowledgeCollection is INamed, IVersioned, ContractStatus, IInitializab _verifySignatures(identityIds, ECDSA.toEthSignedMessageHash(merkleRoot), r, vs); KnowledgeCollectionStorage kcs = knowledgeCollectionStorage; - EpochStorage es = epochStorage; uint40 currentEpoch = uint40(chronos.getCurrentEpoch()); uint256 id = kcs.createKnowledgeCollection( @@ -107,16 +106,21 @@ contract KnowledgeCollection is INamed, IVersioned, ContractStatus, IInitializab merkleRoot, knowledgeAssetsAmount, byteSize, - currentEpoch + 1, - currentEpoch + epochs + 1, + currentEpoch, + currentEpoch + epochs, tokenAmount, isImmutable ); - _validateTokenAmount(byteSize, epochs, tokenAmount, true); + // Validate that the provided token amount is sufficient + // false argument suggests that the user who published the KC pays for the number of epochs + _validateTokenAmount(byteSize, epochs, tokenAmount, false); + + // Distribute time-weight tokenAmount across current, full, and final fractional epochs + _distributeTokens(tokenAmount, epochs, currentEpoch); - es.addTokensToEpochRange(1, currentEpoch, currentEpoch + epochs + 1, tokenAmount); - es.addEpochProducedKnowledgeValue(publisherNodeIdentityId, currentEpoch, tokenAmount); + // Record the knowledge value produced by the publisher in the current epoch + epochStorage.addEpochProducedKnowledgeValue(publisherNodeIdentityId, currentEpoch, tokenAmount); _addTokens(tokenAmount, paymaster); @@ -323,4 +327,55 @@ contract KnowledgeCollection is INamed, IVersioned, ContractStatus, IInitializab } } } + + /** + * @dev Distributes tokens across epochs using time-weighted allocation + * Allocates tokens proportionally based on time remaining in current epoch and distributes + * the remainder across full epochs and final fractional epoch + * @param tokenAmount Total amount of tokens to distribute across epochs + * @param epochs Number of epochs to distribute tokens over + * @param currentEpoch The current epoch number where distribution starts + */ + function _distributeTokens(uint96 tokenAmount, uint256 epochs, uint40 currentEpoch) internal { + require(epochs > 0, "epochs must be > 0"); + + uint256 epochLengthInSeconds = chronos.epochLength(); + uint256 timeRemainingInCurrentEpoch = chronos.timeUntilNextEpoch(); // seconds remaining in current epoch + uint256 baseTokensPerFullEpoch = tokenAmount / epochs; // nominal amount for a full epoch + uint256 currentEpochAllocation = (baseTokensPerFullEpoch * timeRemainingInCurrentEpoch) / epochLengthInSeconds; + uint256 finalEpochAllocation = baseTokensPerFullEpoch - currentEpochAllocation; // goes to the final fractional epoch + uint256 numberOfFullEpochs = epochs - 1; // number of full middle epochs + uint256 totalTokensForFullEpochs = baseTokensPerFullEpoch * numberOfFullEpochs; + + // Add any rounding remainder to the final epoch so total == tokenAmount + uint256 totalAllocated = currentEpochAllocation + totalTokensForFullEpochs + finalEpochAllocation; + if (totalAllocated < tokenAmount) { + finalEpochAllocation += tokenAmount - totalAllocated; + } + + // 1) Current (fractional) epoch + if (currentEpochAllocation > 0) { + epochStorage.addTokensToEpochRange(1, currentEpoch, currentEpoch, uint96(currentEpochAllocation)); + } + + // 2) Full epochs between current and final + if (numberOfFullEpochs > 0 && totalTokensForFullEpochs > 0) { + epochStorage.addTokensToEpochRange( + 1, + currentEpoch + 1, + currentEpoch + uint40(numberOfFullEpochs), + uint96(totalTokensForFullEpochs) + ); + } + + // 3) Final (fractional) epoch + if (finalEpochAllocation > 0) { + epochStorage.addTokensToEpochRange( + 1, + currentEpoch + uint40(epochs), + currentEpoch + uint40(epochs), + uint96(finalEpochAllocation) + ); + } + } } diff --git a/contracts/Profile.sol b/contracts/Profile.sol index ba4ef87b..f76040e4 100644 --- a/contracts/Profile.sol +++ b/contracts/Profile.sol @@ -8,6 +8,8 @@ import {IdentityStorage} from "./storage/IdentityStorage.sol"; import {ParametersStorage} from "./storage/ParametersStorage.sol"; import {ProfileStorage} from "./storage/ProfileStorage.sol"; import {WhitelistStorage} from "./storage/WhitelistStorage.sol"; +import {Chronos} from "./storage/Chronos.sol"; +import {DelegatorsInfo} from "./storage/DelegatorsInfo.sol"; import {ContractStatus} from "./abstract/ContractStatus.sol"; import {IInitializable} from "./interfaces/IInitializable.sol"; import {INamed} from "./interfaces/INamed.sol"; @@ -26,6 +28,8 @@ contract Profile is INamed, IVersioned, ContractStatus, IInitializable { ParametersStorage public parametersStorage; ProfileStorage public profileStorage; WhitelistStorage public whitelistStorage; + Chronos public chronos; + DelegatorsInfo public delegatorsInfo; // solhint-disable-next-line no-empty-blocks constructor(address hubAddress) ContractStatus(hubAddress) {} @@ -57,6 +61,8 @@ contract Profile is INamed, IVersioned, ContractStatus, IInitializable { parametersStorage = ParametersStorage(hub.getContractAddress("ParametersStorage")); profileStorage = ProfileStorage(hub.getContractAddress("ProfileStorage")); whitelistStorage = WhitelistStorage(hub.getContractAddress("WhitelistStorage")); + chronos = Chronos(hub.getContractAddress("Chronos")); + delegatorsInfo = DelegatorsInfo(hub.getContractAddress("DelegatorsInfo")); } function name() external pure virtual override returns (string memory) { @@ -99,7 +105,7 @@ contract Profile is INamed, IVersioned, ContractStatus, IInitializable { if (ps.nodeIdsList(nodeId)) { revert ProfileLib.NodeIdAlreadyExists(nodeId); } - if (initialOperatorFee > 10000) { + if (initialOperatorFee > parametersStorage.maxOperatorFee()) { revert ProfileLib.OperatorFeeOutOfRange(initialOperatorFee); } uint72 identityId = id.createIdentity(msg.sender, adminWallet); @@ -125,20 +131,35 @@ contract Profile is INamed, IVersioned, ContractStatus, IInitializable { } function updateOperatorFee(uint72 identityId, uint16 newOperatorFee) external onlyAdmin(identityId) { - if (newOperatorFee > 10000) { + uint256 currentEpoch = chronos.getCurrentEpoch(); + + if (currentEpoch > 1) { + // All operator fees for previous epochs must be calculated and claimed before updating the operator fee + if (!delegatorsInfo.isOperatorFeeClaimedForEpoch(identityId, currentEpoch - 1)) { + revert( + "Cannot update operatorFee if operatorFee has not been calculated and claimed for previous epochs" + ); + } + } + + if (newOperatorFee > parametersStorage.maxOperatorFee()) { revert ProfileLib.InvalidOperatorFee(); } ProfileStorage ps = profileStorage; + uint256 epochStart = chronos.timestampForEpoch(currentEpoch); + uint256 epochLength = chronos.epochLength(); + uint256 nextEpochStart = epochStart + epochLength; + + uint256 effectiveStart = block.timestamp <= epochStart + epochLength / 2 + ? nextEpochStart + : nextEpochStart + epochLength; + if (ps.isOperatorFeeChangePending(identityId)) { - ps.replacePendingOperatorFee( - identityId, - newOperatorFee, - block.timestamp + parametersStorage.operatorFeeUpdateDelay() - ); + ps.replacePendingOperatorFee(identityId, newOperatorFee, effectiveStart); } else { - ps.addOperatorFee(identityId, newOperatorFee, block.timestamp + parametersStorage.operatorFeeUpdateDelay()); + ps.addOperatorFee(identityId, newOperatorFee, effectiveStart); } } diff --git a/contracts/RandomSampling.sol b/contracts/RandomSampling.sol new file mode 100644 index 00000000..d05bb2ac --- /dev/null +++ b/contracts/RandomSampling.sol @@ -0,0 +1,540 @@ +// SPDX-License-Identifier: Apache-2.0 + +pragma solidity ^0.8.20; + +import {INamed} from "./interfaces/INamed.sol"; +import {IVersioned} from "./interfaces/IVersioned.sol"; +import {ContractStatus} from "./abstract/ContractStatus.sol"; +import {IInitializable} from "./interfaces/IInitializable.sol"; +import {RandomSamplingLib} from "./libraries/RandomSamplingLib.sol"; +import {ProfileLib} from "./libraries/ProfileLib.sol"; +import {IdentityStorage} from "./storage/IdentityStorage.sol"; +import {RandomSamplingStorage} from "./storage/RandomSamplingStorage.sol"; +import {KnowledgeCollectionStorage} from "./storage/KnowledgeCollectionStorage.sol"; +import {StakingStorage} from "./storage/StakingStorage.sol"; +import {ProfileStorage} from "./storage/ProfileStorage.sol"; +import {EpochStorage} from "./storage/EpochStorage.sol"; +import {Chronos} from "./storage/Chronos.sol"; +import {AskStorage} from "./storage/AskStorage.sol"; +import {DelegatorsInfo} from "./storage/DelegatorsInfo.sol"; +import {ParametersStorage} from "./storage/ParametersStorage.sol"; +import {ShardingTableStorage} from "./storage/ShardingTableStorage.sol"; +import {ICustodian} from "./interfaces/ICustodian.sol"; +import {HubLib} from "./libraries/HubLib.sol"; + +contract RandomSampling is INamed, IVersioned, ContractStatus, IInitializable { + string private constant _NAME = "RandomSampling"; + string private constant _VERSION = "1.0.0"; + uint256 public constant SCALE18 = 1e18; + + IdentityStorage public identityStorage; + RandomSamplingStorage public randomSamplingStorage; + KnowledgeCollectionStorage public knowledgeCollectionStorage; + StakingStorage public stakingStorage; + ProfileStorage public profileStorage; + EpochStorage public epochStorage; + Chronos public chronos; + AskStorage public askStorage; + DelegatorsInfo public delegatorsInfo; + ParametersStorage public parametersStorage; + ShardingTableStorage public shardingTableStorage; + + error MerkleRootMismatchError(bytes32 computedMerkleRoot, bytes32 expectedMerkleRoot); + + /** + * @dev Constructor initializes the contract with essential parameters for random sampling + * Only called once during deployment + * @param hubAddress Address of the Hub contract for access control + */ + constructor(address hubAddress) ContractStatus(hubAddress) {} + + modifier profileExists(uint72 identityId) { + _checkProfileExists(identityId); + _; + } + + // @dev Only transactions by HubController owner or one of the owners of the MultiSig Wallet + modifier onlyOwnerOrMultiSigOwner() { + _checkOwnerOrMultiSigOwner(); + _; + } + + /** + * @dev Initializes the contract by connecting to all required Hub dependencies + * Called once during deployment to set up contract references for storage and computation + * Only the Hub can call this function + */ + function initialize() public onlyHub { + identityStorage = IdentityStorage(hub.getContractAddress("IdentityStorage")); + randomSamplingStorage = RandomSamplingStorage(hub.getContractAddress("RandomSamplingStorage")); + knowledgeCollectionStorage = KnowledgeCollectionStorage( + hub.getAssetStorageAddress("KnowledgeCollectionStorage") + ); + stakingStorage = StakingStorage(hub.getContractAddress("StakingStorage")); + profileStorage = ProfileStorage(hub.getContractAddress("ProfileStorage")); + epochStorage = EpochStorage(hub.getContractAddress("EpochStorageV8")); + chronos = Chronos(hub.getContractAddress("Chronos")); + askStorage = AskStorage(hub.getContractAddress("AskStorage")); + delegatorsInfo = DelegatorsInfo(hub.getContractAddress("DelegatorsInfo")); + parametersStorage = ParametersStorage(hub.getContractAddress("ParametersStorage")); + shardingTableStorage = ShardingTableStorage(hub.getContractAddress("ShardingTableStorage")); + } + + /** + * @dev Returns the name of this contract + * Used for contract identification and versioning + */ + function name() external pure virtual override returns (string memory) { + return _NAME; + } + + /** + * @dev Returns the version of this contract + * Used for contract identification and versioning + */ + function version() external pure virtual override returns (string memory) { + return _VERSION; + } + + /** + * @dev Checks if there is a pending proofing period duration that hasn't taken effect yet + * @return True if there is a pending duration change, false otherwise + */ + function isPendingProofingPeriodDuration() public view returns (bool) { + return chronos.getCurrentEpoch() < randomSamplingStorage.getLatestProofingPeriodDurationEffectiveEpoch(); + } + + /** + * @dev Sets the duration of proofing periods in blocks with a one-epoch delay + * Only contracts registered in the Hub can call this function + * If a pending change exists, replaces it; otherwise adds a new duration + * Changes take effect in the next epoch to ensure smooth transitions + * @param durationInBlocks New proofing period duration in blocks (must be > 0) + */ + function setProofingPeriodDurationInBlocks(uint16 durationInBlocks) external onlyOwnerOrMultiSigOwner { + require(durationInBlocks > 0, "Duration in blocks must be greater than 0"); + + // Calculate the effective epoch (current epoch + delay) + uint256 effectiveEpoch = chronos.getCurrentEpoch() + 1; + + // Check if there's a pending change + if (isPendingProofingPeriodDuration()) { + randomSamplingStorage.replacePendingProofingPeriodDuration(durationInBlocks, effectiveEpoch); + } else { + randomSamplingStorage.addProofingPeriodDuration(durationInBlocks, effectiveEpoch); + } + } + + /** + * @dev Creates a new challenge for the calling node in the current proofing period + * Caller must have a registered profile and cannot have an active unsolved challenge + * Generates a random knowledge collection and chunk to be proven + * Can only create one challenge per proofing period + */ + function createChallenge() external profileExists(identityStorage.getIdentityId(msg.sender)) { + uint72 identityId = identityStorage.getIdentityId(msg.sender); + + RandomSamplingLib.Challenge memory nodeChallenge = randomSamplingStorage.getNodeChallenge(identityId); + + if (nodeChallenge.activeProofPeriodStartBlock == updateAndGetActiveProofPeriodStartBlock()) { + // Revert if node has already solved the challenge for this period + if (nodeChallenge.solved) { + revert("The challenge for this proof period has already been solved"); + } + + // Revert if a challenge for this node exists but has not been solved yet + if (nodeChallenge.knowledgeCollectionId != 0) { + revert("An unsolved challenge already exists for this node in the current proof period"); + } + } + + // Generate a new challenge + RandomSamplingLib.Challenge memory challenge = _generateChallenge(msg.sender); + + // Store the new challenge in the storage contract + randomSamplingStorage.setNodeChallenge(identityId, challenge); + } + + /** + * @dev Submits proof for an active challenge to earn score used for later reward calculation + * Validates the submitted chunk and merkle proof against the expected Merkle root + * On successful proof: marks challenge as solved, increments valid proofs count, + * calculates and adds node score, and updates epoch scoring data + * @param chunk The data chunk being proven (must match challenge requirements) + * @param merkleProof Array of hashes for Merkle proof verification + */ + function submitProof( + string memory chunk, + bytes32[] calldata merkleProof + ) external profileExists(identityStorage.getIdentityId(msg.sender)) { + // Get node identityId + uint72 identityId = identityStorage.getIdentityId(msg.sender); + + // Get node challenge + RandomSamplingLib.Challenge memory challenge = randomSamplingStorage.getNodeChallenge(identityId); + + if (challenge.solved) { + revert("This challenge has already been solved"); + } + + uint256 activeProofPeriodStartBlock = updateAndGetActiveProofPeriodStartBlock(); + + // verify that the challengeId matches the current challenge + if (challenge.activeProofPeriodStartBlock != activeProofPeriodStartBlock) { + revert("This challenge is no longer active"); + } + + // Construct the merkle root from chunk and merkleProof + bytes32 computedMerkleRoot = _computeMerkleRootFromProof(chunk, challenge.chunkId, merkleProof); + + // Get the expected merkle root for this challenge + bytes32 expectedMerkleRoot = knowledgeCollectionStorage.getLatestMerkleRoot(challenge.knowledgeCollectionId); + + // Verify the submitted root matches + if (computedMerkleRoot == expectedMerkleRoot) { + // Mark as correct submission and add points to the node + challenge.solved = true; + randomSamplingStorage.setNodeChallenge(identityId, challenge); + + uint256 epoch = chronos.getCurrentEpoch(); + randomSamplingStorage.incrementEpochNodeValidProofsCount(epoch, identityId); + uint256 score18 = calculateNodeScore(identityId); + randomSamplingStorage.addToNodeEpochProofPeriodScore( + epoch, + activeProofPeriodStartBlock, + identityId, + score18 + ); + randomSamplingStorage.addToNodeEpochScore(epoch, identityId, score18); + randomSamplingStorage.addToAllNodesEpochScore(epoch, score18); + + // Calculate and add to nodeEpochScorePerStake + uint96 totalNodeStake = stakingStorage.getNodeStake(identityId); + if (totalNodeStake > 0) { + uint256 nodeScorePerStake36 = (score18 * SCALE18) / totalNodeStake; + randomSamplingStorage.addToNodeEpochScorePerStake(epoch, identityId, nodeScorePerStake36); + } + } else { + revert MerkleRootMismatchError(computedMerkleRoot, expectedMerkleRoot); + } + } + + /** + * @dev Internal function to compute Merkle root from a chunk and its proof + * Reconstructs the Merkle tree root by hashing the chunk with its ID and + * traversing up the tree using the provided proof hashes + * Uses standard Merkle tree construction where smaller hash goes left + * @param chunk The data chunk to verify + * @param chunkId Unique identifier for the chunk position + * @param merkleProof Array of sibling hashes for tree traversal + * @return computedRoot The computed Merkle root hash + */ + function _computeMerkleRootFromProof( + string memory chunk, + uint256 chunkId, + bytes32[] calldata merkleProof + ) internal pure returns (bytes32) { + bytes32 computedHash = keccak256(abi.encodePacked(chunk, chunkId)); + + for (uint256 i = 0; i < merkleProof.length; ) { + if (computedHash < merkleProof[i]) { + computedHash = keccak256(abi.encodePacked(computedHash, merkleProof[i])); + } else { + computedHash = keccak256(abi.encodePacked(merkleProof[i], computedHash)); + } + + unchecked { + i++; + } + } + + return computedHash; + } + + /** + * @dev Internal function to generate a new random challenge for a node + * Uses blockchain properties (block hash, difficulty, timestamp, gas price) for randomness + * Selects a random active knowledge collection and chunk within it + * Creates challenge with current epoch and active proof period information + * @param originalSender The original caller address for randomness seed + * @return challenge The generated challenge struct + */ + function _generateChallenge(address originalSender) internal returns (RandomSamplingLib.Challenge memory) { + uint256 knowledgeCollectionsCount = knowledgeCollectionStorage.getLatestKnowledgeCollectionId(); + if (knowledgeCollectionsCount == 0) { + revert("No knowledge collections exist"); + } + + bytes32 pseudoRandomVariable = keccak256( + abi.encodePacked( + block.difficulty, + blockhash(block.number - ((block.difficulty % 256) + 1)), // +1 to avoid blockhash(block.number) situation + originalSender, + block.timestamp, + tx.gasprice, + uint8(1) // sector = 1 by default + ) + ); + uint256 currentEpoch = chronos.getCurrentEpoch(); + + // Optimized binary search approach for finding active knowledge collection + uint256 knowledgeCollectionId = _findActiveKnowledgeCollection( + pseudoRandomVariable, + 1, + knowledgeCollectionsCount, + currentEpoch + ); + + if (knowledgeCollectionId == 0) { + revert("Failed to find a knowledge collection that is active in the current epoch"); + } + + uint88 kcByteSize = knowledgeCollectionStorage.getByteSize(knowledgeCollectionId); + if (kcByteSize == 0) { + revert("Knowledge collection byte size is 0"); + } + + uint256 chunkId; + uint256 chunkByteSize = randomSamplingStorage.CHUNK_BYTE_SIZE(); + // KC with byteSize < chunkByteSize will always have chunkId = 0 + if (kcByteSize > chunkByteSize) { + chunkId = uint256(pseudoRandomVariable) % (kcByteSize / chunkByteSize); + } + + return + RandomSamplingLib.Challenge( + knowledgeCollectionId, + chunkId, + address(knowledgeCollectionStorage), + currentEpoch, + updateAndGetActiveProofPeriodStartBlock(), + getActiveProofingPeriodDurationInBlocks(), + false + ); + } + + /** + * @dev Internal function to find an active knowledge collection using breadth-first search + * Uses BFS with a queue-based approach to efficiently search for collections that are + * still active (current epoch <= collection's end epoch) + * Splits ranges recursively and uses randomness to select from each range + * Limits iterations to prevent infinite loops and ensures gas efficiency + * @param randomSeed Random seed for picking a collection from current range + * @param start Start of the range (inclusive) - collection ID range to search + * @param end End of the range (inclusive) - collection ID range to search + * @param currentEpoch Current epoch to check collection activity against + * @return knowledgeCollectionId ID of an active knowledge collection, or 0 if none found + */ + function _findActiveKnowledgeCollection( + bytes32 randomSeed, + uint256 start, + uint256 end, + uint256 currentEpoch + ) internal view returns (uint256) { + // Queue using fixed array - [start1, end1, start2, end2, ...] + uint256[100] memory queue; // Can hold 50 ranges max + uint8 queueStart = 0; // Front of queue + uint8 queueEnd = 0; // Back of queue + + // Push initial range + queue[queueEnd++] = start; + queue[queueEnd++] = end; + + bytes32 currentRandom = randomSeed; + uint8 iterations = 0; + + while (queueStart < queueEnd && iterations < 50) { + // Pop range from front of queue (BFS behavior) + uint256 currentStart = queue[queueStart++]; + uint256 currentEnd = queue[queueStart++]; + + // Pick random collection from current range + uint256 randomKcId = currentStart + (uint256(currentRandom) % (currentEnd - currentStart + 1)); + + // Check if this collection is active + if (currentEpoch <= knowledgeCollectionStorage.getEndEpoch(randomKcId)) { + return randomKcId; + } + + // If single element and not active, continue to next range + if (currentStart == currentEnd) { + currentRandom = keccak256(abi.encodePacked(currentRandom)); + unchecked { + iterations++; + } + continue; + } + + // Split range and push both halves to back of queue (BFS order) + uint256 mid = currentStart + (currentEnd - currentStart) / 2; + + if (queueEnd < 96) { + // Leave room for both ranges + // Always push left half first, then right half (consistent BFS) + if (currentStart <= mid) { + queue[queueEnd++] = currentStart; + queue[queueEnd++] = mid; + } + if (mid + 1 <= currentEnd) { + queue[queueEnd++] = mid + 1; + queue[queueEnd++] = currentEnd; + } + } + + currentRandom = keccak256(abi.encodePacked(currentRandom)); + unchecked { + iterations++; + } + } + + return 0; // No active collection found + } + + /** + * @dev Calculates the node score based on stake, ask price, and publishing activity + * Score = nodeStakeFactor + nodeAskFactor + nodePublishingFactor + * + * nodeStakeFactor: 2 * (nodeStake / maxStake)^2 - rewards higher stake + * nodeAskFactor: (nodeStake/maxStake) * ((upperBound - nodeAsk) / (upperBound - lowerBound))^2 - rewards lower ask prices + * nodePublishingFactor: nodeStakeFactor * (nodePublishing / maxNodePublishing) - rewards active publishers + * + * All calculations use 18-decimal precision for accuracy + * @param identityId The node identity to calculate score for + * @return score18 The calculated node score scaled by 18-decimal for precision + */ + function calculateNodeScore(uint72 identityId) public view returns (uint256) { + // 1. Node stake factor calculation + // Formula: nodeStakeFactor = 2 * (nodeStake / maximumStake)^2 + uint256 maximumStake = uint256(parametersStorage.maximumStake()); + uint256 nodeStake = uint256(stakingStorage.getNodeStake(identityId)); + nodeStake = nodeStake > maximumStake ? maximumStake : nodeStake; + uint256 stakeRatio18 = (nodeStake * SCALE18) / maximumStake; + uint256 nodeStakeFactor18 = (2 * stakeRatio18 * stakeRatio18) / SCALE18; + + // 2. Node ask factor calculation + // Formula: nodeStake * ((upperAskBound - nodeAsk) / (upperAskBound - lowerAskBound))^2 / maximumStake + uint256 nodeAsk18 = uint256(profileStorage.getAsk(identityId)) * SCALE18; + (uint256 askLowerBound18, uint256 askUpperBound18) = askStorage.getAskBounds(); + uint256 nodeAskFactor18; + if (askUpperBound18 > askLowerBound18 && nodeAsk18 >= askLowerBound18 && nodeAsk18 <= askUpperBound18) { + uint256 askDiffRatio18 = ((askUpperBound18 - nodeAsk18) * SCALE18) / (askUpperBound18 - askLowerBound18); + nodeAskFactor18 = (stakeRatio18 * (askDiffRatio18 ** 2)) / (SCALE18 ** 2); + } + + // 3. Node publishing factor calculation + // Original: nodeStakeFactor * (nodePublishingFactor / MAX(allNodesPublishingFactors)) + uint256 maxNodePub = uint256(epochStorage.getCurrentEpochNodeMaxProducedKnowledgeValue()); + if (maxNodePub == 0) { + return nodeStakeFactor18 + nodeAskFactor18; + } + uint256 nodePub = uint256(epochStorage.getNodeCurrentEpochProducedKnowledgeValue(identityId)); + uint256 pubRatio18 = (nodePub * SCALE18) / maxNodePub; + uint256 nodePublishingFactor18 = (nodeStakeFactor18 * pubRatio18) / SCALE18; + + return nodeStakeFactor18 + nodeAskFactor18 + nodePublishingFactor18; + } + + /** + * @dev Updates and returns the current active proof period start block + * Automatically advances to the next period if the current one has ended + * @return Current active proof period start block number + */ + function updateAndGetActiveProofPeriodStartBlock() public returns (uint256) { + uint256 activeProofingPeriodDurationInBlocks = getActiveProofingPeriodDurationInBlocks(); + + if (activeProofingPeriodDurationInBlocks == 0) { + revert("Active proofing period duration in blocks should not be 0"); + } + + uint256 activeProofPeriodStartBlock = randomSamplingStorage.getActiveProofPeriodStartBlock(); + + if (block.number > activeProofPeriodStartBlock + activeProofingPeriodDurationInBlocks - 1) { + // Calculate how many complete periods have passed since the last active period started + uint256 blocksSinceLastStart = block.number - activeProofPeriodStartBlock; + uint256 completePeriodsPassed = blocksSinceLastStart / activeProofingPeriodDurationInBlocks; + + uint256 newActiveProofPeriodStartBlock = activeProofPeriodStartBlock + + completePeriodsPassed * + activeProofingPeriodDurationInBlocks; + + randomSamplingStorage.setActiveProofPeriodStartBlock(newActiveProofPeriodStartBlock); + + return newActiveProofPeriodStartBlock; + } + + return activeProofPeriodStartBlock; + } + + /** + * @dev Returns the status of the current active proof period including start block and whether it's still active + * @return ProofPeriodStatus struct containing start block and active status + */ + function getActiveProofPeriodStatus() external view returns (RandomSamplingLib.ProofPeriodStatus memory) { + uint256 activeProofPeriodStartBlock = randomSamplingStorage.getActiveProofPeriodStartBlock(); + return + RandomSamplingLib.ProofPeriodStatus( + activeProofPeriodStartBlock, + block.number < activeProofPeriodStartBlock + getActiveProofingPeriodDurationInBlocks() + ); + } + + /** + * @dev Calculates the start block of a historical proof period based on current period and offset + * Used to determine proof periods from the past for validation purposes + * @param proofPeriodStartBlock Start block of a valid proof period (must be > 0 and aligned to period boundaries) + * @param offset Number of periods to go back (must be > 0) + * @return Start block of the historical proof period + */ + function getHistoricalProofPeriodStartBlock( + uint256 proofPeriodStartBlock, + uint256 offset + ) external view returns (uint256) { + require(proofPeriodStartBlock > 0, "Proof period start block must be greater than 0"); + require( + proofPeriodStartBlock % getActiveProofingPeriodDurationInBlocks() == 0, + "Proof period start block is not valid" + ); + require(offset > 0, "Offset must be greater than 0"); + return proofPeriodStartBlock - offset * getActiveProofingPeriodDurationInBlocks(); + } + + /** + * @dev Returns the currently active proofing period duration in blocks + * Automatically selects the appropriate duration based on current epoch + * @return Duration in blocks of the currently active proofing period + */ + function getActiveProofingPeriodDurationInBlocks() public view returns (uint16) { + return randomSamplingStorage.getEpochProofingPeriodDurationInBlocks(chronos.getCurrentEpoch()); + } + + /** + * @dev Internal function to validate that a node profile exists + * Used by modifiers and functions to ensure operations target valid nodes + * Reverts with ProfileDoesntExist error if profile is not found + * @param identityId Node identity to check existence for + */ + function _checkProfileExists(uint72 identityId) internal view virtual { + if (!profileStorage.profileExists(identityId)) { + revert ProfileLib.ProfileDoesntExist(identityId); + } + } + + function _isMultiSigOwner(address multiSigAddress) internal view returns (bool) { + try ICustodian(multiSigAddress).getOwners() returns (address[] memory multiSigOwners) { + for (uint256 i = 0; i < multiSigOwners.length; i++) { + if (msg.sender == multiSigOwners[i]) { + return true; + } + } // solhint-disable-next-line no-empty-blocks + } catch {} + + return false; + } + + function _checkOwnerOrMultiSigOwner() internal view virtual { + address hubOwner = hub.owner(); + if (msg.sender != hubOwner && !_isMultiSigOwner(hubOwner)) { + revert HubLib.UnauthorizedAccess("Only Hub Owner or Multisig Owner"); + } + } +} diff --git a/contracts/Staking.sol b/contracts/Staking.sol index b6f42598..9f6aaedc 100644 --- a/contracts/Staking.sol +++ b/contracts/Staking.sol @@ -9,6 +9,7 @@ import {ParametersStorage} from "./storage/ParametersStorage.sol"; import {ProfileStorage} from "./storage/ProfileStorage.sol"; import {ShardingTableStorage} from "./storage/ShardingTableStorage.sol"; import {StakingStorage} from "./storage/StakingStorage.sol"; +import {DelegatorsInfo} from "./storage/DelegatorsInfo.sol"; import {ContractStatus} from "./abstract/ContractStatus.sol"; import {IInitializable} from "./interfaces/IInitializable.sol"; import {INamed} from "./interfaces/INamed.sol"; @@ -20,10 +21,21 @@ import {TokenLib} from "./libraries/TokenLib.sol"; import {IdentityLib} from "./libraries/IdentityLib.sol"; import {Permissions} from "./libraries/Permissions.sol"; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import {RandomSamplingStorage} from "./storage/RandomSamplingStorage.sol"; +import {Chronos} from "./storage/Chronos.sol"; +import {EpochStorage} from "./storage/EpochStorage.sol"; contract Staking is INamed, IVersioned, ContractStatus, IInitializable { string private constant _NAME = "Staking"; - string private constant _VERSION = "1.0.0"; + string private constant _VERSION = "1.0.1"; + uint256 public constant SCALE18 = 1e18; + + event StakeRedelegated( + uint72 indexed fromIdentityId, + uint72 indexed toIdentityId, + address indexed delegator, + uint96 amount + ); Ask public askContract; ShardingTableStorage public shardingTableStorage; @@ -32,7 +44,11 @@ contract Staking is INamed, IVersioned, ContractStatus, IInitializable { ParametersStorage public parametersStorage; ProfileStorage public profileStorage; StakingStorage public stakingStorage; + DelegatorsInfo public delegatorsInfo; IERC20 public tokenContract; + RandomSamplingStorage public randomSamplingStorage; + Chronos public chronos; + EpochStorage public epochStorage; // solhint-disable-next-line no-empty-blocks constructor(address hubAddress) ContractStatus(hubAddress) {} @@ -47,7 +63,12 @@ contract Staking is INamed, IVersioned, ContractStatus, IInitializable { _; } - function initialize() public onlyHub { + /** + * @dev Initializes the contract by connecting to all required Hub dependencies + * Called once during deployment to set up contract references + * Only the Hub can call this function + */ + function initialize() external onlyHub { askContract = Ask(hub.getContractAddress("Ask")); shardingTableStorage = ShardingTableStorage(hub.getContractAddress("ShardingTableStorage")); shardingTableContract = ShardingTable(hub.getContractAddress("ShardingTable")); @@ -55,17 +76,37 @@ contract Staking is INamed, IVersioned, ContractStatus, IInitializable { parametersStorage = ParametersStorage(hub.getContractAddress("ParametersStorage")); profileStorage = ProfileStorage(hub.getContractAddress("ProfileStorage")); stakingStorage = StakingStorage(hub.getContractAddress("StakingStorage")); + delegatorsInfo = DelegatorsInfo(hub.getContractAddress("DelegatorsInfo")); tokenContract = IERC20(hub.getContractAddress("Token")); + randomSamplingStorage = RandomSamplingStorage(hub.getContractAddress("RandomSamplingStorage")); + chronos = Chronos(hub.getContractAddress("Chronos")); + epochStorage = EpochStorage(hub.getContractAddress("EpochStorageV8")); } + /** + * @dev Returns the name of this contract + * Used for contract identification and versioning + */ function name() external pure virtual override returns (string memory) { return _NAME; } + /** + * @dev Returns the version of this contract + * Used for contract identification and versioning + */ function version() external pure virtual override returns (string memory) { return _VERSION; } + /** + * @dev Stakes tokens to a specific node, increasing both delegator and node stake + * Transfers tokens from caller to StakingStorage, updates sharding table and active set + * Validates token allowance, balance, and maximum stake limits + * Must settle any pending previous epoch rewards before changing stake + * @param identityId The node to stake to (must exist) + * @param addedStake Amount of tokens to stake (must be > 0) + */ function stake(uint72 identityId, uint96 addedStake) external profileExists(identityId) { IERC20 token = tokenContract; StakingStorage ss = stakingStorage; @@ -80,21 +121,21 @@ contract Staking is INamed, IVersioned, ContractStatus, IInitializable { revert TokenLib.TooLowBalance(address(token), token.balanceOf(msg.sender), addedStake); } + // Validate that all claims have been settled for the node before changing stake + _validateDelegatorEpochClaims(identityId, msg.sender); + bytes32 delegatorKey = keccak256(abi.encodePacked(msg.sender)); - _updateStakeInfo(identityId, delegatorKey); + // settle all pending score changes for the node's delegator + _prepareForStakeChange(chronos.getCurrentEpoch(), identityId, delegatorKey); - (uint96 delegatorStakeBase, uint96 delegatorStakeIndexed, ) = ss.getDelegatorStakeInfo( - identityId, - delegatorKey - ); + uint96 delegatorStakeBase = stakingStorage.getDelegatorStakeBase(identityId, delegatorKey); uint96 totalNodeStakeBefore = ss.getNodeStake(identityId); uint96 totalNodeStakeAfter = totalNodeStakeBefore + addedStake; if (totalNodeStakeAfter > parametersStorage.maximumStake()) { revert StakingLib.MaximumStakeExceeded(parametersStorage.maximumStake()); } - - ss.setDelegatorStakeInfo(identityId, delegatorKey, delegatorStakeBase + addedStake, delegatorStakeIndexed); + ss.setDelegatorStakeBase(identityId, delegatorKey, delegatorStakeBase + addedStake); ss.setNodeStake(identityId, totalNodeStakeAfter); ss.increaseTotalStake(addedStake); @@ -102,9 +143,22 @@ contract Staking is INamed, IVersioned, ContractStatus, IInitializable { askContract.recalculateActiveSet(); + // Check if this is first time staking + _manageDelegatorStatus(identityId, msg.sender); + token.transferFrom(msg.sender, address(ss), addedStake); } + /** + * @dev Moves stake from one node to another without unstaking/restaking process + * Validates both source and destination nodes exist and all claims are settled + * Updates stake amounts, sharding table, and active set for both nodes + * Handles delegator removal if all stake is moved from source node and no score was earned in the current epoch + * Must settle any pending previous epoch rewards before redelegating + * @param fromIdentityId Source node to move stake from + * @param toIdentityId Destination node to move stake to (cannot be same as source) + * @param stakeAmount Amount of stake to move (must be > 0 and <= delegator's stake) + */ function redelegate( uint72 fromIdentityId, uint72 toIdentityId, @@ -113,65 +167,82 @@ contract Staking is INamed, IVersioned, ContractStatus, IInitializable { StakingStorage ss = stakingStorage; Ask ask = askContract; + if (fromIdentityId == toIdentityId) { + revert("Cannot redelegate to the same node"); + } + if (stakeAmount == 0) { revert TokenLib.ZeroTokenAmount(); } bytes32 delegatorKey = keccak256(abi.encodePacked(msg.sender)); - _updateStakeInfo(fromIdentityId, delegatorKey); - _updateStakeInfo(toIdentityId, delegatorKey); + uint256 currentEpoch = chronos.getCurrentEpoch(); - (uint96 delegatorStakeBase, uint96 delegatorStakeIndexed, ) = ss.getDelegatorStakeInfo( - fromIdentityId, - delegatorKey - ); + // Validate that all claims have been settled for the source and destination nodes before changing stake + _validateDelegatorEpochClaims(fromIdentityId, msg.sender); + _validateDelegatorEpochClaims(toIdentityId, msg.sender); - if (stakeAmount > delegatorStakeBase + delegatorStakeIndexed) { - revert StakingLib.WithdrawalExceedsStake(delegatorStakeBase + delegatorStakeIndexed, stakeAmount); - } + // Prepare for stake change on the source and destination nodes + uint256 fromDelegatorEpochScore18 = _prepareForStakeChange(currentEpoch, fromIdentityId, delegatorKey); + // settle all pending score changes for the node's delegator + _prepareForStakeChange(currentEpoch, toIdentityId, delegatorKey); - if (ss.getNodeStake(toIdentityId) + stakeAmount > parametersStorage.maximumStake()) { - revert StakingLib.MaximumStakeExceeded(parametersStorage.maximumStake()); - } + uint96 fromDelegatorStakeBase = ss.getDelegatorStakeBase(fromIdentityId, delegatorKey); - uint96 newDelegatorStakeBase = delegatorStakeBase; - uint96 newDelegatorStakeIndexed = delegatorStakeIndexed; + if (stakeAmount > fromDelegatorStakeBase) { + revert StakingLib.WithdrawalExceedsStake(fromDelegatorStakeBase, stakeAmount); + } - if (stakeAmount > delegatorStakeIndexed) { - newDelegatorStakeBase = delegatorStakeBase - (stakeAmount - delegatorStakeIndexed); - newDelegatorStakeIndexed = 0; - } else { - newDelegatorStakeIndexed = delegatorStakeIndexed - stakeAmount; + uint96 maxStake = parametersStorage.maximumStake(); + if (ss.getNodeStake(toIdentityId) + stakeAmount > maxStake) { + revert StakingLib.MaximumStakeExceeded(maxStake); } + // calculate new delegator stake base on the source node + uint96 newFromDelegatorStakeBase = fromDelegatorStakeBase - stakeAmount; + + // calculate new total node stake on the source node uint96 totalFromNodeStakeBefore = ss.getNodeStake(fromIdentityId); uint96 totalFromNodeStakeAfter = totalFromNodeStakeBefore - stakeAmount; + // calculate new total node stake on the destination node uint96 totalToNodeStakeBefore = ss.getNodeStake(toIdentityId); uint96 totalToNodeStakeAfter = totalToNodeStakeBefore + stakeAmount; - ss.setDelegatorStakeInfo(fromIdentityId, delegatorKey, newDelegatorStakeBase, newDelegatorStakeIndexed); + // update the delegator stake base and the total node stake on the source node + ss.setDelegatorStakeBase(fromIdentityId, delegatorKey, newFromDelegatorStakeBase); ss.setNodeStake(fromIdentityId, totalFromNodeStakeAfter); _removeNodeFromShardingTable(fromIdentityId, totalFromNodeStakeAfter); - ask.recalculateActiveSet(); - - if (stakeAmount > delegatorStakeIndexed) { - ss.increaseDelegatorStakeBase(toIdentityId, delegatorKey, (delegatorStakeBase - newDelegatorStakeBase)); - } - ss.increaseDelegatorStakeRewardIndexed( - toIdentityId, - delegatorKey, - (delegatorStakeIndexed - newDelegatorStakeIndexed) - ); + // update the delegator stake base and the total node stake on the destination node + ss.increaseDelegatorStakeBase(toIdentityId, delegatorKey, stakeAmount); ss.setNodeStake(toIdentityId, totalToNodeStakeAfter); _addNodeToShardingTable(toIdentityId, totalToNodeStakeAfter); ask.recalculateActiveSet(); + + // Check if all stake is being removed from the source node + if (newFromDelegatorStakeBase == 0) { + _handleDelegatorRemovalOnZeroStake(fromIdentityId, msg.sender, fromDelegatorEpochScore18, currentEpoch); + } + + _manageDelegatorStatus(toIdentityId, msg.sender); + + emit StakeRedelegated(fromIdentityId, toIdentityId, msg.sender, stakeAmount); } + /** + * @dev Initiates withdrawal process for staked tokens with time delay + * For nodes above maximum stake: tokens are transferred immediately + * For other nodes: creates withdrawal request with delay period + * Updates sharding table/active set + * Removes delegator from node if all stake is withdrawn and no score was earned in the current epoch + * Must settle any pending previous epoch rewards before withdrawing + * @param identityId Node to withdraw stake from (must exist) + * @param removedStake Amount to withdraw (must be > 0 and <= delegator's stake) + */ function requestWithdrawal(uint72 identityId, uint96 removedStake) external profileExists(identityId) { StakingStorage ss = stakingStorage; @@ -179,183 +250,147 @@ contract Staking is INamed, IVersioned, ContractStatus, IInitializable { revert TokenLib.ZeroTokenAmount(); } - bytes32 delegatorKey = keccak256(abi.encodePacked(msg.sender)); - _updateStakeInfo(identityId, delegatorKey); - - (uint96 delegatorStakeBase, uint96 delegatorStakeIndexed, ) = ss.getDelegatorStakeInfo( - identityId, - delegatorKey - ); + // Validate that all claims have been settled for the node before changing stake + _validateDelegatorEpochClaims(identityId, msg.sender); - if (removedStake > delegatorStakeBase + delegatorStakeIndexed) { - revert StakingLib.WithdrawalExceedsStake(delegatorStakeBase + delegatorStakeIndexed, removedStake); - } + bytes32 delegatorKey = keccak256(abi.encodePacked(msg.sender)); + uint256 currentEpoch = chronos.getCurrentEpoch(); - uint96 newDelegatorStakeBase = delegatorStakeBase; - uint96 newDelegatorStakeIndexed = delegatorStakeIndexed; + // settle all pending score changes for the node's delegator + uint256 delegatorEpochScore18 = _prepareForStakeChange(currentEpoch, identityId, delegatorKey); - if (removedStake > delegatorStakeIndexed) { - newDelegatorStakeBase = delegatorStakeBase - (removedStake - delegatorStakeIndexed); - newDelegatorStakeIndexed = 0; - } else { - newDelegatorStakeIndexed = delegatorStakeIndexed - removedStake; + uint96 delegatorStakeBase = ss.getDelegatorStakeBase(identityId, delegatorKey); + if (removedStake > delegatorStakeBase) { + revert StakingLib.WithdrawalExceedsStake(delegatorStakeBase, removedStake); } + uint96 newDelegatorStakeBase = delegatorStakeBase - removedStake; uint96 totalNodeStakeBefore = ss.getNodeStake(identityId); uint96 totalNodeStakeAfter = totalNodeStakeBefore - removedStake; - ss.setDelegatorStakeInfo(identityId, delegatorKey, newDelegatorStakeBase, newDelegatorStakeIndexed); + ss.setDelegatorStakeBase(identityId, delegatorKey, newDelegatorStakeBase); ss.setNodeStake(identityId, totalNodeStakeAfter); ss.decreaseTotalStake(removedStake); _removeNodeFromShardingTable(identityId, totalNodeStakeAfter); - askContract.recalculateActiveSet(); + if (newDelegatorStakeBase == 0) { + _handleDelegatorRemovalOnZeroStake(identityId, msg.sender, delegatorEpochScore18, currentEpoch); + } + if (totalNodeStakeAfter >= parametersStorage.maximumStake()) { - ss.addDelegatorCumulativePaidOutRewards( - identityId, - delegatorKey, - delegatorStakeIndexed - newDelegatorStakeIndexed - ); - ss.addNodeCumulativePaidOutRewards(identityId, delegatorStakeIndexed - newDelegatorStakeIndexed); ss.transferStake(msg.sender, removedStake); } else { - (uint96 prevDelegatorWithdrawalAmount, uint96 prevDelegatorIndexedOutRewardAmount, ) = ss - .getDelegatorWithdrawalRequest(identityId, delegatorKey); - + (uint96 prevDelegatorWithdrawalAmount, , ) = ss.getDelegatorWithdrawalRequest(identityId, delegatorKey); ss.createDelegatorWithdrawalRequest( identityId, delegatorKey, removedStake + prevDelegatorWithdrawalAmount, - delegatorStakeIndexed - newDelegatorStakeIndexed + prevDelegatorIndexedOutRewardAmount, + 0, // no indexed rewards any more block.timestamp + parametersStorage.stakeWithdrawalDelay() ); } } + /** + * @dev Completes withdrawal process after the delay period has passed + * Transfers the withdrawn tokens from StakingStorage to the delegator + * Validates that withdrawal was initiated and delay period is complete + * Removes the withdrawal request after successful transfer + * @param identityId Node that withdrawal was requested from (must exist) + */ function finalizeWithdrawal(uint72 identityId) external profileExists(identityId) { StakingStorage ss = stakingStorage; bytes32 delegatorKey = keccak256(abi.encodePacked(msg.sender)); - ( - uint96 delegatorWithdrawalAmount, - uint96 delegatorIndexedOutRewardAmount, - uint256 delegatorWithdrawalTimestamp - ) = ss.getDelegatorWithdrawalRequest(identityId, delegatorKey); + (uint96 withdrawalAmount, , uint256 withdrawalReleaseTimestamp) = ss.getDelegatorWithdrawalRequest( + identityId, + delegatorKey + ); - if (delegatorWithdrawalAmount == 0) { + if (withdrawalAmount == 0) { revert StakingLib.WithdrawalWasntInitiated(); } - if (block.timestamp < delegatorWithdrawalTimestamp) { - revert StakingLib.WithdrawalPeriodPending(block.timestamp, delegatorWithdrawalTimestamp); + if (block.timestamp < withdrawalReleaseTimestamp) { + revert StakingLib.WithdrawalPeriodPending(block.timestamp, withdrawalReleaseTimestamp); } ss.deleteDelegatorWithdrawalRequest(identityId, delegatorKey); - ss.addDelegatorCumulativePaidOutRewards(identityId, delegatorKey, delegatorIndexedOutRewardAmount); - ss.addNodeCumulativePaidOutRewards(identityId, delegatorIndexedOutRewardAmount); - ss.transferStake(msg.sender, delegatorWithdrawalAmount); + ss.transferStake(msg.sender, withdrawalAmount); } + /** + * @dev Cancels pending withdrawal and restakes the tokens back to the node + * If restaking would exceed maximum stake, partial amount is restaked and rest remains pending + * Settles rewards and updates sharding table/active set + * Validates that withdrawal was initiated and no rewards are pending claim + * Must settle any pending previous epoch rewards before cancelling withdrawal + * @param identityId Node to cancel withdrawal from (must exist) + */ function cancelWithdrawal(uint72 identityId) external profileExists(identityId) { StakingStorage ss = stakingStorage; bytes32 delegatorKey = keccak256(abi.encodePacked(msg.sender)); - ( - uint96 delegatorWithdrawalAmount, - uint96 delegatorIndexedOutRewardAmount, - uint256 delegatorWithdrawalTimestamp - ) = ss.getDelegatorWithdrawalRequest(identityId, delegatorKey); - if (delegatorWithdrawalAmount == 0) { - revert StakingLib.WithdrawalWasntInitiated(); - } + (uint96 prevDelegatorWithdrawalAmount /*unused*/, , uint256 withdrawalReleaseTimestamp) = ss + .getDelegatorWithdrawalRequest(identityId, delegatorKey); + if (prevDelegatorWithdrawalAmount == 0) revert StakingLib.WithdrawalWasntInitiated(); - _updateStakeInfo(identityId, delegatorKey); - (uint96 delegatorStakeBase, uint96 delegatorStakeIndexed, ) = ss.getDelegatorStakeInfo( - identityId, - delegatorKey - ); + // Validate that all claims have been settled for the node before changing stake + _validateDelegatorEpochClaims(identityId, msg.sender); - uint96 returnableStakeAmount; - uint96 returnableIndexedOutReward; - uint96 totalNodeStakeBefore = ss.getNodeStake(identityId); - uint96 maximumStake = parametersStorage.maximumStake(); - if (totalNodeStakeBefore + delegatorWithdrawalAmount > maximumStake) { - returnableStakeAmount = maximumStake - totalNodeStakeBefore; - returnableIndexedOutReward = returnableStakeAmount < delegatorIndexedOutRewardAmount - ? delegatorIndexedOutRewardAmount - returnableStakeAmount - : delegatorIndexedOutRewardAmount; + // settle all pending score changes for the node's delegator + _prepareForStakeChange(chronos.getCurrentEpoch(), identityId, delegatorKey); - ss.createDelegatorWithdrawalRequest( - identityId, - delegatorKey, - delegatorWithdrawalAmount - returnableStakeAmount, - delegatorIndexedOutRewardAmount - returnableIndexedOutReward, - delegatorWithdrawalTimestamp - ); - } else { - returnableStakeAmount = delegatorWithdrawalAmount; - returnableIndexedOutReward = delegatorIndexedOutRewardAmount; - ss.deleteDelegatorWithdrawalRequest(identityId, delegatorKey); - } + uint96 nodeStakeBefore = ss.getNodeStake(identityId); + uint96 maxStake = parametersStorage.maximumStake(); + uint96 restake; + uint96 keepPending = 0; - uint96 totalNodeStakeAfter = totalNodeStakeBefore + returnableStakeAmount; - - ss.setDelegatorStakeInfo( - identityId, - delegatorKey, - delegatorStakeBase + returnableStakeAmount, - delegatorStakeIndexed + returnableIndexedOutReward - ); - ss.setNodeStake(identityId, totalNodeStakeAfter); - ss.increaseTotalStake(delegatorWithdrawalAmount); - - _addNodeToShardingTable(identityId, totalNodeStakeAfter); - - askContract.recalculateActiveSet(); - } - - function distributeRewards( - uint72 identityId, - uint96 rewardAmount - ) external onlyContracts profileExists(identityId) { - StakingStorage ss = stakingStorage; - - if (rewardAmount == 0) { - revert TokenLib.ZeroTokenAmount(); + if (nodeStakeBefore + prevDelegatorWithdrawalAmount > maxStake) { + restake = maxStake - nodeStakeBefore; // might be zero + keepPending = prevDelegatorWithdrawalAmount - restake; + } else { + restake = prevDelegatorWithdrawalAmount; } - ProfileLib.OperatorFee memory operatorFee = profileStorage.getActiveOperatorFee(identityId); + if (restake > 0) { + uint96 newBase = ss.getDelegatorStakeBase(identityId, delegatorKey) + restake; - uint96 delegatorsReward = rewardAmount; - if (operatorFee.feePercentage != 0) { - uint96 operatorFeeAmount = uint96((uint256(rewardAmount) * operatorFee.feePercentage) / 10000); - delegatorsReward -= operatorFeeAmount; + ss.setDelegatorStakeBase(identityId, delegatorKey, newBase); + ss.setNodeStake(identityId, nodeStakeBefore + restake); + ss.increaseTotalStake(restake); - ss.increaseOperatorFeeBalance(identityId, operatorFeeAmount); - ss.addOperatorFeeCumulativeEarnedRewards(identityId, operatorFeeAmount); + // the delegator might have had zero stake before the cancel + // If delegator was inactive and is now restaking, reset their lastStakeHeldEpoch + _manageDelegatorStatus(identityId, msg.sender); } - if (delegatorsReward == 0) { - return; + if (keepPending == 0) { + ss.deleteDelegatorWithdrawalRequest(identityId, delegatorKey); // request fully cancelled + } else { + ss.createDelegatorWithdrawalRequest( + identityId, + delegatorKey, + keepPending, + 0, // indexed-out rewards no longer exist + withdrawalReleaseTimestamp // keep the original release time + ); } - uint96 totalNodeStakeBefore = ss.getNodeStake(identityId); - uint96 totalNodeStakeAfter = totalNodeStakeBefore + delegatorsReward; - - uint256 nodeRewardIndex = ss.getNodeRewardIndex(identityId); - uint256 nodeRewardIndexIncrement = (uint256(delegatorsReward) * 1e18) / totalNodeStakeBefore; - - ss.setNodeRewardIndex(identityId, nodeRewardIndex + nodeRewardIndexIncrement); - ss.setNodeStake(identityId, totalNodeStakeAfter); - ss.addNodeCumulativeEarnedRewards(identityId, delegatorsReward); - ss.increaseTotalStake(delegatorsReward); - - _addNodeToShardingTable(identityId, totalNodeStakeAfter); - + _addNodeToShardingTable(identityId, ss.getNodeStake(identityId)); askContract.recalculateActiveSet(); } + /** + * @dev Converts accumulated operator fees back into stake for the node + * Only the node admin can perform this operation + * Settles rewards, validates fee balance, and updates stake amounts + * Updates sharding table and active set after restaking + * Must settle any pending previous epoch rewards before restaking + * @param identityId Node to restake fees for (caller must be admin) + * @param addedStake Amount of fees to convert to stake (must be > 0 and <= fee balance) + */ function restakeOperatorFee(uint72 identityId, uint96 addedStake) external onlyAdmin(identityId) { StakingStorage ss = stakingStorage; @@ -368,14 +403,15 @@ contract Staking is INamed, IVersioned, ContractStatus, IInitializable { revert StakingLib.AmountExceedsOperatorFeeBalance(oldOperatorFeeBalance, addedStake); } - uint96 newOperatorFeeBalance = oldOperatorFeeBalance - addedStake; - ss.setOperatorFeeBalance(identityId, newOperatorFeeBalance); - - bytes32 operatorKey = keccak256(abi.encodePacked(msg.sender)); - _updateStakeInfo(identityId, operatorKey); + // Validate that all claims have been settled for the node before changing stake + _validateDelegatorEpochClaims(identityId, msg.sender); + bytes32 delegatorKey = keccak256(abi.encodePacked(msg.sender)); + // settle all pending score changes for the node's delegator + _prepareForStakeChange(chronos.getCurrentEpoch(), identityId, delegatorKey); - (uint96 delegatorStakeBase, uint96 delegatorStakeIndexed, ) = ss.getDelegatorStakeInfo(identityId, operatorKey); + ss.setOperatorFeeBalance(identityId, oldOperatorFeeBalance - addedStake); + uint96 delegatorStakeBase = ss.getDelegatorStakeBase(identityId, delegatorKey); uint96 totalNodeStakeBefore = ss.getNodeStake(identityId); uint96 totalNodeStakeAfter = totalNodeStakeBefore + addedStake; @@ -383,16 +419,25 @@ contract Staking is INamed, IVersioned, ContractStatus, IInitializable { revert StakingLib.MaximumStakeExceeded(parametersStorage.maximumStake()); } - ss.setDelegatorStakeInfo(identityId, operatorKey, delegatorStakeBase + addedStake, delegatorStakeIndexed); + ss.setDelegatorStakeBase(identityId, delegatorKey, delegatorStakeBase + addedStake); ss.setNodeStake(identityId, totalNodeStakeAfter); - ss.addOperatorFeeCumulativePaidOutRewards(identityId, addedStake); + ss.addOperatorFeeCumulativePaidOutRewards(identityId, addedStake); // bookkeeping ss.increaseTotalStake(addedStake); - _addNodeToShardingTable(identityId, totalNodeStakeAfter); + _manageDelegatorStatus(identityId, msg.sender); + _addNodeToShardingTable(identityId, totalNodeStakeAfter); askContract.recalculateActiveSet(); } + /** + * @dev Initiates withdrawal process for accumulated operator fees + * Only the node admin can perform this operation + * Creates withdrawal request with delay period before funds can be claimed + * Validates that sufficient fees are available for withdrawal + * @param identityId Node to withdraw fees from (caller must be admin) + * @param withdrawalAmount Amount of fees to withdraw (must be > 0 and <= fee balance) + */ function requestOperatorFeeWithdrawal(uint72 identityId, uint96 withdrawalAmount) external onlyAdmin(identityId) { StakingStorage ss = stakingStorage; @@ -400,34 +445,63 @@ contract Staking is INamed, IVersioned, ContractStatus, IInitializable { revert TokenLib.ZeroTokenAmount(); } - uint96 oldOperatorFeeBalance = ss.getOperatorFeeBalance(identityId); - if (withdrawalAmount > oldOperatorFeeBalance) { - revert StakingLib.AmountExceedsOperatorFeeBalance(oldOperatorFeeBalance, withdrawalAmount); + // Check if there's an existing withdrawal request + uint96 existingRequestAmount = ss.getOperatorFeeWithdrawalRequestAmount(identityId); + uint96 currentOperatorFeeBalance = ss.getOperatorFeeBalance(identityId); + + // If there's an existing request, add it back to the balance first + if (existingRequestAmount > 0) { + currentOperatorFeeBalance += existingRequestAmount; } - uint256 releaseTime = block.timestamp + parametersStorage.stakeWithdrawalDelay(); + // Calculate total request amount (existing + new) + uint96 totalRequestAmount = existingRequestAmount + withdrawalAmount; - ss.setOperatorFeeBalance(identityId, oldOperatorFeeBalance - withdrawalAmount); - ss.createOperatorFeeWithdrawalRequest(identityId, withdrawalAmount, withdrawalAmount, releaseTime); + if (totalRequestAmount > currentOperatorFeeBalance) { + revert StakingLib.AmountExceedsOperatorFeeBalance(currentOperatorFeeBalance, totalRequestAmount); + } + + uint256 withdrawalReleaseTimestamp = block.timestamp + parametersStorage.stakeWithdrawalDelay(); + // Deduct total request amount from balance + ss.setOperatorFeeBalance(identityId, currentOperatorFeeBalance - totalRequestAmount); + // Create request with total amount (existing + new) + ss.createOperatorFeeWithdrawalRequest( + identityId, + totalRequestAmount, + /*indexed*/ 0, + withdrawalReleaseTimestamp + ); } + /** + * @dev Completes operator fee withdrawal after delay period has passed + * Only the node admin can perform this operation + * Transfers the withdrawn fees to the admin and updates bookkeeping + * Validates that withdrawal was initiated and delay period is complete + * @param identityId Node to finalize fee withdrawal for (caller must be admin) + */ function finalizeOperatorFeeWithdrawal(uint72 identityId) external onlyAdmin(identityId) { StakingStorage ss = stakingStorage; - (uint96 operatorFeeWithdrawalAmount, uint96 operatorFeeIndexedOutAmount, uint256 timestamp) = ss - .getOperatorFeeWithdrawalRequest(identityId); - if (operatorFeeWithdrawalAmount == 0) { - revert StakingLib.WithdrawalWasntInitiated(); - } - if (block.timestamp < timestamp) { - revert StakingLib.WithdrawalPeriodPending(block.timestamp, timestamp); - } + (uint96 operatorFeeWithdrawalAmount, , uint256 withdrawalReleaseTimestamp) = ss.getOperatorFeeWithdrawalRequest( + identityId + ); + if (operatorFeeWithdrawalAmount == 0) revert StakingLib.WithdrawalWasntInitiated(); + if (block.timestamp < withdrawalReleaseTimestamp) + revert StakingLib.WithdrawalPeriodPending(block.timestamp, withdrawalReleaseTimestamp); ss.deleteOperatorFeeWithdrawalRequest(identityId); - ss.addOperatorFeeCumulativePaidOutRewards(identityId, operatorFeeIndexedOutAmount); + ss.addOperatorFeeCumulativePaidOutRewards(identityId, operatorFeeWithdrawalAmount); ss.transferStake(msg.sender, operatorFeeWithdrawalAmount); } + /** + * @dev Cancels pending operator fee withdrawal and returns fees to balance + * Only the node admin can perform this operation + * Validates that withdrawal was initiated and restores the fee balance + * No delay period restrictions apply for cancellation + * @param identityId Node to cancel fee withdrawal for (caller must be admin) + */ function cancelOperatorFeeWithdrawal(uint72 identityId) external onlyAdmin(identityId) { StakingStorage ss = stakingStorage; @@ -440,98 +514,296 @@ contract Staking is INamed, IVersioned, ContractStatus, IInitializable { ss.increaseOperatorFeeBalance(identityId, operatorFeeWithdrawalAmount); } - function getOperatorStats(uint72 identityId) external view returns (uint96, uint96, uint96) { - StakingStorage ss = stakingStorage; + /** + * @dev Claims rewards for a delegator for a specific epoch. Claiming is not the same as withdrawing. + * Claiming adds delegator's rewards to their stake. Withdrawing takes delegator's stake out of the system. + * Handles operator fee distribution and delegator reward calculation + * Must claim epochs in sequential order starting from last claimed + 1 + * If more than one epoch rewards are pending, the rewards are accumulated in rolling rewards + * Automatically restakes rewards if no other epoch rewards are pending + * Updates delegator status and handles removal when appropriate + * @param identityId Node to which delegator has delegated (must exist) + * @param epoch Epoch to claim rewards for (must be finalized and in sequence) + * @param delegator Address of the delegator to claim for (must be a node delegator) + */ + function claimDelegatorRewards( + uint72 identityId, + uint256 epoch, + address delegator + ) public profileExists(identityId) { + uint256 currentEpoch = chronos.getCurrentEpoch(); + require(epoch < currentEpoch, "Epoch not finalised"); - bytes32[] memory adminKeys = identityStorage.getKeysByPurpose(identityId, IdentityLib.ADMIN_KEY); + // Cannot claim rewards for a delegator that is not a node delegator + require(delegatorsInfo.isNodeDelegator(identityId, delegator), "Delegator not found"); - uint96 totalSimBase; - uint96 totalSimIndexed; - uint96 totalSimUnrealized; - uint96 totalEarned; - uint96 totalPaidOut; - for (uint256 i; i < adminKeys.length; i++) { - (uint96 simBase, uint96 simIndexed, uint96 simUnrealized) = simulateStakeInfoUpdate( - identityId, - adminKeys[i] - ); + uint256 lastClaimed = delegatorsInfo.getLastClaimedEpoch(identityId, delegator); + if (lastClaimed == currentEpoch - 1) { + revert("Already claimed all finalised epochs"); + } - (uint96 operatorEarned, uint96 operatorPaidOut) = ss.getDelegatorRewardsInfo(identityId, adminKeys[i]); + if (epoch <= lastClaimed) { + revert("Epoch already claimed"); + } - totalSimBase += simBase; - totalSimIndexed += simIndexed; - totalSimUnrealized += simUnrealized; - totalEarned += operatorEarned; - totalPaidOut += operatorPaidOut; + if (epoch > lastClaimed + 1) { + revert("Must claim older epochs first"); } - return (totalSimBase + totalSimIndexed, totalEarned + totalSimUnrealized - totalPaidOut, totalPaidOut); - } + bytes32 delegatorKey = keccak256(abi.encodePacked(delegator)); + require( + !delegatorsInfo.hasDelegatorClaimedEpochRewards(epoch, identityId, delegatorKey), + "Already claimed rewards for this epoch" + ); + + // settle all pending score changes for the node's delegator + uint256 delegatorScore18 = _prepareForStakeChange(epoch, identityId, delegatorKey); + uint256 nodeScore18 = randomSamplingStorage.getNodeEpochScore(epoch, identityId); + uint256 reward; + + // If delegatorScore18 = 0 or nodeScore18 = 0, rewards are 0 too + if (delegatorScore18 != 0 && nodeScore18 != 0) { + // netNodeRewards (rewards for node's delegators) = grossNodeRewards - operator fee + uint256 netNodeRewards; + if (!delegatorsInfo.isOperatorFeeClaimedForEpoch(identityId, epoch)) { + // Operator fee has not been claimed for this epoch, calculate it + uint256 allNodesScore18 = randomSamplingStorage.getAllNodesEpochScore(epoch); + if (allNodesScore18 > 0) { + uint256 grossNodeRewards = (epochStorage.getEpochPool(1, epoch) * nodeScore18) / allNodesScore18; + uint96 operatorFeeAmount = uint96( + (grossNodeRewards * profileStorage.getLatestOperatorFeePercentage(identityId)) / + parametersStorage.maxOperatorFee() + ); + netNodeRewards = grossNodeRewards - operatorFeeAmount; + stakingStorage.increaseOperatorFeeBalance(identityId, operatorFeeAmount); + // Mark the operator fee as claimed for this epoch + delegatorsInfo.setIsOperatorFeeClaimedForEpoch(identityId, epoch, true); + // Set node's delegators net rewards for this epoch so we don't have to calculate it again + delegatorsInfo.setNetNodeEpochRewards(identityId, epoch, netNodeRewards); + } + } else { + // Operator fee has been claimed for this epoch already, use the previously calculated node's delegators net rewards for this epoch + netNodeRewards = delegatorsInfo.getNetNodeEpochRewards(identityId, epoch); + } - function getNodeStats(uint72 identityId) external view returns (uint96, uint96, uint96) { - return stakingStorage.getNodeRewardsInfo(identityId); + reward = (delegatorScore18 * netNodeRewards) / nodeScore18; + } + + // update state even when reward is zero + // Mark the delegator's rewards as claimed for this epoch + delegatorsInfo.setHasDelegatorClaimedEpochRewards(epoch, identityId, delegatorKey, true); + uint256 lastClaimedEpoch = delegatorsInfo.getLastClaimedEpoch(identityId, delegator); + delegatorsInfo.setLastClaimedEpoch(identityId, delegator, epoch); + + // Check if this completes all required claims and reset lastStakeHeldEpoch + uint256 lastStakeHeldEpoch = delegatorsInfo.getLastStakeHeldEpoch(identityId, delegator); + if (lastStakeHeldEpoch > 0 && epoch >= lastStakeHeldEpoch) { + // They've now claimed all rewards they're entitled to, reset the tracker + delegatorsInfo.setLastStakeHeldEpoch(identityId, delegator, 0); + + // Check if they should be removed from delegators list + if (reward == 0 && stakingStorage.getDelegatorStakeBase(identityId, delegatorKey) == 0) { + delegatorsInfo.removeDelegator(identityId, delegator); + } + } + + uint256 rolling = delegatorsInfo.getDelegatorRollingRewards(identityId, delegator); + + if (reward == 0 && rolling == 0) return; + + // if there are still older epochs pending, accumulate; otherwise restake immediately + if ((currentEpoch - 1) - lastClaimedEpoch > 1) { + delegatorsInfo.setDelegatorRollingRewards(identityId, delegator, rolling + reward); + } else { + uint96 total = uint96(reward + rolling); + delegatorsInfo.setDelegatorRollingRewards(identityId, delegator, 0); + stakingStorage.increaseDelegatorStakeBase(identityId, delegatorKey, total); + stakingStorage.increaseNodeStake(identityId, total); + stakingStorage.increaseTotalStake(total); + } + //Should it increase on roling rewards or on stakeBaseIncrease only? + stakingStorage.addDelegatorCumulativeEarnedRewards(identityId, delegatorKey, uint96(reward)); } - function getOperatorFeeStats(uint72 identityId) external view returns (uint96, uint96, uint96) { - return stakingStorage.getNodeOperatorFeesInfo(identityId); + /** + * @dev Claims rewards for multiple delegators across multiple epochs in batch + * Calls claimDelegatorRewards internally for each epoch-delegator combination + * Provides gas-efficient way to process multiple reward claims + * All standard reward claiming rules and validations apply + * @param identityId Node to claim rewards from (must exist) + * @param epochs Array of epochs to claim for (each must be valid for claiming) + * @param delegators Array of delegator addresses (each must be a node delegator) + */ + function batchClaimDelegatorRewards( + uint72 identityId, + uint256[] memory epochs, + address[] memory delegators + ) external profileExists(identityId) { + for (uint256 i = 0; i < epochs.length; i++) { + for (uint256 j = 0; j < delegators.length; j++) { + claimDelegatorRewards(identityId, epochs[i], delegators[j]); + } + } } - function getDelegatorStats(uint72 identityId, address delegator) external view returns (uint96, uint96, uint96) { + /** + * @dev Internal function to validate that delegator has claimed all required epoch rewards + * Ensures delegators claim rewards before changing stake to prevent reward loss + * Handles special cases for new delegators and those with zero stake + * Auto-advances claim state when no rewards exist for previous epoch + * @param identityId Node to validate claims for + * @param delegator Address of delegator to validate + */ + function _validateDelegatorEpochClaims(uint72 identityId, address delegator) internal { bytes32 delegatorKey = keccak256(abi.encodePacked(delegator)); - (uint96 simBase, uint96 simIndexed, uint96 simUnrealized) = simulateStakeInfoUpdate(identityId, delegatorKey); + uint256 currentEpoch = chronos.getCurrentEpoch(); + uint256 previousEpoch = currentEpoch - 1; + + if (delegatorsInfo.hasEverDelegatedToNode(identityId, delegator)) { + // If delegator has delegated to the node before, and has removed all their stake from the node at some point + if (stakingStorage.getDelegatorStakeBase(identityId, delegatorKey) == 0) { + uint256 lastStakeHeldEpoch = delegatorsInfo.getLastStakeHeldEpoch(identityId, delegator); + // If lastStakeHeldEpoch > 0 and < currentEpoch, delegator has unclaimed rewards for a past epoch + if (lastStakeHeldEpoch > 0 && lastStakeHeldEpoch < currentEpoch) { + revert("Must claim rewards up to the lastStakeHeldEpoch before changing stake"); + } + // If lastStakeHeldEpoch == currentEpoch, rewards aren't claimable yet - allow operation + // If lastStakeHeldEpoch == 0, delegator claimed all rewards they are entitled to + delegatorsInfo.setLastClaimedEpoch(identityId, delegator, previousEpoch); + } + } else { + // delegator is delegating to a node for the first time ever, set the last claimed epoch to the previous epoch + delegatorsInfo.setLastClaimedEpoch(identityId, delegator, previousEpoch); + } + + uint256 lastClaimedEpoch = delegatorsInfo.getLastClaimedEpoch(identityId, delegator); + + // If delegator is up to date with claims, no validation needed + if (lastClaimedEpoch == previousEpoch) { + return; + } - (uint96 delegatorEarned, uint96 delegatorPaidOut) = stakingStorage.getDelegatorRewardsInfo( + // Check if delegator has multiple unclaimed epochs + if (lastClaimedEpoch < previousEpoch - 1) { + revert("Must claim all previous epoch rewards before changing stake"); + } + + // Delegator has exactly one unclaimed epoch (previousEpoch) + // Check if there are actually rewards to claim for that epoch + uint256 delegatorScore18 = randomSamplingStorage.getEpochNodeDelegatorScore( + previousEpoch, identityId, delegatorKey ); - return (simBase + simIndexed, delegatorEarned + simUnrealized - delegatorPaidOut, delegatorPaidOut); + uint256 nodeScorePerStake36 = randomSamplingStorage.getNodeEpochScorePerStake(previousEpoch, identityId); + + uint256 delegatorLastSettledScorePerStake36 = randomSamplingStorage + .getDelegatorLastSettledNodeEpochScorePerStake(previousEpoch, identityId, delegatorKey); + + // If no rewards exist for this delegator in the previous epoch, auto-advance their claim state + if (delegatorScore18 == 0 && nodeScorePerStake36 == delegatorLastSettledScorePerStake36) { + delegatorsInfo.setLastClaimedEpoch(identityId, delegator, previousEpoch); + return; + } + + // Delegator has unclaimed rewards that must be claimed first + revert("Must claim the previous epoch rewards before changing stake"); } - function simulateStakeInfoUpdate( + /** + * @dev Internal function to settle delegator rewards before stake changes + * Calculates and applies newly earned score for the delegator in the epoch + * Updates delegator's last settled score-per-stake index to current value + * Handles edge cases for delegators with zero stake + * @param epoch Epoch to settle score for + * @param identityId Node to settle score for + * @param delegatorKey Keccak256 hash of delegator address + * @return delegatorEpochScore Total score for the delegator in the epoch after settlement + */ + function _prepareForStakeChange( + uint256 epoch, uint72 identityId, bytes32 delegatorKey - ) public view returns (uint96, uint96, uint96) { - uint256 nodeRewardIndex = stakingStorage.getNodeRewardIndex(identityId); + ) internal returns (uint256 delegatorEpochScore) { + // 1. Current "score-per-stake" + uint256 nodeScorePerStake36 = randomSamplingStorage.getNodeEpochScorePerStake(epoch, identityId); + + uint256 currentDelegatorScore18 = randomSamplingStorage.getEpochNodeDelegatorScore( + epoch, + identityId, + delegatorKey + ); - (uint96 delegatorStakeBase, uint96 delegatorStakeIndexed, uint256 delegatorLastRewardIndex) = stakingStorage - .getDelegatorStakeInfo(identityId, delegatorKey); + // 2. Last index at which this delegator was settled + uint256 delegatorLastSettledNodeEpochScorePerStake36 = randomSamplingStorage + .getDelegatorLastSettledNodeEpochScorePerStake(epoch, identityId, delegatorKey); - if (nodeRewardIndex <= delegatorLastRewardIndex) { - return (delegatorStakeBase, delegatorStakeIndexed, 0); + // Nothing new to settle + if (nodeScorePerStake36 == delegatorLastSettledNodeEpochScorePerStake36) { + return currentDelegatorScore18; } - uint256 diff = nodeRewardIndex - delegatorLastRewardIndex; - uint256 currentStake = uint256(delegatorStakeBase) + uint256(delegatorStakeIndexed); - uint96 additionalReward = uint96((currentStake * diff) / 1e18); - - return (delegatorStakeBase, delegatorStakeIndexed + additionalReward, additionalReward); - } + uint96 stakeBase = stakingStorage.getDelegatorStakeBase(identityId, delegatorKey); - function _updateStakeInfo(uint72 identityId, bytes32 delegatorKey) internal { - StakingStorage ss = stakingStorage; + // If the delegator has no stake, just bump the index and exit + if (stakeBase == 0) { + randomSamplingStorage.setDelegatorLastSettledNodeEpochScorePerStake( + epoch, + identityId, + delegatorKey, + nodeScorePerStake36 + ); + return currentDelegatorScore18; + } + // 4. Newly earned score for this delegator in the epoch + uint256 diff36 = nodeScorePerStake36 - delegatorLastSettledNodeEpochScorePerStake36; + uint256 scoreEarned18 = (uint256(stakeBase) * diff36) / SCALE18; - (uint96 delegatorStakeBase, uint96 delegatorStakeIndexed, uint256 delegatorLastRewardIndex) = ss - .getDelegatorStakeInfo(identityId, delegatorKey); - uint256 nodeRewardIndex = ss.getNodeRewardIndex(identityId); + // 5. Persist results + if (scoreEarned18 > 0) { + randomSamplingStorage.addToEpochNodeDelegatorScore(epoch, identityId, delegatorKey, scoreEarned18); + } - if (nodeRewardIndex > delegatorLastRewardIndex) { - uint256 currentStake = uint256(delegatorStakeBase) + uint256(delegatorStakeIndexed); - if (currentStake == 0) { - ss.setDelegatorLastRewardIndex(identityId, delegatorKey, nodeRewardIndex); - } else { - uint256 diff = nodeRewardIndex - delegatorLastRewardIndex; - uint96 additional = uint96((currentStake * diff) / 1e18); - delegatorStakeIndexed += additional; + randomSamplingStorage.setDelegatorLastSettledNodeEpochScorePerStake( + epoch, + identityId, + delegatorKey, + nodeScorePerStake36 + ); - ss.setDelegatorStakeInfo(identityId, delegatorKey, delegatorStakeBase, delegatorStakeIndexed); - ss.setDelegatorLastRewardIndex(identityId, delegatorKey, nodeRewardIndex); + return currentDelegatorScore18 + scoreEarned18; + } - ss.addDelegatorCumulativeEarnedRewards(identityId, delegatorKey, additional); - } + /** + * @dev Internal function to manage delegator registration and status tracking + * Adds delegator to node's delegator list if not already registered + * Marks delegator as having ever delegated to the node (for claim validation) + * Resets lastStakeHeldEpoch when delegator becomes active again + * @param identityId Node to manage delegator status for + * @param delegator Address of the delegator + */ + function _manageDelegatorStatus(uint72 identityId, address delegator) internal { + if (!delegatorsInfo.isNodeDelegator(identityId, delegator)) { + delegatorsInfo.addDelegator(identityId, delegator); + } + if (!delegatorsInfo.hasEverDelegatedToNode(identityId, delegator)) { + delegatorsInfo.setHasEverDelegatedToNode(identityId, delegator, true); + } + // If operator was inactive and is now restaking fees, reset their lastStakeHeldEpoch + uint256 lastStakeHeldEpoch = delegatorsInfo.getLastStakeHeldEpoch(identityId, delegator); + if (lastStakeHeldEpoch > 0) { + delegatorsInfo.setLastStakeHeldEpoch(identityId, delegator, 0); } } + /** + * @dev Internal function to add node to sharding table when stake requirements are met + * Only adds node if it doesn't exist and has minimum required stake + * Validates that sharding table isn't full before adding + * @param identityId Node to potentially add to sharding table + * @param newStake Current stake amount for the node + */ function _addNodeToShardingTable(uint72 identityId, uint96 newStake) internal { ShardingTableStorage sts = shardingTableStorage; ParametersStorage params = parametersStorage; @@ -544,12 +816,24 @@ contract Staking is INamed, IVersioned, ContractStatus, IInitializable { } } + /** + * @dev Internal function to remove node from sharding table when stake falls below minimum + * Only removes node if it exists and stake is below minimum threshold + * @param identityId Node to potentially remove from sharding table + * @param newStake Current stake amount for the node + */ function _removeNodeFromShardingTable(uint72 identityId, uint96 newStake) internal { if (shardingTableStorage.nodeExists(identityId) && newStake < parametersStorage.minimumStake()) { shardingTableContract.removeNode(identityId); } } + /** + * @dev Internal function to validate that caller is an admin of the specified node + * Checks if caller's address has admin key purpose for the identity + * Used by functions that require node admin permissions + * @param identityId Node identity to check admin rights for + */ function _checkAdmin(uint72 identityId) internal view virtual { if ( !identityStorage.keyHasPurpose(identityId, keccak256(abi.encodePacked(msg.sender)), IdentityLib.ADMIN_KEY) @@ -558,9 +842,40 @@ contract Staking is INamed, IVersioned, ContractStatus, IInitializable { } } + /** + * @dev Internal function to validate that a node profile exists + * Used by modifiers and functions to ensure operations target valid nodes + * @param identityId Node identity to check existence for + */ function _checkProfileExists(uint72 identityId) internal view virtual { if (!profileStorage.profileExists(identityId)) { revert ProfileLib.ProfileDoesntExist(identityId); } } + + /** + * @dev Internal function to handle delegator cleanup when stake reaches zero + * If delegator earned score in current epoch: keeps them for future reward claims + * If no score earned: removes delegator from node immediately + * Prevents loss of rewards while optimizing storage usage + * @param identityId Node to handle delegator removal for + * @param delegator Address of delegator with zero stake + * @param delegatorEpochScore18 Score earned by delegator in current epoch + * @param currentEpoch Current epoch number + */ + function _handleDelegatorRemovalOnZeroStake( + uint72 identityId, + address delegator, + uint256 delegatorEpochScore18, + uint256 currentEpoch + ) internal { + // Don't remove delegator immediately - they might still be eligible for rewards in current epoch + if (delegatorEpochScore18 > 0) { + // Delegator earned score in current epoch (can claim), keep them for future reward claims + delegatorsInfo.setLastStakeHeldEpoch(identityId, delegator, currentEpoch); + } else { + // No score earned in current epoch, safe to remove immediately + delegatorsInfo.removeDelegator(identityId, delegator); + } + } } diff --git a/contracts/StakingKPI.sol b/contracts/StakingKPI.sol new file mode 100644 index 00000000..b105a9bc --- /dev/null +++ b/contracts/StakingKPI.sol @@ -0,0 +1,245 @@ +// SPDX-License-Identifier: Apache-2.0 + +pragma solidity ^0.8.20; + +import {IdentityStorage} from "./storage/IdentityStorage.sol"; +import {ProfileStorage} from "./storage/ProfileStorage.sol"; +import {StakingStorage} from "./storage/StakingStorage.sol"; +import {DelegatorsInfo} from "./storage/DelegatorsInfo.sol"; +import {ContractStatus} from "./abstract/ContractStatus.sol"; +import {IInitializable} from "./interfaces/IInitializable.sol"; +import {INamed} from "./interfaces/INamed.sol"; +import {IVersioned} from "./interfaces/IVersioned.sol"; +import {ProfileLib} from "./libraries/ProfileLib.sol"; +import {IdentityLib} from "./libraries/IdentityLib.sol"; +import {EpochStorage} from "./storage/EpochStorage.sol"; +import {RandomSamplingStorage} from "./storage/RandomSamplingStorage.sol"; +import {ParametersStorage} from "./storage/ParametersStorage.sol"; + +contract StakingKPI is INamed, IVersioned, ContractStatus, IInitializable { + string private constant _NAME = "StakingKPI"; + string private constant _VERSION = "1.0.0"; + uint256 public constant SCALE18 = 1e18; + + IdentityStorage public identityStorage; + ProfileStorage public profileStorage; + StakingStorage public stakingStorage; + DelegatorsInfo public delegatorsInfo; + RandomSamplingStorage public randomSamplingStorage; + EpochStorage public epochStorage; + ParametersStorage public parametersStorage; + + /** + * @dev Initializes the StakingKPI contract with the Hub address for access control + * Only called once during deployment + * @param hubAddress Address of the Hub contract for access control and contract dependencies + */ + constructor(address hubAddress) ContractStatus(hubAddress) {} + + modifier profileExists(uint72 identityId) { + _checkProfileExists(identityId); + _; + } + + /** + * @dev Initializes the contract by connecting to all required Hub storage dependencies + * Called once during deployment to set up contract references for staking calculations + * Only the Hub can call this function + */ + function initialize() external onlyHub { + identityStorage = IdentityStorage(hub.getContractAddress("IdentityStorage")); + profileStorage = ProfileStorage(hub.getContractAddress("ProfileStorage")); + stakingStorage = StakingStorage(hub.getContractAddress("StakingStorage")); + delegatorsInfo = DelegatorsInfo(hub.getContractAddress("DelegatorsInfo")); + randomSamplingStorage = RandomSamplingStorage(hub.getContractAddress("RandomSamplingStorage")); + epochStorage = EpochStorage(hub.getContractAddress("EpochStorageV8")); + parametersStorage = ParametersStorage(hub.getContractAddress("ParametersStorage")); + } + + /** + * @dev Returns the name of this contract for identification purposes + * @return Contract name as a string + */ + function name() external pure virtual override returns (string memory) { + return _NAME; + } + + /** + * @dev Returns the version of this contract for compatibility tracking + * @return Contract version as a string + */ + function version() external pure virtual override returns (string memory) { + return _VERSION; + } + + /** + * @dev Returns the total stake of all admin keys for a node + * @param identityId Node's identity ID to get total stake for + * @return Total stake of all admin keys for the node + */ + function getOperatorStats(uint72 identityId) external view returns (uint96) { + bytes32[] memory adminKeys = identityStorage.getKeysByPurpose(identityId, IdentityLib.ADMIN_KEY); + + uint96 totalStake; + for (uint256 i; i < adminKeys.length; i++) { + uint96 delegatorStakeBase = stakingStorage.getDelegatorStakeBase(identityId, adminKeys[i]); + totalStake += delegatorStakeBase; + } + + return totalStake; + } + + /** + * @dev Returns the total node stake + * @param identityId Node's identity ID to get total stake for + * @return Total stake of the node + */ + function getNodeStats(uint72 identityId) external view returns (uint96) { + return stakingStorage.getNodeStake(identityId); + } + + /** + * @dev Returns the total node operator fee balance + * @param identityId Node's identity ID to get total operator fee balance for + * @return Total node operator fee balance + */ + function getOperatorFeeStats(uint72 identityId) external view returns (uint96) { + return stakingStorage.getOperatorFeeBalance(identityId); + } + + /** + * @dev Returns the total stake of a node's delegator + * @param identityId Node's identity ID to get total stake for + * @param delegator Delegator's address to get stake for + * @return Total stake of the node's delegator + */ + function getDelegatorStats(uint72 identityId, address delegator) external view returns (uint96) { + bytes32 delegatorKey = keccak256(abi.encodePacked(delegator)); + return stakingStorage.getDelegatorStakeBase(identityId, delegatorKey); + } + + /** + * @dev Calculate the reward for a delegator in an epoch (correct only for the finalized epochs) + * Determines the delegator's share of the total node rewards for a specific epoch + * Uses the delegator's score relative to the total node score to calculate proportional rewards + * @param identityId Node's identity ID that the delegator is delegating to + * @param epoch Epoch number to calculate rewards for (must be finalized) + * @param delegator Delegator's address to calculate rewards for + * @return Reward amount for the delegator in the specified epoch + */ + function getDelegatorReward( + uint72 identityId, + uint256 epoch, + address delegator + ) external view profileExists(identityId) returns (uint256) { + require(delegatorsInfo.isNodeDelegator(identityId, delegator), "Delegator not found"); + + bytes32 delegatorKey = keccak256(abi.encodePacked(delegator)); + + uint256 delegatorScore18 = _simulatePrepareForStakeChange(epoch, identityId, delegatorKey); + if (delegatorScore18 == 0) return 0; + + uint256 nodeScore18 = randomSamplingStorage.getNodeEpochScore(epoch, identityId); + if (nodeScore18 == 0) return 0; + + // Calculate the final delegators rewards pool + uint256 netNodeRewards = getNetNodeRewards(identityId, epoch); + + if (netNodeRewards == 0) return 0; + + return (delegatorScore18 * netNodeRewards) / nodeScore18; + } + + /** + * @dev Fetch the net rewards for all node's delegators in an epoch (rewards of node's delegators - operator fee) + * Calculates the total rewards available to node's delegators after operator fees are deducted + * Handles both cases: when operator fee has been claimed and when it hasn't + * @param identityId Node's identity ID to get net rewards for + * @param epoch Epoch number to calculate net rewards for + * @return Net rewards available for distribution to the node's delegators in the epoch + */ + function getNetNodeRewards( + uint72 identityId, + uint256 epoch + ) public view profileExists(identityId) returns (uint256) { + // If the operator fee has been claimed, return the net delegators rewards + if (delegatorsInfo.isOperatorFeeClaimedForEpoch(identityId, epoch)) { + return delegatorsInfo.getNetNodeEpochRewards(identityId, epoch); + } + + uint256 nodeScore18 = randomSamplingStorage.getNodeEpochScore(epoch, identityId); + if (nodeScore18 == 0) return 0; + + uint256 allNodesScore18 = randomSamplingStorage.getAllNodesEpochScore(epoch); + if (allNodesScore18 == 0) return 0; + + uint256 epocRewardsPool = epochStorage.getEpochPool(1, epoch); + if (epocRewardsPool == 0) return 0; + + uint256 totalNodeRewards = (epocRewardsPool * nodeScore18) / allNodesScore18; + + uint256 feePercentageForEpoch = profileStorage.getLatestOperatorFeePercentage(identityId); + uint96 operatorFeeAmount = uint96( + (totalNodeRewards * feePercentageForEpoch) / parametersStorage.maxOperatorFee() + ); + + return totalNodeRewards - operatorFeeAmount; + } + + /** + * @dev Internal function to simulate preparing for stake change and calculate delegator score + * Calculates what the delegator's score would be after settling all pending score changes + * Used for reward calculations without actually updating storage state + * @param epoch The epoch to simulate the stake change for + * @param identityId The node identity ID the delegator is delegating to + * @param delegatorKey The unique key identifying the delegator + * @return delegatorScore18 The simulated delegator score after settling, scaled by 10^18 + */ + function _simulatePrepareForStakeChange( + uint256 epoch, + uint72 identityId, + bytes32 delegatorKey + ) internal view returns (uint256 delegatorScore18) { + // 1. Current "score-per-stake" + uint256 nodeScorePerStake36 = randomSamplingStorage.getNodeEpochScorePerStake(epoch, identityId); + + uint256 currentDelegatorScore18 = randomSamplingStorage.getEpochNodeDelegatorScore( + epoch, + identityId, + delegatorKey + ); + + // 2. Last index at which this delegator was settled + uint256 delegatorLastSettledNodeEpochScorePerStake36 = randomSamplingStorage + .getDelegatorLastSettledNodeEpochScorePerStake(epoch, identityId, delegatorKey); + + // Nothing new to settle + if (nodeScorePerStake36 == delegatorLastSettledNodeEpochScorePerStake36) { + return currentDelegatorScore18; + } + + uint96 stakeBase = stakingStorage.getDelegatorStakeBase(identityId, delegatorKey); + + // If the delegator has no stake, just bump the index and exit + if (stakeBase == 0) { + return currentDelegatorScore18; + } + // 4. Newly earned score for this delegator in the epoch + uint256 diff36 = nodeScorePerStake36 - delegatorLastSettledNodeEpochScorePerStake36; // scaled 1e36 + uint256 scoreEarned18 = (uint256(stakeBase) * diff36) / SCALE18; + + return currentDelegatorScore18 + scoreEarned18; + } + + /** + * @dev Internal function to validate that a node profile exists + * Used by modifiers and functions to ensure operations target valid nodes + * Reverts with ProfileDoesntExist error if profile is not found + * @param identityId Node identity ID to check existence for + */ + function _checkProfileExists(uint72 identityId) internal view virtual { + if (!profileStorage.profileExists(identityId)) { + revert ProfileLib.ProfileDoesntExist(identityId); + } + } +} diff --git a/contracts/libraries/RandomSamplingLib.sol b/contracts/libraries/RandomSamplingLib.sol new file mode 100644 index 00000000..b9661199 --- /dev/null +++ b/contracts/libraries/RandomSamplingLib.sol @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: Apache-2.0 + +pragma solidity ^0.8.20; + +library RandomSamplingLib { + struct Challenge { + uint256 knowledgeCollectionId; + uint256 chunkId; // TODO:Smaller data structure + address knowledgeCollectionStorageContract; + uint256 epoch; + uint256 activeProofPeriodStartBlock; + uint256 proofingPeriodDurationInBlocks; + bool solved; + } + + struct ProofPeriodStatus { + uint256 activeProofPeriodStartBlock; + bool isValid; + } + + struct ProofingPeriodDuration { + uint16 durationInBlocks; + uint256 effectiveEpoch; + } +} diff --git a/contracts/storage/DelegatorsInfo.sol b/contracts/storage/DelegatorsInfo.sol new file mode 100644 index 00000000..66c37bbb --- /dev/null +++ b/contracts/storage/DelegatorsInfo.sol @@ -0,0 +1,218 @@ +// SPDX-License-Identifier: Apache-2.0 + +pragma solidity ^0.8.20; + +import {StakingStorage} from "./StakingStorage.sol"; +import {IInitializable} from "../interfaces/IInitializable.sol"; +import {INamed} from "../interfaces/INamed.sol"; +import {IVersioned} from "../interfaces/IVersioned.sol"; +import {ContractStatus} from "../abstract/ContractStatus.sol"; + +contract DelegatorsInfo is INamed, IVersioned, ContractStatus, IInitializable { + string private constant _NAME = "DelegatorsInfo"; + string private constant _VERSION = "1.0.0"; + + // IdentityId => Delegators + mapping(uint72 => address[]) public nodeDelegatorAddresses; + // IdentityId => Delegator => Index + mapping(uint72 => mapping(address => uint256)) public nodeDelegatorIndex; + // IdentityId => Delegator => IsDelegator + mapping(uint72 => mapping(address => bool)) public isDelegatorMap; + // IdentityId => Delegator => LastClaimedEpoch + mapping(uint72 => mapping(address => uint256)) public lastClaimedEpoch; + // IdentityId => Delegator => RollingRewards + mapping(uint72 => mapping(address => uint256)) public delegatorRollingRewards; + // IdentityId => Epoch => OperatorFeeClaimed + mapping(uint72 => mapping(uint256 => bool)) public isOperatorFeeClaimedForEpoch; + // IdentityId => Epoch => Amount + mapping(uint72 => mapping(uint256 => uint256)) public netNodeEpochRewards; + // IdentityId => Epoch + mapping(uint72 => uint256) public lastClaimedDelegatorsRewardsEpoch; + // epoch => identityId => delegatorKey => rewards claimed status + mapping(uint256 => mapping(uint72 => mapping(bytes32 => bool))) public hasDelegatorClaimedEpochRewards; + // IdentityId => Delegator => HasEverDelegatedToNode + mapping(uint72 => mapping(address => bool)) public hasEverDelegatedToNode; + // IdentityId => Delegator => LastStakeHeldEpoch (the last epoch when delegator held stake, 0 if fully claimed) + mapping(uint72 => mapping(address => uint256)) public lastStakeHeldEpoch; + + event DelegatorAdded(uint72 indexed identityId, address indexed delegator); + event DelegatorRemoved(uint72 indexed identityId, address indexed delegator); + event DelegatorLastClaimedEpochUpdated( + uint72 indexed identityId, + address indexed delegator, + uint256 newLastClaimedEpoch + ); + event DelegatorRollingRewardsUpdated( + uint72 indexed identityId, + address indexed delegator, + uint256 amount, + uint256 newTotalRollingRewards + ); + event IsOperatorFeeClaimedForEpochUpdated(uint72 indexed identityId, uint256 indexed epoch, bool isClaimed); + event NetNodeEpochRewardsSet(uint72 indexed identityId, uint256 indexed epoch, uint256 amount); + event HasEverDelegatedToNodeUpdated( + uint72 indexed identityId, + address indexed delegator, + bool hasEverDelegatedToNode + ); + event LastStakeHeldEpochUpdated(uint72 indexed identityId, address indexed delegator, uint256 epoch); + event HasDelegatorClaimedEpochRewardsUpdated( + uint256 indexed epoch, + uint72 indexed identityId, + bytes32 indexed delegatorKey, + bool claimed + ); + + // solhint-disable-next-line no-empty-blocks + constructor(address hubAddress) ContractStatus(hubAddress) {} + + function initialize() external onlyHub {} + + function name() external pure virtual override returns (string memory) { + return _NAME; + } + + function version() external pure virtual override returns (string memory) { + return _VERSION; + } + + function addDelegator(uint72 identityId, address delegator) external onlyContracts { + nodeDelegatorIndex[identityId][delegator] = nodeDelegatorAddresses[identityId].length; + nodeDelegatorAddresses[identityId].push(delegator); + isDelegatorMap[identityId][delegator] = true; + + emit DelegatorAdded(identityId, delegator); + } + + function removeDelegator(uint72 identityId, address delegator) external onlyContracts { + if (!isDelegatorMap[identityId][delegator]) { + revert("Delegator not found"); + } + + uint256 indexToRemove = nodeDelegatorIndex[identityId][delegator]; + uint256 lastIndex = nodeDelegatorAddresses[identityId].length - 1; + + if (indexToRemove != lastIndex) { + address lastDelegator = nodeDelegatorAddresses[identityId][lastIndex]; + nodeDelegatorAddresses[identityId][indexToRemove] = lastDelegator; + nodeDelegatorIndex[identityId][lastDelegator] = indexToRemove; + } + + nodeDelegatorAddresses[identityId].pop(); + delete nodeDelegatorIndex[identityId][delegator]; + delete isDelegatorMap[identityId][delegator]; + + emit DelegatorRemoved(identityId, delegator); + } + + function setLastClaimedEpoch(uint72 identityId, address delegator, uint256 epoch) external onlyContracts { + lastClaimedEpoch[identityId][delegator] = epoch; + emit DelegatorLastClaimedEpochUpdated(identityId, delegator, epoch); + } + + function getLastClaimedEpoch(uint72 identityId, address delegator) external view returns (uint256) { + return lastClaimedEpoch[identityId][delegator]; + } + + function setDelegatorRollingRewards(uint72 identityId, address delegator, uint256 amount) external onlyContracts { + delegatorRollingRewards[identityId][delegator] = amount; + emit DelegatorRollingRewardsUpdated(identityId, delegator, amount, amount); + } + + function addDelegatorRollingRewards(uint72 identityId, address delegator, uint256 amount) external onlyContracts { + delegatorRollingRewards[identityId][delegator] += amount; + emit DelegatorRollingRewardsUpdated( + identityId, + delegator, + amount, + delegatorRollingRewards[identityId][delegator] + ); + } + + function getDelegatorRollingRewards(uint72 identityId, address delegator) external view returns (uint256) { + return delegatorRollingRewards[identityId][delegator]; + } + + function getDelegators(uint72 identityId) external view returns (address[] memory) { + return nodeDelegatorAddresses[identityId]; + } + + function getDelegatorIndex(uint72 identityId, address delegator) external view returns (uint256) { + return nodeDelegatorIndex[identityId][delegator]; + } + + function isNodeDelegator(uint72 identityId, address delegator) external view returns (bool) { + return isDelegatorMap[identityId][delegator]; + } + + function setIsOperatorFeeClaimedForEpoch(uint72 identityId, uint256 epoch, bool isClaimed) external onlyContracts { + isOperatorFeeClaimedForEpoch[identityId][epoch] = isClaimed; + emit IsOperatorFeeClaimedForEpochUpdated(identityId, epoch, isClaimed); + } + + function setNetNodeEpochRewards(uint72 identityId, uint256 epoch, uint256 amount) external onlyContracts { + netNodeEpochRewards[identityId][epoch] = amount; + emit NetNodeEpochRewardsSet(identityId, epoch, amount); + } + + function getNetNodeEpochRewards(uint72 identityId, uint256 epoch) external view returns (uint256) { + return netNodeEpochRewards[identityId][epoch]; + } + + function setHasDelegatorClaimedEpochRewards( + uint256 epoch, + uint72 identityId, + bytes32 delegatorKey, + bool claimed + ) external onlyContracts { + hasDelegatorClaimedEpochRewards[epoch][identityId][delegatorKey] = claimed; + emit HasDelegatorClaimedEpochRewardsUpdated(epoch, identityId, delegatorKey, claimed); + } + + function setHasEverDelegatedToNode( + uint72 identityId, + address delegator, + bool _hasEverDelegatedToNode + ) external onlyContracts { + hasEverDelegatedToNode[identityId][delegator] = _hasEverDelegatedToNode; + emit HasEverDelegatedToNodeUpdated(identityId, delegator, _hasEverDelegatedToNode); + } + + function setLastStakeHeldEpoch(uint72 identityId, address delegator, uint256 epoch) external onlyContracts { + lastStakeHeldEpoch[identityId][delegator] = epoch; + emit LastStakeHeldEpochUpdated(identityId, delegator, epoch); + } + + function getLastStakeHeldEpoch(uint72 identityId, address delegator) external view returns (uint256) { + return lastStakeHeldEpoch[identityId][delegator]; + } + + function migrate(address[] memory newAddresses) external { + StakingStorage ss = StakingStorage(hub.getContractAddress("StakingStorage")); + for (uint256 i = 0; i < newAddresses.length; ) { + bytes32 addressHash = keccak256(abi.encodePacked(newAddresses[i])); + uint72[] memory delegatorNodes = ss.getDelegatorNodes(addressHash); + for (uint256 j = 0; j < delegatorNodes.length; ) { + if (isDelegatorMap[delegatorNodes[j]][newAddresses[i]]) { + unchecked { + j++; + } + continue; + } + nodeDelegatorIndex[delegatorNodes[j]][newAddresses[i]] = nodeDelegatorAddresses[delegatorNodes[j]] + .length; + nodeDelegatorAddresses[delegatorNodes[j]].push(newAddresses[i]); + isDelegatorMap[delegatorNodes[j]][newAddresses[i]] = true; + + emit DelegatorAdded(delegatorNodes[j], newAddresses[i]); + + unchecked { + j++; + } + } + unchecked { + i++; + } + } + } +} diff --git a/contracts/storage/MigratorM1V8.sol b/contracts/storage/MigratorM1V8.sol new file mode 100644 index 00000000..27533f43 --- /dev/null +++ b/contracts/storage/MigratorM1V8.sol @@ -0,0 +1,233 @@ +// SPDX-License-Identifier: Apache-2.0 + +pragma solidity ^0.8.20; + +import {ShardingTable} from "../ShardingTable.sol"; +import {Token} from "../Token.sol"; +import {AskStorage} from "../storage/AskStorage.sol"; +import {EpochStorage} from "../storage/EpochStorage.sol"; +import {IdentityStorage} from "../storage/IdentityStorage.sol"; +import {ParametersStorage} from "../storage/ParametersStorage.sol"; +import {ProfileStorage} from "../storage/ProfileStorage.sol"; +import {StakingStorage} from "../storage/StakingStorage.sol"; +import {ContractStatus} from "../abstract/ContractStatus.sol"; +import {IdentityLib} from "../libraries/IdentityLib.sol"; +import {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; +import {ICustodian} from "../interfaces/ICustodian.sol"; + +interface IOldHub { + function getContractAddress(string memory) external view returns (address); +} + +interface IOldStakingStorage { + function transferStake(address, uint96) external; + function totalStakes(uint72) external view returns (uint96); + function getWithdrawalRequestAmount(uint72, address) external view returns (uint96); + function getWithdrawalRequestTimestamp(uint72, address) external view returns (uint256); +} + +interface IOldProfileStorage { + function transferAccumulatedOperatorFee(address, uint96) external; + function getAccumulatedOperatorFee(uint72) external view returns (uint96); + function getSharesContractAddress(uint72) external view returns (address); + function getAccumulatedOperatorFeeWithdrawalAmount(uint72) external view returns (uint96); + function getAccumulatedOperatorFeeWithdrawalTimestamp(uint72) external view returns (uint256); + function getNodeId(uint72) external view returns (bytes memory); + function getAsk(uint72) external view returns (uint96); +} + +interface IOldNodeOperatorFeesStorage { + function getOperatorFeesLength(uint72) external view returns (uint256); + function getLatestOperatorFeePercentage(uint72) external view returns (uint8); +} + +interface IOldServiceAgreementStorage { + function transferAgreementTokens(address, uint96) external; +} + +contract MigratorM1V8 is ContractStatus { + error DelegatorsMigrationNotInitiated(); + error DelegatorAlreadyMigrated(uint72 identityId, address delegator); + error InvalidTotalStake(uint96 expected, uint96 received); + + IOldHub public oldHub; + IdentityStorage public oldIdentityStorage; + IOldStakingStorage public oldStakingStorage; + IOldProfileStorage public oldProfileStorage; + IOldNodeOperatorFeesStorage public oldNodeOperatorFeesStorage; + IOldServiceAgreementStorage public oldServiceAgreementStorageV1; + IOldServiceAgreementStorage public oldServiceAgreementStorageV1U1; + + EpochStorage public epochStorageV6; + ParametersStorage public newParametersStorage; + ProfileStorage public newProfileStorage; + ShardingTable public newShardingTable; + StakingStorage public newStakingStorage; + IdentityStorage public newIdentityStorage; + AskStorage public askStorage; + Token public token; + + uint72 public oldNodesCount; + uint72 public migratedNodes; + + uint96 public oldStakingStorageBalance; + uint96 public oldOperatorFees; + uint96 public oldTotalUnpaidRewards; + + uint96 public oldTotalStake; + uint96 public oldMigratedOperatorFees; + uint96 public migratedStake; + + bool public delegatorsMigrationInitiated; + + mapping(uint72 => uint96) public oldNodeStakes; + mapping(uint72 => uint96) public migratedStakes; + + mapping(uint72 => bool) public nodeMigrated; + mapping(uint72 => mapping(address => bool)) public delegatorMigrated; + mapping(uint72 => bool) public operatorMigrated; + + constructor(address hubAddress, address oldHubAddress) ContractStatus(hubAddress) { + oldHub = IOldHub(oldHubAddress); + } + + // @dev Only transactions by HubController owner or one of the owners of the MultiSig Wallet + modifier onlyOwnerOrMultiSigOwner() { + _checkOwnerOrMultiSigOwner(); + _; + } + + function initializeOldContracts() external onlyOwnerOrMultiSigOwner { + oldIdentityStorage = IdentityStorage(oldHub.getContractAddress("IdentityStorage")); + oldStakingStorage = IOldStakingStorage(oldHub.getContractAddress("StakingStorage")); + oldProfileStorage = IOldProfileStorage(oldHub.getContractAddress("ProfileStorage")); + oldNodeOperatorFeesStorage = IOldNodeOperatorFeesStorage(oldHub.getContractAddress("NodeOperatorFeesStorage")); + oldServiceAgreementStorageV1 = IOldServiceAgreementStorage( + oldHub.getContractAddress("ServiceAgreementStorageV1") + ); + oldServiceAgreementStorageV1U1 = IOldServiceAgreementStorage( + oldHub.getContractAddress("ServiceAgreementStorageV1U1") + ); + } + + function initializeNewContracts() external onlyOwnerOrMultiSigOwner { + epochStorageV6 = EpochStorage(hub.getContractAddress("EpochStorageV6")); + newParametersStorage = ParametersStorage(hub.getContractAddress("ParametersStorage")); + newProfileStorage = ProfileStorage(hub.getContractAddress("ProfileStorage")); + newShardingTable = ShardingTable(hub.getContractAddress("ShardingTable")); + newStakingStorage = StakingStorage(hub.getContractAddress("StakingStorage")); + newIdentityStorage = IdentityStorage(hub.getContractAddress("IdentityStorage")); + askStorage = AskStorage(hub.getContractAddress("AskStorage")); + token = Token(hub.getContractAddress("Token")); + } + + // start the migration process + function initiateDelegatorsMigration() external onlyOwnerOrMultiSigOwner { + delegatorsMigrationInitiated = true; + } + + // end the migration process + function finalizeDelegatorsMigration() external onlyOwnerOrMultiSigOwner { + delegatorsMigrationInitiated = false; + } + + // migrate the delegator data + function migrateDelegatorData(uint72 identityId, address delegator) external onlyOwnerOrMultiSigOwner { + if (!delegatorsMigrationInitiated) { + revert DelegatorsMigrationNotInitiated(); + } + if (delegatorMigrated[identityId][delegator]) { + revert DelegatorAlreadyMigrated(identityId, delegator); + } + + // Stake migration + IERC20Metadata shares = IERC20Metadata(oldProfileStorage.getSharesContractAddress(identityId)); + + uint256 sharesTotalSupply = shares.totalSupply(); + uint256 delegatorSharesAmount = shares.balanceOf(delegator); + + // shares.transferFrom(delegator, address(this), delegatorSharesAmount); + oldNodeStakes[identityId] = oldStakingStorage.totalStakes(identityId); + + // Update the delegator stake base in newStakingStorage + uint96 delegatorStakeBase = uint96((oldNodeStakes[identityId] * delegatorSharesAmount) / sharesTotalSupply); + newStakingStorage.setDelegatorStakeBase(identityId, keccak256(abi.encodePacked(delegator)), delegatorStakeBase); + + // Update the node and total stake in newStakingStorage + newStakingStorage.increaseNodeStake(identityId, delegatorStakeBase); + newStakingStorage.increaseTotalStake(delegatorStakeBase); + + migratedStake += delegatorStakeBase; + + uint256 migratedNodeShares = shares.balanceOf(address(this)); + if (migratedNodeShares == sharesTotalSupply) { + nodeMigrated[identityId] = true; + migratedNodes += 1; + } + + // Delegator withdrawal migration + uint96 withdrawalAmount = oldStakingStorage.getWithdrawalRequestAmount(identityId, delegator); + if (withdrawalAmount > 0) { + uint256 withdrawalTimestamp = oldStakingStorage.getWithdrawalRequestTimestamp(identityId, delegator); + + newStakingStorage.createDelegatorWithdrawalRequest( + identityId, + keccak256(abi.encodePacked(delegator)), + withdrawalAmount, + 0, + withdrawalTimestamp + ); + } + + delegatorMigrated[identityId][delegator] = true; + + // Node operator fees and withdrawal migration + if ( + !operatorMigrated[identityId] && + newIdentityStorage.keyHasPurpose(identityId, keccak256(abi.encodePacked(delegator)), IdentityLib.ADMIN_KEY) + ) { + uint96 V6operatorAccumulatedOperatorFee = oldProfileStorage.getAccumulatedOperatorFee(identityId); + + // uint96 currentOperatorFee = newProfileStorage.getOperatorFee(identityId); + // newProfileStorage.setOperatorFees(identityId, currentOperatorFee + V6operatorAccumulatedOperatorFee); + newStakingStorage.increaseOperatorFeeBalance(identityId, V6operatorAccumulatedOperatorFee); + + oldMigratedOperatorFees += V6operatorAccumulatedOperatorFee; + + uint96 feeWithdrawalAmount = oldProfileStorage.getAccumulatedOperatorFeeWithdrawalAmount(identityId); + if (feeWithdrawalAmount > 0) { + uint256 feeWithdrawalTimestamp = oldProfileStorage.getAccumulatedOperatorFeeWithdrawalTimestamp( + identityId + ); + + newStakingStorage.createOperatorFeeWithdrawalRequest( + identityId, + feeWithdrawalAmount, + 0, + feeWithdrawalTimestamp + ); + } + + operatorMigrated[identityId] = true; + } + } + + function _isMultiSigOwner(address multiSigAddress) internal view returns (bool) { + try ICustodian(multiSigAddress).getOwners() returns (address[] memory multiSigOwners) { + for (uint256 i = 0; i < multiSigOwners.length; i++) { + if (msg.sender == multiSigOwners[i]) { + return true; + } + } // solhint-disable-next-line no-empty-blocks + } catch {} + + return false; + } + + function _checkOwnerOrMultiSigOwner() internal view virtual { + address hubOwner = hub.owner(); + if (msg.sender != hubOwner && msg.sender != address(hub) && !_isMultiSigOwner(hubOwner)) { + revert("Only Hub Owner, Hub, or Multisig Owner can call"); + } + } +} diff --git a/contracts/storage/ParametersStorage.sol b/contracts/storage/ParametersStorage.sol index c9495c44..a2d9ae7d 100644 --- a/contracts/storage/ParametersStorage.sol +++ b/contracts/storage/ParametersStorage.sol @@ -27,6 +27,8 @@ contract ParametersStorage is INamed, IVersioned, HubDependent { uint256 public askUpperBoundFactor; uint256 public askLowerBoundFactor; + uint16 public maxOperatorFee; + constructor(address hubAddress) HubDependent(hubAddress) { minimumStake = 50_000 ether; maximumStake = 2_000_000 ether; @@ -42,6 +44,8 @@ contract ParametersStorage is INamed, IVersioned, HubDependent { askUpperBoundFactor = 1467000000000000000; askLowerBoundFactor = 533000000000000000; + + maxOperatorFee = 10_000; } function name() external pure virtual override returns (string memory) { @@ -107,4 +111,10 @@ contract ParametersStorage is INamed, IVersioned, HubDependent { emit ParameterChanged("shardingTableSizeLimit", shardingTableSizeLimit); } + + function setMaxOperatorFee(uint16 maxOperatorFee_) external onlyHub { + maxOperatorFee = maxOperatorFee_; + + emit ParameterChanged("maxOperatorFee", maxOperatorFee); + } } diff --git a/contracts/storage/RandomSamplingStorage.sol b/contracts/storage/RandomSamplingStorage.sol new file mode 100644 index 00000000..ce400d52 --- /dev/null +++ b/contracts/storage/RandomSamplingStorage.sol @@ -0,0 +1,638 @@ +// SPDX-License-Identifier: Apache-2.0 + +pragma solidity ^0.8.20; + +import {INamed} from "../interfaces/INamed.sol"; +import {IVersioned} from "../interfaces/IVersioned.sol"; +import {IInitializable} from "../interfaces/IInitializable.sol"; +import {RandomSamplingLib} from "../libraries/RandomSamplingLib.sol"; +import {Chronos} from "../storage/Chronos.sol"; +import {ContractStatus} from "../abstract/ContractStatus.sol"; +import {ICustodian} from "../interfaces/ICustodian.sol"; +import {HubLib} from "../libraries/HubLib.sol"; + +contract RandomSamplingStorage is INamed, IVersioned, IInitializable, ContractStatus { + string private constant _NAME = "RandomSamplingStorage"; + string private constant _VERSION = "1.0.0"; + uint8 public constant CHUNK_BYTE_SIZE = 32; + Chronos public chronos; + + uint256 public w1; + uint256 public w2; + + RandomSamplingLib.ProofingPeriodDuration[] public proofingPeriodDurations; + + uint256 private activeProofPeriodStartBlock; + // identityId => Challenge - used in proof to verify the challenge is within proofing period + mapping(uint72 => RandomSamplingLib.Challenge) public nodesChallenges; + // epoch => identityId => successful proofs count + mapping(uint256 => mapping(uint72 => uint256)) public epochNodeValidProofsCount; + // identityId => epoch => proofPeriodStartBlock => score + mapping(uint72 => mapping(uint256 => mapping(uint256 => uint256))) public nodeEpochProofPeriodScore; + // identityId => epoch => score + mapping(uint72 => mapping(uint256 => uint256)) public nodeEpochScore; + // epoch => score + mapping(uint256 => uint256) public allNodesEpochScore; + // epoch => identityId => delegatorKey => score + mapping(uint256 => mapping(uint72 => mapping(bytes32 => uint256))) public epochNodeDelegatorScore; + // epoch => identityId => scorePerStake + mapping(uint256 => mapping(uint72 => uint256)) public nodeEpochScorePerStake; + // epoch => identityId => delegatorKey => last settled nodeEpochScorePerStake + mapping(uint256 => mapping(uint72 => mapping(bytes32 => uint256))) + public delegatorLastSettledNodeEpochScorePerStake; + + event W1Set(uint256 oldW1, uint256 newW1); + event W2Set(uint256 oldW2, uint256 newW2); + event ProofingPeriodDurationAdded(uint16 durationInBlocks, uint256 indexed effectiveEpoch); + event PendingProofingPeriodDurationReplaced( + uint16 oldDurationInBlocks, + uint16 newDurationInBlocks, + uint256 indexed effectiveEpoch + ); + event NodeEpochScoreAdded(uint256 indexed epoch, uint72 indexed identityId, uint256 scoreAdded, uint256 totalScore); + event AllNodesEpochScoreAdded(uint256 indexed epoch, uint256 scoreAdded, uint256 totalScore); + event NodeEpochProofPeriodScoreAdded( + uint256 indexed epoch, + uint256 indexed proofPeriodStartBlock, + uint72 indexed identityId, + uint256 scoreAdded, + uint256 totalScore + ); + event NodeEpochProofPeriodScoreSet( + uint256 indexed epoch, + uint256 indexed proofPeriodStartBlock, + uint72 indexed identityId, + uint256 newScore + ); + event NodeEpochScorePerStakeAdded( + uint256 indexed epoch, + uint72 indexed identityId, + uint256 scorePerStakeToAdd, + uint256 totalNodeEpochScorePerStake + ); + event NodeEpochScorePerStakeSet(uint256 indexed epoch, uint72 indexed identityId, uint256 newScorePerStake); + event EpochNodeDelegatorScoreAdded( + uint256 indexed epoch, + uint72 indexed identityId, + bytes32 indexed delegatorKey, + uint256 scoreAdded, + uint256 totalScore + ); + event DelegatorLastSettledNodeEpochScorePerStakeSet( + uint256 indexed epoch, + uint72 indexed identityId, + bytes32 indexed delegatorKey, + uint256 newDelegatorLastSettledNodeEpochScorePerStake + ); + event NodeChallengeSet(uint72 indexed identityId, RandomSamplingLib.Challenge challenge); + event ActiveProofPeriodStartBlockSet(uint256 indexed activeProofPeriodStartBlock); + event EpochNodeValidProofsCountIncremented(uint256 indexed epoch, uint72 indexed identityId, uint256 newCount); + event EpochNodeValidProofsCountSet(uint256 indexed epoch, uint72 indexed identityId, uint256 newCount); + event NodeEpochScoreSet(uint256 indexed epoch, uint72 indexed identityId, uint256 newScore); + event AllNodesEpochScoreSet(uint256 indexed epoch, uint256 newScore); + event EpochNodeDelegatorScoreSet( + uint256 indexed epoch, + uint72 indexed identityId, + bytes32 indexed delegatorKey, + uint256 newScore + ); + + /** + * @dev Initializes the RandomSamplingStorage contract with initial parameters + * Sets up proofing period duration, block time, and weight parameters for random sampling + * @param hubAddress Address of the Hub contract for access control and contract dependencies + * @param _proofingPeriodDurationInBlocks Initial duration of proofing periods in blocks + * @param _w1 First weight parameter used in rewards calculations + * @param _w2 Second weight parameter used in rewards calculations + */ + constructor( + address hubAddress, + uint16 _proofingPeriodDurationInBlocks, + uint256 _w1, + uint256 _w2 + ) ContractStatus(hubAddress) { + require(_proofingPeriodDurationInBlocks > 0, "Proofing period duration in blocks must be greater than 0"); + + Chronos c = Chronos(hub.getContractAddress("Chronos")); + + proofingPeriodDurations.push( + RandomSamplingLib.ProofingPeriodDuration({ + durationInBlocks: _proofingPeriodDurationInBlocks, + effectiveEpoch: c.getCurrentEpoch() + }) + ); + w1 = _w1; + w2 = _w2; + + emit ProofingPeriodDurationAdded(_proofingPeriodDurationInBlocks, c.getCurrentEpoch()); + emit W1Set(0, _w1); + emit W2Set(0, _w2); + } + + // @dev Only transactions by HubController owner or one of the owners of the MultiSig Wallet + modifier onlyOwnerOrMultiSigOwner() { + _checkOwnerOrMultiSigOwner(); + _; + } + + /** + * @dev Initializes the contract by setting up the Chronos reference from the hub + * Called once after deployment to complete contract setup + */ + function initialize() external onlyHub { + chronos = Chronos(hub.getContractAddress("Chronos")); + } + + /** + * @dev Returns the name of this contract for identification purposes + * @return Contract name as a string + */ + function name() external pure virtual override returns (string memory) { + return _NAME; + } + + /** + * @dev Returns the version of this contract for compatibility tracking + * @return Contract version as a string + */ + function version() external pure virtual override returns (string memory) { + return _VERSION; + } + + /** + * @dev Updates the w1 parameter used in rewards calculations + * Can only be called by the hub owner or multisig owners + * @param _w1 New w1 parameter value + */ + function setW1(uint256 _w1) external onlyOwnerOrMultiSigOwner { + uint256 oldW1 = w1; + w1 = _w1; + emit W1Set(oldW1, w1); + } + + /** + * @dev Returns the current w1 parameter value + * @return Current w1 parameter used in rewards calculations + */ + function getW1() external view returns (uint256) { + return w1; + } + + /** + * @dev Updates the w2 parameter used in rewards calculations + * Can only be called by the hub owner or multisig owners + * @param _w2 New w2 parameter value + */ + function setW2(uint256 _w2) external onlyOwnerOrMultiSigOwner { + uint256 oldW2 = w2; + w2 = _w2; + emit W2Set(oldW2, w2); + } + + /** + * @dev Returns the current w2 parameter value + * @return Current w2 parameter used in rewards calculations + */ + function getW2() external view returns (uint256) { + return w2; + } + + /** + * @dev Returns the current active proof period start block + * @return Current active proof period start block number + */ + function getActiveProofPeriodStartBlock() external view returns (uint256) { + return activeProofPeriodStartBlock; + } + + /** + * @dev Sets the active proof period start block + * Can only be called by contracts registered in the Hub + * @param newActiveProofPeriodStartBlock New active proof period start block + */ + function setActiveProofPeriodStartBlock(uint256 newActiveProofPeriodStartBlock) external onlyContracts { + activeProofPeriodStartBlock = newActiveProofPeriodStartBlock; + emit ActiveProofPeriodStartBlockSet(newActiveProofPeriodStartBlock); + } + + /** + * @dev Replaces a pending proofing period duration with new values before it becomes active + * Can only be called by contracts registered in the Hub + * @param durationInBlocks New duration in blocks for the proofing period + * @param effectiveEpoch Epoch when the new duration will take effect + */ + function replacePendingProofingPeriodDuration( + uint16 durationInBlocks, + uint256 effectiveEpoch + ) external onlyContracts { + uint16 oldDurationInBlocks = proofingPeriodDurations[proofingPeriodDurations.length - 1].durationInBlocks; + proofingPeriodDurations[proofingPeriodDurations.length - 1] = RandomSamplingLib.ProofingPeriodDuration({ + durationInBlocks: durationInBlocks, + effectiveEpoch: effectiveEpoch + }); + + emit PendingProofingPeriodDurationReplaced(oldDurationInBlocks, durationInBlocks, effectiveEpoch); + } + + /** + * @dev Adds a new proofing period duration to take effect at a future epoch + * Can only be called by contracts registered in the Hub + * @param durationInBlocks Duration in blocks for the new proofing period + * @param effectiveEpoch Epoch when the new duration will take effect + */ + function addProofingPeriodDuration(uint16 durationInBlocks, uint256 effectiveEpoch) external onlyContracts { + proofingPeriodDurations.push( + RandomSamplingLib.ProofingPeriodDuration({ + durationInBlocks: durationInBlocks, + effectiveEpoch: effectiveEpoch + }) + ); + + emit ProofingPeriodDurationAdded(durationInBlocks, effectiveEpoch); + } + + /** + * @dev Returns the proofing period duration for a specific epoch + * @param epoch The epoch to get the duration for + * @return Duration in blocks for the specified epoch + */ + function getEpochProofingPeriodDurationInBlocks(uint256 epoch) external view returns (uint16) { + // Find the most recent duration that was effective before or at the specified epoch + for (uint256 i = proofingPeriodDurations.length; i > 0; ) { + if (epoch >= proofingPeriodDurations[i - 1].effectiveEpoch) { + return proofingPeriodDurations[i - 1].durationInBlocks; + } + + unchecked { + i--; + } + } + + // If no applicable duration found, revert + revert("No applicable duration found"); + } + + /** + * @dev Returns the length of the proofing period durations array + * @return Length of the proofing period durations array + */ + function getProofingPeriodDurationsLength() external view returns (uint256) { + return proofingPeriodDurations.length; + } + + /** + * @dev Returns the effective epoch of the latest proofing period duration + * @return Effective epoch of the latest duration + */ + function getLatestProofingPeriodDurationEffectiveEpoch() external view returns (uint256) { + return proofingPeriodDurations[proofingPeriodDurations.length - 1].effectiveEpoch; + } + + /** + * @dev Returns the duration in blocks of the latest proofing period duration + * @return Duration in blocks of the latest proofing period duration + */ + function getLatestProofingPeriodDurationInBlocks() external view returns (uint16) { + return proofingPeriodDurations[proofingPeriodDurations.length - 1].durationInBlocks; + } + + /** + * @dev Returns the proofing period duration struct for a specific index + * @param index The index to get the duration for + * @return Proofing period duration struct for the specified index + */ + function getProofingPeriodDurationFromIndex( + uint256 index + ) external view returns (RandomSamplingLib.ProofingPeriodDuration memory) { + return proofingPeriodDurations[index]; + } + + /** + * @dev Returns the current challenge assigned to a specific node + * Challenges are used to verify proofs during random sampling + * @param identityId The node identity ID to get the challenge for + * @return Challenge struct containing all challenge details + */ + function getNodeChallenge(uint72 identityId) external view returns (RandomSamplingLib.Challenge memory) { + return nodesChallenges[identityId]; + } + + /** + * @dev Sets a new challenge for a specific node + * Can only be called by contracts registered in the Hub + * @param identityId The node identity ID to set the challenge for + * @param challenge The challenge struct containing all challenge details + */ + function setNodeChallenge( + uint72 identityId, + RandomSamplingLib.Challenge calldata challenge + ) external onlyContracts { + nodesChallenges[identityId] = challenge; + emit NodeChallengeSet(identityId, challenge); + } + + /** + * @dev Returns the score earned by a node during a specific epoch and proof period + * @param identityId The node identity ID to get the score for + * @param epoch The epoch to get the score for + * @param proofPeriodStartBlock The start block of the proof period + * @return Score earned by the node in the specified epoch and proof period, scaled by 10^18 + */ + function getNodeEpochProofPeriodScore( + uint72 identityId, + uint256 epoch, + uint256 proofPeriodStartBlock + ) external view returns (uint256) { + return nodeEpochProofPeriodScore[identityId][epoch][proofPeriodStartBlock]; + } + + /** + * @dev Increments the count of valid proofs submitted by a node in an epoch + * Can only be called by contracts registered in the Hub + * @param epoch The epoch to increment the count for + * @param identityId The node identity ID to increment the count for + */ + function incrementEpochNodeValidProofsCount(uint256 epoch, uint72 identityId) external onlyContracts { + epochNodeValidProofsCount[epoch][identityId] += 1; + emit EpochNodeValidProofsCountIncremented(epoch, identityId, epochNodeValidProofsCount[epoch][identityId]); + } + + function setEpochNodeValidProofsCount(uint256 epoch, uint72 identityId, uint256 count) external onlyContracts { + epochNodeValidProofsCount[epoch][identityId] = count; + emit EpochNodeValidProofsCountSet(epoch, identityId, count); + } + + /** + * @dev Returns the number of valid proofs submitted by a node in a specific epoch + * @param epoch The epoch to get the count for + * @param identityId The node identity ID to get the count for + * @return Number of valid proofs submitted by the node in the specified epoch + */ + function getEpochNodeValidProofsCount(uint256 epoch, uint72 identityId) external view returns (uint256) { + return epochNodeValidProofsCount[epoch][identityId]; + } + + /** + * @dev Adds to the total score earned by a node in a specific epoch + * Can only be called by contracts registered in the Hub + * @param epoch The epoch to add the score to + * @param identityId The node identity ID to add the score for + * @param score The score amount to add, scaled by 10^18 + */ + function addToNodeEpochScore(uint256 epoch, uint72 identityId, uint256 score) external onlyContracts { + nodeEpochScore[identityId][epoch] += score; + emit NodeEpochScoreAdded(epoch, identityId, score, nodeEpochScore[identityId][epoch]); + } + + /** + * @dev Sets a node's score for a specific epoch + * Can only be called by contracts registered in the Hub + * @param epoch The epoch to set the score for + * @param identityId The node identity ID to set the score for + * @param score The score amount to set, scaled by 10^18 + */ + function setNodeEpochScore(uint256 epoch, uint72 identityId, uint256 score) external onlyContracts { + nodeEpochScore[identityId][epoch] = score; + emit NodeEpochScoreSet(epoch, identityId, score); + } + + /** + * @dev Returns the total score earned by a node in a specific epoch + * @param epoch The epoch to get the score for + * @param identityId The node identity ID to get the score for + * @return Total score earned by the node in the specified epoch, scaled by 10^18 + */ + function getNodeEpochScore(uint256 epoch, uint72 identityId) external view returns (uint256) { + return nodeEpochScore[identityId][epoch]; + } + + /** + * @dev Adds to the total score of all nodes in a specific epoch + * Can only be called by contracts registered in the Hub + * @param epoch The epoch to add the score to + * @param score The score amount to add to the total, scaled by 10^18 + */ + function addToAllNodesEpochScore(uint256 epoch, uint256 score) external onlyContracts { + allNodesEpochScore[epoch] += score; + emit AllNodesEpochScoreAdded(epoch, score, allNodesEpochScore[epoch]); + } + + /** + * @dev Sets the total score of all nodes in a specific epoch + * Can only be called by contracts registered in the Hub + * @param epoch The epoch to set the score for + * @param score The score amount to set, scaled by 10^18 + */ + function setAllNodesEpochScore(uint256 epoch, uint256 score) external onlyContracts { + allNodesEpochScore[epoch] = score; + emit AllNodesEpochScoreSet(epoch, score); + } + + /** + * @dev Returns the total score of all nodes in a specific epoch + * @param epoch The epoch to get the total score for + * @return Total score of all nodes in the specified epoch, scaled by 10^18 + */ + function getAllNodesEpochScore(uint256 epoch) external view returns (uint256) { + return allNodesEpochScore[epoch]; + } + + /** + * @dev Adds to a node's score for a specific epoch and proof period + * Can only be called by contracts registered in the Hub + * @param epoch The epoch to add the score to + * @param proofPeriodStartBlock The start block of the proof period + * @param identityId The node identity ID to add the score for + * @param score The score amount to add, scaled by 10^18 + */ + function addToNodeEpochProofPeriodScore( + uint256 epoch, + uint256 proofPeriodStartBlock, + uint72 identityId, + uint256 score + ) external onlyContracts { + nodeEpochProofPeriodScore[identityId][epoch][proofPeriodStartBlock] += score; + emit NodeEpochProofPeriodScoreAdded( + epoch, + proofPeriodStartBlock, + identityId, + score, + nodeEpochProofPeriodScore[identityId][epoch][proofPeriodStartBlock] + ); + } + + /** + * @dev Sets a node's score for a specific epoch and proof period + * Can only be called by contracts registered in the Hub + * @param epoch The epoch to set the score for + * @param proofPeriodStartBlock The start block of the proof period + * @param identityId The node identity ID to set the score for + * @param score The score amount to set, scaled by 10^18 + */ + function setNodeEpochProofPeriodScore( + uint256 epoch, + uint256 proofPeriodStartBlock, + uint72 identityId, + uint256 score + ) external onlyContracts { + nodeEpochProofPeriodScore[identityId][epoch][proofPeriodStartBlock] = score; + emit NodeEpochProofPeriodScoreSet(epoch, proofPeriodStartBlock, identityId, score); + } + + /** + * @dev Returns the score earned by a specific node's delegator in an epoch + * Used for calculating delegator rewards + * @param epoch The epoch to get the score for + * @param identityId The node identity ID the delegator is delegating to + * @param delegatorKey The unique key identifying the delegator + * @return Score earned by the delegator for the specified node in the epoch, scaled by 10^18 + */ + function getEpochNodeDelegatorScore( + uint256 epoch, + uint72 identityId, + bytes32 delegatorKey + ) external view returns (uint256) { + return epochNodeDelegatorScore[epoch][identityId][delegatorKey]; + } + + /** + * @dev Adds to the score earned by a node's delegator in an epoch + * Can only be called by contracts registered in the Hub + * @param epoch The epoch to add the score to + * @param identityId The node identity ID the delegator is delegating to + * @param delegatorKey The unique key identifying the delegator + * @param score The score amount to add, scaled by 10^18 + */ + function addToEpochNodeDelegatorScore( + uint256 epoch, + uint72 identityId, + bytes32 delegatorKey, + uint256 score + ) external onlyContracts { + epochNodeDelegatorScore[epoch][identityId][delegatorKey] += score; + emit EpochNodeDelegatorScoreAdded( + epoch, + identityId, + delegatorKey, + score, + epochNodeDelegatorScore[epoch][identityId][delegatorKey] + ); + } + + function setEpochNodeDelegatorScore( + uint256 epoch, + uint72 identityId, + bytes32 delegatorKey, + uint256 score + ) external onlyContracts { + epochNodeDelegatorScore[epoch][identityId][delegatorKey] = score; + emit EpochNodeDelegatorScoreSet(epoch, identityId, delegatorKey, score); + } + + /** + * @dev Returns the score per stake ratio for a node in a specific epoch + * Used for calculating proportional rewards based on staked amount + * @param epoch The epoch to get the score per stake for + * @param identityId The node identity ID to get the score per stake for + * @return Score per stake ratio for the node in the specified epoch, scaled by 10^36 + */ + function getNodeEpochScorePerStake(uint256 epoch, uint72 identityId) external view returns (uint256) { + return nodeEpochScorePerStake[epoch][identityId]; + } + + /** + * @dev Adds to the score per stake ratio for a node in a specific epoch + * Can only be called by contracts registered in the Hub + * @param epoch The epoch to add the score per stake to + * @param identityId The node identity ID to add the score per stake for + * @param scorePerStakeToAdd The score per stake amount to add, scaled by 10^36 + */ + function addToNodeEpochScorePerStake( + uint256 epoch, + uint72 identityId, + uint256 scorePerStakeToAdd + ) external onlyContracts { + nodeEpochScorePerStake[epoch][identityId] += scorePerStakeToAdd; + emit NodeEpochScorePerStakeAdded( + epoch, + identityId, + scorePerStakeToAdd, + nodeEpochScorePerStake[epoch][identityId] + ); + } + + /** + * @dev Sets the score per stake ratio for a node in a specific epoch + * Can only be called by contracts registered in the Hub + * @param epoch The epoch to set the score per stake for + * @param identityId The node identity ID to set the score per stake for + * @param scorePerStake The score per stake amount to set, scaled by 10^36 + */ + function setNodeEpochScorePerStake(uint256 epoch, uint72 identityId, uint256 scorePerStake) external onlyContracts { + nodeEpochScorePerStake[epoch][identityId] = scorePerStake; + emit NodeEpochScorePerStakeSet(epoch, identityId, scorePerStake); + } + + /** + * @dev Returns the last settled score per stake value for a delegator + * Used to track reward settlement state for delegators + * @param epoch The epoch to get the last settled score per stake for + * @param identityId The node identity ID the delegator is delegating to + * @param delegatorKey The unique key identifying the delegator + * @return Last settled score per stake value for the delegator, scaled by 10^36 + */ + function getDelegatorLastSettledNodeEpochScorePerStake( + uint256 epoch, + uint72 identityId, + bytes32 delegatorKey + ) external view returns (uint256) { + return delegatorLastSettledNodeEpochScorePerStake[epoch][identityId][delegatorKey]; + } + + /** + * @dev Updates the last settled score per stake value for a delegator + * Can only be called by contracts registered in the Hub + * @param epoch The epoch to update the last settled score per stake for + * @param identityId The node identity ID the delegator is delegating to + * @param delegatorKey The unique key identifying the delegator + * @param newNodeEpochScorePerStake The new score per stake value to set as last settled, scaled by 10^36 + */ + function setDelegatorLastSettledNodeEpochScorePerStake( + uint256 epoch, + uint72 identityId, + bytes32 delegatorKey, + uint256 newNodeEpochScorePerStake + ) external onlyContracts { + delegatorLastSettledNodeEpochScorePerStake[epoch][identityId][delegatorKey] = newNodeEpochScorePerStake; + emit DelegatorLastSettledNodeEpochScorePerStakeSet(epoch, identityId, delegatorKey, newNodeEpochScorePerStake); + } + + /** + * @dev Internal function to check if an address is an owner of the multisig wallet + * Used for access control in administrative functions + * @param multiSigAddress Address of the multisig wallet to check ownership of + * @return True if the caller is an owner of the multisig, false otherwise + */ + function _isMultiSigOwner(address multiSigAddress) internal view returns (bool) { + try ICustodian(multiSigAddress).getOwners() returns (address[] memory multiSigOwners) { + for (uint256 i = 0; i < multiSigOwners.length; i++) { + if (msg.sender == multiSigOwners[i]) { + return true; + } + } // solhint-disable-next-line no-empty-blocks + } catch {} + + return false; + } + + /** + * @dev Internal function to verify that the caller is either the hub owner or a multisig owner + * Used by the onlyOwnerOrMultiSigOwner modifier for access control + */ + function _checkOwnerOrMultiSigOwner() internal view virtual { + address hubOwner = hub.owner(); + if (msg.sender != hubOwner && !_isMultiSigOwner(hubOwner)) { + revert HubLib.UnauthorizedAccess("Only Hub Owner or Multisig Owner"); + } + } +} diff --git a/deploy/021_deploy_delegatorsInfo.ts b/deploy/021_deploy_delegatorsInfo.ts new file mode 100644 index 00000000..3bef68cf --- /dev/null +++ b/deploy/021_deploy_delegatorsInfo.ts @@ -0,0 +1,12 @@ +import { HardhatRuntimeEnvironment } from 'hardhat/types'; +import { DeployFunction } from 'hardhat-deploy/types'; + +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + await hre.helpers.deploy({ + newContractName: 'DelegatorsInfo', + }); +}; + +export default func; +func.tags = ['DelegatorsInfo']; +func.dependencies = ['Hub']; diff --git a/deploy/022_deploy_random_sampling_storage.ts b/deploy/022_deploy_random_sampling_storage.ts new file mode 100644 index 00000000..c9349a7e --- /dev/null +++ b/deploy/022_deploy_random_sampling_storage.ts @@ -0,0 +1,35 @@ +import { HardhatRuntimeEnvironment } from 'hardhat/types'; +import { DeployFunction } from 'hardhat-deploy/types'; + +type RandomSamplingStorageNetworkConfig = { + proofingPeriodDurationInBlocks: string; + W1: string; + W2: string; +}; + +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + const randomSamplingStorageParametersConfig = hre.helpers.parametersConfig[ + hre.network.config.environment + ].RandomSamplingStorage[ + hre.network.name + ] as unknown as RandomSamplingStorageNetworkConfig; + + if (!randomSamplingStorageParametersConfig) { + throw new Error( + `RandomSamplingStorage parameters config not found for network: ${hre.network.name}`, + ); + } + + await hre.helpers.deploy({ + newContractName: 'RandomSamplingStorage', + additionalArgs: [ + randomSamplingStorageParametersConfig.proofingPeriodDurationInBlocks, + randomSamplingStorageParametersConfig.W1, + randomSamplingStorageParametersConfig.W2, + ], + }); +}; + +export default func; +func.tags = ['RandomSamplingStorage']; +func.dependencies = ['Hub']; diff --git a/deploy/021_deploy_staking.ts b/deploy/023_deploy_staking.ts similarity index 87% rename from deploy/021_deploy_staking.ts rename to deploy/023_deploy_staking.ts index 9cda57cd..14af5809 100644 --- a/deploy/021_deploy_staking.ts +++ b/deploy/023_deploy_staking.ts @@ -20,4 +20,8 @@ func.dependencies = [ 'StakingStorage', 'NodeOperatorFeesStorage', 'Ask', + 'DelegatorsInfo', + 'Chronos', + 'RandomSamplingStorage', + 'EpochStorage', ]; diff --git a/deploy/024_deploy_staking_kpi.ts b/deploy/024_deploy_staking_kpi.ts new file mode 100644 index 00000000..0ec20ff6 --- /dev/null +++ b/deploy/024_deploy_staking_kpi.ts @@ -0,0 +1,21 @@ +import { HardhatRuntimeEnvironment } from 'hardhat/types'; +import { DeployFunction } from 'hardhat-deploy/types'; + +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + await hre.helpers.deploy({ + newContractName: 'StakingKPI', + }); +}; + +export default func; +func.tags = ['StakingKPI']; +func.dependencies = [ + 'Hub', + 'IdentityStorage', + 'ProfileStorage', + 'StakingStorage', + 'DelegatorsInfo', + 'RandomSamplingStorage', + 'EpochStorage', + 'ParametersStorage', +]; diff --git a/deploy/022_deploy_profile.ts b/deploy/025_deploy_profile.ts similarity index 93% rename from deploy/022_deploy_profile.ts rename to deploy/025_deploy_profile.ts index 2ecb2a4d..fd04fb7e 100644 --- a/deploy/022_deploy_profile.ts +++ b/deploy/025_deploy_profile.ts @@ -17,4 +17,6 @@ func.dependencies = [ 'ProfileStorage', 'WhitelistStorage', 'Ask', + 'DelegatorsInfo', + 'Chronos', ]; diff --git a/deploy/023_deploy_knowledge_collection.ts b/deploy/026_deploy_knowledge_collection.ts similarity index 100% rename from deploy/023_deploy_knowledge_collection.ts rename to deploy/026_deploy_knowledge_collection.ts diff --git a/deploy/024_deploy_paranet_staging_registry.ts b/deploy/027_deploy_paranet_staging_registry.ts similarity index 100% rename from deploy/024_deploy_paranet_staging_registry.ts rename to deploy/027_deploy_paranet_staging_registry.ts diff --git a/deploy/028_deploy_migrator.ts b/deploy/028_deploy_migrator.ts deleted file mode 100644 index 6a06ea38..00000000 --- a/deploy/028_deploy_migrator.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { HardhatRuntimeEnvironment } from 'hardhat/types'; -import { DeployFunction } from 'hardhat-deploy/types'; - -const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { - const oldHubAddress = - hre.helpers.contractDeployments.contracts['OldHub']?.evmAddress; - - if (hre.network.config.environment === 'development' || !oldHubAddress) { - return; - } - - const Migrator = await hre.helpers.deploy({ - newContractName: 'Migrator', - additionalArgs: [oldHubAddress], - }); - - hre.helpers.setParametersEncodedData.push({ - contractName: 'Migrator', - encodedData: [ - Migrator.interface.encodeFunctionData('initializeOldContracts', []), - Migrator.interface.encodeFunctionData('initializeNewContracts', []), - ], - }); -}; - -export default func; -func.tags = ['Migrator']; -func.dependencies = [ - 'Hub', - 'IdentityStorage', - 'ProfileStorage', - 'StakingStorage', - 'Ask', -]; diff --git a/deploy/025_deploy_paranet.ts b/deploy/028_deploy_paranet.ts similarity index 100% rename from deploy/025_deploy_paranet.ts rename to deploy/028_deploy_paranet.ts diff --git a/deploy/026_deploy_paranet_Incentives_pool_factory_helper.ts b/deploy/029_deploy_paranet_Incentives_pool_factory_helper.ts similarity index 100% rename from deploy/026_deploy_paranet_Incentives_pool_factory_helper.ts rename to deploy/029_deploy_paranet_Incentives_pool_factory_helper.ts diff --git a/deploy/027_deploy_paranet_incentives_pool_factory.ts b/deploy/030_deploy_paranet_incentives_pool_factory.ts similarity index 100% rename from deploy/027_deploy_paranet_incentives_pool_factory.ts rename to deploy/030_deploy_paranet_incentives_pool_factory.ts diff --git a/deploy/031_deploy_random_sampling.ts b/deploy/031_deploy_random_sampling.ts new file mode 100644 index 00000000..c5d6c4e2 --- /dev/null +++ b/deploy/031_deploy_random_sampling.ts @@ -0,0 +1,25 @@ +import { HardhatRuntimeEnvironment } from 'hardhat/types'; +import { DeployFunction } from 'hardhat-deploy/types'; + +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + await hre.helpers.deploy({ + newContractName: 'RandomSampling', + }); +}; + +export default func; +func.tags = ['RandomSampling']; +func.dependencies = [ + 'Hub', + 'Chronos', + 'RandomSamplingStorage', + 'StakingStorage', + 'ProfileStorage', + 'EpochStorage', + 'AskStorage', + 'DelegatorsInfo', + 'KnowledgeCollectionStorage', + 'IdentityStorage', + 'ShardingTableStorage', + 'ParametersStorage', +]; diff --git a/deploy/032_deploy_migratorM1V8.ts b/deploy/032_deploy_migratorM1V8.ts new file mode 100644 index 00000000..80e4f867 --- /dev/null +++ b/deploy/032_deploy_migratorM1V8.ts @@ -0,0 +1,48 @@ +import { HardhatRuntimeEnvironment } from 'hardhat/types'; +import { DeployFunction } from 'hardhat-deploy/types'; + +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + const oldHubAddress = + hre.helpers.contractDeployments.contracts['OldHub']?.evmAddress; + const V8HubAddress = + hre.helpers.contractDeployments.contracts['Hub']?.evmAddress; + + if (hre.network.config.environment === 'development' || !oldHubAddress) { + console.log( + 'Skipping MigratorM1V8 deployment: development environment or missing old hub address', + ); + return; + } + + console.log(`Deploying MigratorM1V8 with:`); + console.log(` New Hub: ${V8HubAddress}`); + console.log(` Old Hub: ${oldHubAddress}`); + + const MigratorM1V8 = await hre.helpers.deploy({ + newContractName: 'MigratorM1V8', + passHubInConstructor: false, + additionalArgs: [V8HubAddress, oldHubAddress], + }); + + // Set up initialization calls for the migrator + // These will be executed after deployment to connect to old and new contract systems + hre.helpers.setParametersEncodedData.push({ + contractName: 'MigratorM1V8', + encodedData: [ + MigratorM1V8.interface.encodeFunctionData('initializeOldContracts', []), + MigratorM1V8.interface.encodeFunctionData('initializeNewContracts', []), + ], + }); + + console.log(`MigratorM1V8 deployed at: ${await MigratorM1V8.getAddress()}`); +}; + +export default func; +func.tags = ['MigratorM1V8']; +func.dependencies = [ + 'Hub', + 'IdentityStorage', + 'ProfileStorage', + 'StakingStorage', + 'Ask', +]; diff --git a/deployments/base_sepolia_test_contracts.json b/deployments/base_sepolia_test_contracts.json index f4f22961..cf1a69bc 100644 --- a/deployments/base_sepolia_test_contracts.json +++ b/deployments/base_sepolia_test_contracts.json @@ -146,30 +146,30 @@ "deployed": true }, "Ask": { - "evmAddress": "0x55c8d5AB131286Fc09bD586131449756a69C4e8E", + "evmAddress": "0xeBc4766278a8fAfAa930e309BC7523a0e71aC138", "version": "1.0.0", - "gitBranch": "v8-contracts", - "gitCommitHash": "ddb3f9e1ef7c2f9f7ca8554b19fae7d521a5507f", - "deploymentBlock": 19684794, - "deploymentTimestamp": 1735137882248, + "gitBranch": "release/reworked-staking", + "gitCommitHash": "7a489bac60a752cbfa8ae52a2ee23a561db4557c", + "deploymentBlock": 26725269, + "deploymentTimestamp": 1749218830084, "deployed": true }, "Staking": { - "evmAddress": "0x53206d344C47c4A8b3AACF99273342331928cb06", - "version": "1.0.0", - "gitBranch": "v8-contracts", - "gitCommitHash": "ddb3f9e1ef7c2f9f7ca8554b19fae7d521a5507f", - "deploymentBlock": 19684799, - "deploymentTimestamp": 1735137892397, + "evmAddress": "0xC448740F566AEbcCf22EF22a43d313A5E3bdbC99", + "version": "1.0.1", + "gitBranch": "release/reworked-staking", + "gitCommitHash": "67ad1cd45d09aa6603a881d83ade56f17fac6fb7", + "deploymentBlock": 27343725, + "deploymentTimestamp": 1750455742292, "deployed": true }, "Profile": { - "evmAddress": "0x13Af909944f34AeF37bf5bEb542Df94fF51c23cD", + "evmAddress": "0xF5F59870c9eBe8B8942Fd3C234EA5f46980d650f", "version": "1.0.0", - "gitBranch": "v8-contracts", - "gitCommitHash": "ddb3f9e1ef7c2f9f7ca8554b19fae7d521a5507f", - "deploymentBlock": 19684804, - "deploymentTimestamp": 1735137901423, + "gitBranch": "release/reworked-staking", + "gitCommitHash": "e660b9adf0736cb63f25ad66a57c67dda84351c3", + "deploymentBlock": 27158859, + "deploymentTimestamp": 1750086011529, "deployed": true }, "Migrator": { @@ -182,12 +182,12 @@ "deployed": true }, "KnowledgeCollection": { - "evmAddress": "0xAF09267e228E5D529732497BF20d652d10278a6e", + "evmAddress": "0x58bf70BcEc83E41bC15aB92f0A0AF44CD34889a6", "version": "1.0.0", - "gitBranch": "fix/remove-kc-update", - "gitCommitHash": "59a62815b3d8c5deffdf8da44dd5ace4655052ed", - "deploymentBlock": 20972223, - "deploymentTimestamp": 1737712739031, + "gitBranch": "release/reworked-staking", + "gitCommitHash": "aa7aec7036926a6f988949f04f883858a5b9b4ca", + "deploymentBlock": 27324442, + "deploymentTimestamp": 1750417175913, "deployed": true }, "ParanetsRegistry": { @@ -261,6 +261,42 @@ "deploymentBlock": 22788786, "deploymentTimestamp": 1741345864175, "deployed": true + }, + "DelegatorsInfo": { + "evmAddress": "0x2bDb37901cBF74a404c891ea5AF1a0f8E439c114", + "version": "1.0.0", + "gitBranch": "release/reworked-staking", + "gitCommitHash": "e660b9adf0736cb63f25ad66a57c67dda84351c3", + "deploymentBlock": 27158845, + "deploymentTimestamp": 1750085983302, + "deployed": true + }, + "RandomSamplingStorage": { + "evmAddress": "0xdf00326263B0aBA1975D64e516887F913EcE4c3B", + "version": "1.0.0", + "gitBranch": "release/reworked-staking", + "gitCommitHash": "aa7aec7036926a6f988949f04f883858a5b9b4ca", + "deploymentBlock": 27324436, + "deploymentTimestamp": 1750417163610, + "deployed": true + }, + "RandomSampling": { + "evmAddress": "0x3DCf196341d450Fb9Fb4a3Fea9894f7473002399", + "version": "1.0.0", + "gitBranch": "release/reworked-staking", + "gitCommitHash": "aa7aec7036926a6f988949f04f883858a5b9b4ca", + "deploymentBlock": 27324445, + "deploymentTimestamp": 1750417182102, + "deployed": true + }, + "StakingKPI": { + "evmAddress": "0x26485ff2E548ACA1AF4B50f765AF6Bc26dBE64E6", + "version": "1.0.0", + "gitBranch": "release/reworked-staking", + "gitCommitHash": "aa7aec7036926a6f988949f04f883858a5b9b4ca", + "deploymentBlock": 27324439, + "deploymentTimestamp": 1750417169758, + "deployed": true } } } diff --git a/deployments/gnosis_chiado_test_contracts.json b/deployments/gnosis_chiado_test_contracts.json index 3964285a..3218d678 100644 --- a/deployments/gnosis_chiado_test_contracts.json +++ b/deployments/gnosis_chiado_test_contracts.json @@ -146,39 +146,39 @@ "deployed": true }, "Ask": { - "evmAddress": "0xAB454CAC31f29c714dF7d61bbf0EA877889f4c25", + "evmAddress": "0x99aaf878f85A6aD905159c9D1c12BFFc58454501", "version": "1.0.0", - "gitBranch": "v8-contracts", - "gitCommitHash": "ddb3f9e1ef7c2f9f7ca8554b19fae7d521a5507f", - "deploymentBlock": 13494291, - "deploymentTimestamp": 1735137931936, + "gitBranch": "feature/random-sampling", + "gitCommitHash": "f9a27fe39e560294dfaa3035a3977eb52aea9a8f", + "deploymentBlock": 15645173, + "deploymentTimestamp": 1746624945008, "deployed": true }, "Staking": { - "evmAddress": "0x379160686f3f31c26BcF0b033374601556cB5f96", - "version": "1.0.0", - "gitBranch": "v8-contracts", - "gitCommitHash": "ddb3f9e1ef7c2f9f7ca8554b19fae7d521a5507f", - "deploymentBlock": 13494293, - "deploymentTimestamp": 1735137944317, + "evmAddress": "0xc0372fBE1765578B2071A5B9C5280f6130Ae8195", + "version": "1.0.1", + "gitBranch": "release/reworked-staking", + "gitCommitHash": "67ad1cd45d09aa6603a881d83ade56f17fac6fb7", + "deploymentBlock": 16363121, + "deploymentTimestamp": 1750455757392, "deployed": true }, "Profile": { - "evmAddress": "0x222C3a2b2A7c2E714771bFc099C8b5B9Be56872F", + "evmAddress": "0x0a569BF13CA78FC1672ef679e4c7276A6516849F", "version": "1.0.0", - "gitBranch": "v8-contracts", - "gitCommitHash": "ddb3f9e1ef7c2f9f7ca8554b19fae7d521a5507f", - "deploymentBlock": 13494296, - "deploymentTimestamp": 1735137963842, + "gitBranch": "release/reworked-staking", + "gitCommitHash": "e660b9adf0736cb63f25ad66a57c67dda84351c3", + "deploymentBlock": 16294025, + "deploymentTimestamp": 1750086032601, "deployed": true }, "KnowledgeCollection": { - "evmAddress": "0x27F52c0d7289A982D76F74De1adeFBFCB1EB8ed8", + "evmAddress": "0x3DCf196341d450Fb9Fb4a3Fea9894f7473002399", "version": "1.0.0", - "gitBranch": "v8-paranet-update", - "gitCommitHash": "b3ce1bc042e3c5f28f93758e750f9f0e1cbcdee5", - "deploymentBlock": 13947424, - "deploymentTimestamp": 1737552337932, + "gitBranch": "release/reworked-staking", + "gitCommitHash": "aa7aec7036926a6f988949f04f883858a5b9b4ca", + "deploymentBlock": 16355927, + "deploymentTimestamp": 1750417218270, "deployed": true }, "Migrator": { @@ -261,6 +261,51 @@ "deploymentBlock": 14659414, "deploymentTimestamp": 1741345656892, "deployed": true + }, + "DelegatorsInfo": { + "evmAddress": "0xB168292cA0E05A75d1A0590eb1dd3a94dBDBb7e4", + "version": "1.0.0", + "gitBranch": "release/reworked-staking", + "gitCommitHash": "e660b9adf0736cb63f25ad66a57c67dda84351c3", + "deploymentBlock": 16294020, + "deploymentTimestamp": 1750086005918, + "deployed": true + }, + "RandomSamplingStorage": { + "evmAddress": "0x26485ff2E548ACA1AF4B50f765AF6Bc26dBE64E6", + "version": "1.0.0", + "gitBranch": "release/reworked-staking", + "gitCommitHash": "aa7aec7036926a6f988949f04f883858a5b9b4ca", + "deploymentBlock": 16355924, + "deploymentTimestamp": 1750417196279, + "deployed": true + }, + "RandomSampling": { + "evmAddress": "0xe0a3fD8C3C701b19C6601aF9824174AaA5A051A2", + "version": "1.0.0", + "gitBranch": "release/reworked-staking", + "gitCommitHash": "aa7aec7036926a6f988949f04f883858a5b9b4ca", + "deploymentBlock": 16355929, + "deploymentTimestamp": 1750417226924, + "deployed": true + }, + "StakingKPI": { + "evmAddress": "0x58bf70BcEc83E41bC15aB92f0A0AF44CD34889a6", + "version": "1.0.0", + "gitBranch": "release/reworked-staking", + "gitCommitHash": "aa7aec7036926a6f988949f04f883858a5b9b4ca", + "deploymentBlock": 16355925, + "deploymentTimestamp": 1750417209469, + "deployed": true + }, + "MigratorM1V8": { + "evmAddress": "0xB46A7bF33fD34a710Cf497196bEb7c17a0af56Fc", + "version": null, + "gitBranch": "feature/m1-v8-migrator", + "gitCommitHash": "e65e131489c038790ca6117c757dce4783d6dfc5", + "deploymentBlock": 16357950, + "deploymentTimestamp": 1750427976240, + "deployed": true } } } diff --git a/deployments/neuroweb_testnet_contracts.json b/deployments/neuroweb_testnet_contracts.json index 0f8c2bd8..e5e9ddf0 100644 --- a/deployments/neuroweb_testnet_contracts.json +++ b/deployments/neuroweb_testnet_contracts.json @@ -162,43 +162,43 @@ "deployed": true }, "Ask": { - "evmAddress": "0x4F823cfFa6b051Fa0321FA2963F4073589A27B54", - "substrateAddress": "5EMjsczc79k5aRA7wb1CLiCy6E51RHLoLTkvDk49iLkJ6BL9", + "evmAddress": "0x16cE77136A6bdf09a622665E8c626C3aE4a9d5D4", + "substrateAddress": "5EMjsczQkBKmabbzKnXMCtmV3RLWkA3Uxoo9WhpPQgcdhKvj", "version": "1.0.0", - "gitBranch": "main", - "gitCommitHash": "04baf6bee66a9023a60acedf00b82d1152e31a17", - "deploymentBlock": 7064209, - "deploymentTimestamp": 1744106191737, + "gitBranch": "feature/random-sampling", + "gitCommitHash": "f9a27fe39e560294dfaa3035a3977eb52aea9a8f", + "deploymentBlock": 7437670, + "deploymentTimestamp": 1746625028380, "deployed": true }, "Staking": { - "evmAddress": "0xF8da4B3BbEBFdEf157BbF4E35A203b41B3F1aca9", - "substrateAddress": "5EMjsd1C3CsC2vPhB8GdqED5kw42tu46VyGhLynXjXVGsE4s", - "version": "1.0.0", - "gitBranch": "main", - "gitCommitHash": "04baf6bee66a9023a60acedf00b82d1152e31a17", - "deploymentBlock": 7064210, - "deploymentTimestamp": 1744106196840, + "evmAddress": "0x1670Ae201b1D988B11313c3E7b01f92A37899527", + "substrateAddress": "5EMjsczQfvPM5o5wUqwvHmRsn9A8AFud8oEmPXmi8MqqoCwp", + "version": "1.0.1", + "gitBranch": "release/reworked-staking", + "gitCommitHash": "67ad1cd45d09aa6603a881d83ade56f17fac6fb7", + "deploymentBlock": 8012334, + "deploymentTimestamp": 1750455783624, "deployed": true }, "Profile": { - "evmAddress": "0x94b4b5bd973c42065059C9635EF6432e6b1Dc6a7", - "substrateAddress": "5EMjsczqyLRQ8owpW8UYk3UMipKdpmuEJQYXZGtuYp9WeLnJ", + "evmAddress": "0x7864f7B82c028605EF40fA0B715442317429f520", + "substrateAddress": "5EMjsczkJJvSGukPUMMPK2magRWRgWVY8wGadHZH8pL9H6PC", "version": "1.0.0", - "gitBranch": "main", - "gitCommitHash": "04baf6bee66a9023a60acedf00b82d1152e31a17", - "deploymentBlock": 7064211, - "deploymentTimestamp": 1744106205918, + "gitBranch": "release/reworked-staking", + "gitCommitHash": "e660b9adf0736cb63f25ad66a57c67dda84351c3", + "deploymentBlock": 7954830, + "deploymentTimestamp": 1750086048864, "deployed": true }, "KnowledgeCollection": { - "evmAddress": "0x0074fab132740ebC4c1335C02DA15fe4Ed34460e", - "substrateAddress": "5EMjsczLGSVtr7mFrs2SMLSN3y2m5NfKRsWBHzM1YAkAMPRZ", + "evmAddress": "0x8534af9D58402daD81B17FA2904e98779E0635e7", + "substrateAddress": "5EMjscznsCWS8WtZoU31ubc54zWCJqyFNsTweHu2Hd8tBDYC", "version": "1.0.0", - "gitBranch": "main", - "gitCommitHash": "04baf6bee66a9023a60acedf00b82d1152e31a17", - "deploymentBlock": 7064212, - "deploymentTimestamp": 1744106210995, + "gitBranch": "release/reworked-staking", + "gitCommitHash": "aa7aec7036926a6f988949f04f883858a5b9b4ca", + "deploymentBlock": 8006363, + "deploymentTimestamp": 1750417263693, "deployed": true }, "Migrator": { @@ -209,7 +209,7 @@ "gitCommitHash": "04baf6bee66a9023a60acedf00b82d1152e31a17", "deploymentBlock": 7064218, "deploymentTimestamp": 1744106244945, - "deployed": true + "deployed": false }, "ParanetsRegistry": { "evmAddress": "0x17bb588fdE9e2F69aceAb9A24deE753245E3EAFE", @@ -290,6 +290,46 @@ "deploymentBlock": 7064217, "deploymentTimestamp": 1744106239694, "deployed": true + }, + "DelegatorsInfo": { + "evmAddress": "0x0a569BF13CA78FC1672ef679e4c7276A6516849F", + "substrateAddress": "5EMjsczNFH5ifu2EiXcw7F7KfAxpGdJTSDvjoBwrZ26n1jP8", + "version": "1.0.0", + "gitBranch": "release/reworked-staking", + "gitCommitHash": "e660b9adf0736cb63f25ad66a57c67dda84351c3", + "deploymentBlock": 7954825, + "deploymentTimestamp": 1750086020320, + "deployed": true + }, + "RandomSamplingStorage": { + "evmAddress": "0xC448740F566AEbcCf22EF22a43d313A5E3bdbC99", + "substrateAddress": "5EMjsd11WG1eKK7QXqTLmMFqJct6gnvcSPK5U6Ah65CZakBV", + "version": "1.0.0", + "gitBranch": "release/reworked-staking", + "gitCommitHash": "aa7aec7036926a6f988949f04f883858a5b9b4ca", + "deploymentBlock": 8006361, + "deploymentTimestamp": 1750417245596, + "deployed": true + }, + "RandomSampling": { + "evmAddress": "0x42Fd7cdad11467174Bd13f10bbC31A996e79A986", + "substrateAddress": "5EMjsczZbfYpyNVYg52yTCYaFgoZtUrm5d8w6MPbKxoiL5ck", + "version": "1.0.0", + "gitBranch": "release/reworked-staking", + "gitCommitHash": "aa7aec7036926a6f988949f04f883858a5b9b4ca", + "deploymentBlock": 8006364, + "deploymentTimestamp": 1750417268908, + "deployed": true + }, + "StakingKPI": { + "evmAddress": "0xd791663B5A6c3C356D0051dd727cDD0A247DC84E", + "substrateAddress": "5EMjsd15NP85PKVGgrZifNKhiu85mCHAss2NAzBdKuNfAP2C", + "version": "1.0.0", + "gitBranch": "release/reworked-staking", + "gitCommitHash": "aa7aec7036926a6f988949f04f883858a5b9b4ca", + "deploymentBlock": 8006362, + "deploymentTimestamp": 1750417254677, + "deployed": true } } } diff --git a/deployments/parameters.json b/deployments/parameters.json index ca9cdb6c..c2460554 100644 --- a/deployments/parameters.json +++ b/deployments/parameters.json @@ -17,6 +17,18 @@ "KnowledgeCollectionStorage": { "knowledgeCollectionSize": "1000000", "uriBase": "did:dkg" + }, + "RandomSamplingStorage": { + "hardhat": { + "proofingPeriodDurationInBlocks": "100", + "W1": "0", + "W2": "2" + }, + "localhost": { + "proofingPeriodDurationInBlocks": "100", + "W1": "0", + "W2": "2" + } } }, "devnet": { @@ -38,6 +50,23 @@ "KnowledgeCollectionStorage": { "knowledgeCollectionSize": "1000000", "uriBase": "did:dkg" + }, + "RandomSamplingStorage": { + "base_sepolia_dev": { + "proofingPeriodDurationInBlocks": "900", + "W1": "0", + "W2": "2" + }, + "base_sepolia_stable_dev_staging": { + "proofingPeriodDurationInBlocks": "900", + "W1": "0", + "W2": "2" + }, + "base_sepolia_stable_dev_prod": { + "proofingPeriodDurationInBlocks": "900", + "W1": "0", + "W2": "2" + } } }, "testnet": { @@ -60,6 +89,23 @@ "KnowledgeCollectionStorage": { "knowledgeCollectionSize": "1000000", "uriBase": "did:dkg" + }, + "RandomSamplingStorage": { + "neuroweb_testnet": { + "proofingPeriodDurationInBlocks": "257", + "W1": "0", + "W2": "2" + }, + "gnosis_chiado_test": { + "proofingPeriodDurationInBlocks": "360", + "W1": "0", + "W2": "2" + }, + "base_sepolia_test": { + "proofingPeriodDurationInBlocks": "900", + "W1": "0", + "W2": "2" + } } }, "mainnet": { @@ -82,6 +128,23 @@ "KnowledgeCollectionStorage": { "knowledgeCollectionSize": "1000000", "uriBase": "did:dkg" + }, + "RandomSamplingStorage": { + "neuroweb_mainnet": { + "proofingPeriodDurationInBlocks": "300", + "W1": "0", + "W2": "2" + }, + "gnosis_mainnet": { + "proofingPeriodDurationInBlocks": "360", + "W1": "0", + "W2": "2" + }, + "base_mainnet": { + "proofingPeriodDurationInBlocks": "900", + "W1": "0", + "W2": "2" + } } } } diff --git a/package-lock.json b/package-lock.json index 06ab018c..792109d9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "dkg-evm-module", - "version": "8.0.1", - "lockfileVersion": 2, + "version": "8.0.5", + "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "dkg-evm-module", - "version": "8.0.1", + "version": "8.0.5", "license": "Apache-2.0", "dependencies": { "@openzeppelin/contracts": "^5.1.0", @@ -24,6 +24,7 @@ "typescript": "^5.7.2" }, "devDependencies": { + "@nomicfoundation/ethereumjs-util": "^9.0.4", "@nomicfoundation/hardhat-chai-matchers": "^2.0.8", "@nomicfoundation/hardhat-network-helpers": "^1.0.12", "@nomiclabs/hardhat-solhint": "^4.0.1", @@ -34,7 +35,7 @@ "@types/node": "^22.10.2", "@typescript-eslint/eslint-plugin": "^8.18.1", "@typescript-eslint/parser": "^8.18.1", - "assertion-tools": "^2.2.1", + "assertion-tools": "^8.0.3", "chai": "^4.5.0", "cross-env": "^7.0.3", "eslint": "^8.17.0", @@ -59,10 +60,9 @@ } }, "node_modules/@adraffy/ens-normalize": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.0.tgz", - "integrity": "sha512-nA9XHtlAkYfJxY7bce8DcN7eKxWWCWkU+1GR9d+U6MbNpfwQp8TI7vqOsBsMcHoT4mBu2kypKoSKnghEzOOq5Q==", - "dev": true, + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz", + "integrity": "sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==", "license": "MIT" }, "node_modules/@babel/code-frame": { @@ -95,6 +95,7 @@ "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", "dev": true, + "license": "MIT", "optional": true, "engines": { "node": ">=0.1.90" @@ -104,6 +105,7 @@ "version": "0.8.1", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "license": "MIT", "dependencies": { "@jridgewell/trace-mapping": "0.3.9" }, @@ -112,23 +114,58 @@ } }, "node_modules/@digitalbazaar/http-client": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@digitalbazaar/http-client/-/http-client-3.2.0.tgz", - "integrity": "sha512-NhYXcWE/JDE7AnJikNX7q0S6zNuUPA2NuIoRdUpmvHlarjmRqyr6hIO3Awu2FxlUzbdiI1uzuWrZyB9mD1tTvw==", + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/@digitalbazaar/http-client/-/http-client-3.4.1.tgz", + "integrity": "sha512-Ahk1N+s7urkgj7WvvUND5f8GiWEPfUw0D41hdElaqLgu8wZScI8gdI0q+qWw5N1d35x7GCRH2uk9mi+Uzo9M3g==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { - "ky": "^0.30.0", - "ky-universal": "^0.10.1", - "undici": "^5.2.0" + "ky": "^0.33.3", + "ky-universal": "^0.11.0", + "undici": "^5.21.2" }, "engines": { "node": ">=14.0" } }, + "node_modules/@emnapi/core": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.4.3.tgz", + "integrity": "sha512-4m62DuCE07lw01soJwPiBGC0nAww0Q+RY70VZ+n49yDIO13yyinhbWCeNnaob0lakDtWQzSdtNWzJeOJt2ma+g==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.0.2", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.4.3.tgz", + "integrity": "sha512-pBPWdu6MLKROBX05wSNKcNb++m5Er+KQ9QkB+WVM+pW2Kx9hoSrVTnu3BdkI5eBLZoKu/J6mW/B6i6bJB2ytXQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.0.2.tgz", + "integrity": "sha512-5n3nTJblwRi8LlXkJ9eBzu+kZR8Yxcc7ubakyQTFzPMtIhFpUBRbsnc2Dv88IZDIbCDlBiWrknhB4Lsz7mg6BA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz", - "integrity": "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==", + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.6.1.tgz", + "integrity": "sha512-KTsJMmobmbrFLe3LDh0PC2FXpcSYJt/MLjlkh/9LEnmKYLSYmT/0EW9JWANjeoemiuZrmogti0tW5Ch+qNUYDw==", "dev": true, "license": "MIT", "dependencies": { @@ -178,17 +215,28 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/@eslint/eslintrc/node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "license": "MIT", - "engines": { - "node": ">=8" + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": "*" } }, "node_modules/@eslint/js": { @@ -201,10 +249,107 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, + "node_modules/@ethereumjs/rlp": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@ethereumjs/rlp/-/rlp-5.0.2.tgz", + "integrity": "sha512-DziebCdg4JpGlEqEdGgXmjqcFoJi+JGulUXwEjsZGAscAQ7MyD/7LE/GVCP29vEQxKc7AAwjT3A2ywHp2xfoCA==", + "license": "MPL-2.0", + "bin": { + "rlp": "bin/rlp.cjs" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@ethereumjs/util": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/@ethereumjs/util/-/util-9.1.0.tgz", + "integrity": "sha512-XBEKsYqLGXLah9PNJbgdkigthkG7TAGvlD/sH12beMXEyHDyigfcbdvHhmLyDWgDyOJn4QwiQUaF7yeuhnjdog==", + "license": "MPL-2.0", + "dependencies": { + "@ethereumjs/rlp": "^5.0.2", + "ethereum-cryptography": "^2.2.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@ethereumjs/util/node_modules/@noble/curves": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.4.2.tgz", + "integrity": "sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.4.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@ethereumjs/util/node_modules/@noble/hashes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", + "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", + "license": "MIT", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@ethereumjs/util/node_modules/@scure/base": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.9.tgz", + "integrity": "sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg==", + "license": "MIT", + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@ethereumjs/util/node_modules/@scure/bip32": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.4.0.tgz", + "integrity": "sha512-sVUpc0Vq3tXCkDGYVWGIZTRfnvu8LoTDaev7vbwh0omSvVORONr960MQWdKqJDCReIEmTj3PAr73O3aoxz7OPg==", + "license": "MIT", + "dependencies": { + "@noble/curves": "~1.4.0", + "@noble/hashes": "~1.4.0", + "@scure/base": "~1.1.6" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@ethereumjs/util/node_modules/@scure/bip39": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.3.0.tgz", + "integrity": "sha512-disdg7gHuTDZtY+ZdkmLpPCk7fxZSu3gBiEGuoC1XYxv9cGx3Z6cpTggCgW6odSOOIXCiDjuGejW+aJKCY/pIQ==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "~1.4.0", + "@scure/base": "~1.1.6" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@ethereumjs/util/node_modules/ethereum-cryptography": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.2.1.tgz", + "integrity": "sha512-r/W8lkHSiTLxUxW8Rf3u4HGB0xQweG2RyETjywylKZSzLWoWAijRz8WCuOtJ6wah+avllXBqZuk29HCCvhEIRg==", + "license": "MIT", + "dependencies": { + "@noble/curves": "1.4.2", + "@noble/hashes": "1.4.0", + "@scure/bip32": "1.4.0", + "@scure/bip39": "1.3.0" + } + }, "node_modules/@ethersproject/abi": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.7.0.tgz", - "integrity": "sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.8.0.tgz", + "integrity": "sha512-b9YS/43ObplgyV6SlyQsG53/vkSal0MNA1fskSC4mbnCMi8R+NkcH8K9FPYNESf6jUefBUniE4SOKms0E/KK1Q==", "funding": [ { "type": "individual", @@ -215,22 +360,23 @@ "url": "https://www.buymeacoffee.com/ricmoo" } ], + "license": "MIT", "dependencies": { - "@ethersproject/address": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/constants": "^5.7.0", - "@ethersproject/hash": "^5.7.0", - "@ethersproject/keccak256": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/strings": "^5.7.0" + "@ethersproject/address": "^5.8.0", + "@ethersproject/bignumber": "^5.8.0", + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/constants": "^5.8.0", + "@ethersproject/hash": "^5.8.0", + "@ethersproject/keccak256": "^5.8.0", + "@ethersproject/logger": "^5.8.0", + "@ethersproject/properties": "^5.8.0", + "@ethersproject/strings": "^5.8.0" } }, "node_modules/@ethersproject/abstract-provider": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.7.0.tgz", - "integrity": "sha512-R41c9UkchKCpAqStMYUpdunjo3pkEvZC3FAwZn5S5MGbXoMQOHIdHItezTETxAO5bevtMApSyEhn9+CHcDsWBw==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.8.0.tgz", + "integrity": "sha512-wC9SFcmh4UK0oKuLJQItoQdzS/qZ51EJegK6EmAWlh+OptpQ/npECOR3QqECd8iGHC0RJb4WKbVdSfif4ammrg==", "funding": [ { "type": "individual", @@ -241,20 +387,21 @@ "url": "https://www.buymeacoffee.com/ricmoo" } ], + "license": "MIT", "dependencies": { - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/networks": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/transactions": "^5.7.0", - "@ethersproject/web": "^5.7.0" + "@ethersproject/bignumber": "^5.8.0", + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/logger": "^5.8.0", + "@ethersproject/networks": "^5.8.0", + "@ethersproject/properties": "^5.8.0", + "@ethersproject/transactions": "^5.8.0", + "@ethersproject/web": "^5.8.0" } }, "node_modules/@ethersproject/abstract-signer": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.7.0.tgz", - "integrity": "sha512-a16V8bq1/Cz+TGCkE2OPMTOUDLS3grCpdjoJCYNnVBbdYEMSgKrU0+B90s8b6H+ByYTBZN7a3g76jdIJi7UfKQ==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.8.0.tgz", + "integrity": "sha512-N0XhZTswXcmIZQdYtUnd79VJzvEwXQw6PK0dTl9VoYrEBxxCPXqS0Eod7q5TNKRxe1/5WUMuR0u0nqTF/avdCA==", "funding": [ { "type": "individual", @@ -265,18 +412,19 @@ "url": "https://www.buymeacoffee.com/ricmoo" } ], + "license": "MIT", "dependencies": { - "@ethersproject/abstract-provider": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0" + "@ethersproject/abstract-provider": "^5.8.0", + "@ethersproject/bignumber": "^5.8.0", + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/logger": "^5.8.0", + "@ethersproject/properties": "^5.8.0" } }, "node_modules/@ethersproject/address": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.7.0.tgz", - "integrity": "sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.8.0.tgz", + "integrity": "sha512-GhH/abcC46LJwshoN+uBNoKVFPxUuZm6dA257z0vZkKmU1+t8xTn8oK7B9qrj8W2rFRMch4gbJl6PmVxjxBEBA==", "funding": [ { "type": "individual", @@ -287,18 +435,19 @@ "url": "https://www.buymeacoffee.com/ricmoo" } ], + "license": "MIT", "dependencies": { - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/keccak256": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/rlp": "^5.7.0" + "@ethersproject/bignumber": "^5.8.0", + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/keccak256": "^5.8.0", + "@ethersproject/logger": "^5.8.0", + "@ethersproject/rlp": "^5.8.0" } }, "node_modules/@ethersproject/base64": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.7.0.tgz", - "integrity": "sha512-Dr8tcHt2mEbsZr/mwTPIQAf3Ai0Bks/7gTw9dSqk1mQvhW3XvRlmDJr/4n+wg1JmCl16NZue17CDh8xb/vZ0sQ==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.8.0.tgz", + "integrity": "sha512-lN0oIwfkYj9LbPx4xEkie6rAMJtySbpOAFXSDVQaBnAzYfB4X2Qr+FXJGxMoc3Bxp2Sm8OwvzMrywxyw0gLjIQ==", "funding": [ { "type": "individual", @@ -309,14 +458,15 @@ "url": "https://www.buymeacoffee.com/ricmoo" } ], + "license": "MIT", "dependencies": { - "@ethersproject/bytes": "^5.7.0" + "@ethersproject/bytes": "^5.8.0" } }, "node_modules/@ethersproject/basex": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/basex/-/basex-5.7.0.tgz", - "integrity": "sha512-ywlh43GwZLv2Voc2gQVTKBoVQ1mti3d8HK5aMxsfu/nRDnMmNqaSJ3r3n85HBByT8OpoY96SXM1FogC533T4zw==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/basex/-/basex-5.8.0.tgz", + "integrity": "sha512-PIgTszMlDRmNwW9nhS6iqtVfdTAKosA7llYXNmGPw4YAI1PUyMv28988wAb41/gHF/WqGdoLv0erHaRcHRKW2Q==", "funding": [ { "type": "individual", @@ -327,15 +477,16 @@ "url": "https://www.buymeacoffee.com/ricmoo" } ], + "license": "MIT", "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/properties": "^5.7.0" + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/properties": "^5.8.0" } }, "node_modules/@ethersproject/bignumber": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.7.0.tgz", - "integrity": "sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.8.0.tgz", + "integrity": "sha512-ZyaT24bHaSeJon2tGPKIiHszWjD/54Sz8t57Toch475lCLljC6MgPmxk7Gtzz+ddNN5LuHea9qhAe0x3D+uYPA==", "funding": [ { "type": "individual", @@ -346,16 +497,17 @@ "url": "https://www.buymeacoffee.com/ricmoo" } ], + "license": "MIT", "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0", + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/logger": "^5.8.0", "bn.js": "^5.2.1" } }, "node_modules/@ethersproject/bytes": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.7.0.tgz", - "integrity": "sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.8.0.tgz", + "integrity": "sha512-vTkeohgJVCPVHu5c25XWaWQOZ4v+DkGoC42/TS2ond+PARCxTJvgTFUNDZovyQ/uAQ4EcpqqowKydcdmRKjg7A==", "funding": [ { "type": "individual", @@ -366,14 +518,15 @@ "url": "https://www.buymeacoffee.com/ricmoo" } ], + "license": "MIT", "dependencies": { - "@ethersproject/logger": "^5.7.0" + "@ethersproject/logger": "^5.8.0" } }, "node_modules/@ethersproject/constants": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.7.0.tgz", - "integrity": "sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.8.0.tgz", + "integrity": "sha512-wigX4lrf5Vu+axVTIvNsuL6YrV4O5AXl5ubcURKMEME5TnWBouUh0CDTWxZ2GpnRn1kcCgE7l8O5+VbV9QTTcg==", "funding": [ { "type": "individual", @@ -384,14 +537,15 @@ "url": "https://www.buymeacoffee.com/ricmoo" } ], + "license": "MIT", "dependencies": { - "@ethersproject/bignumber": "^5.7.0" + "@ethersproject/bignumber": "^5.8.0" } }, "node_modules/@ethersproject/contracts": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/contracts/-/contracts-5.7.0.tgz", - "integrity": "sha512-5GJbzEU3X+d33CdfPhcyS+z8MzsTrBGk/sc+G+59+tPa9yFkl6HQ9D6L0QMgNTA9q8dT0XKxxkyp883XsQvbbg==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/contracts/-/contracts-5.8.0.tgz", + "integrity": "sha512-0eFjGz9GtuAi6MZwhb4uvUM216F38xiuR0yYCjKJpNfSEy4HUM8hvqqBj9Jmm0IUz8l0xKEhWwLIhPgxNY0yvQ==", "funding": [ { "type": "individual", @@ -402,23 +556,24 @@ "url": "https://www.buymeacoffee.com/ricmoo" } ], + "license": "MIT", "dependencies": { - "@ethersproject/abi": "^5.7.0", - "@ethersproject/abstract-provider": "^5.7.0", - "@ethersproject/abstract-signer": "^5.7.0", - "@ethersproject/address": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/constants": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/transactions": "^5.7.0" + "@ethersproject/abi": "^5.8.0", + "@ethersproject/abstract-provider": "^5.8.0", + "@ethersproject/abstract-signer": "^5.8.0", + "@ethersproject/address": "^5.8.0", + "@ethersproject/bignumber": "^5.8.0", + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/constants": "^5.8.0", + "@ethersproject/logger": "^5.8.0", + "@ethersproject/properties": "^5.8.0", + "@ethersproject/transactions": "^5.8.0" } }, "node_modules/@ethersproject/hash": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.7.0.tgz", - "integrity": "sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.8.0.tgz", + "integrity": "sha512-ac/lBcTbEWW/VGJij0CNSw/wPcw9bSRgCB0AIBz8CvED/jfvDoV9hsIIiWfvWmFEi8RcXtlNwp2jv6ozWOsooA==", "funding": [ { "type": "individual", @@ -429,22 +584,23 @@ "url": "https://www.buymeacoffee.com/ricmoo" } ], + "license": "MIT", "dependencies": { - "@ethersproject/abstract-signer": "^5.7.0", - "@ethersproject/address": "^5.7.0", - "@ethersproject/base64": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/keccak256": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/strings": "^5.7.0" + "@ethersproject/abstract-signer": "^5.8.0", + "@ethersproject/address": "^5.8.0", + "@ethersproject/base64": "^5.8.0", + "@ethersproject/bignumber": "^5.8.0", + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/keccak256": "^5.8.0", + "@ethersproject/logger": "^5.8.0", + "@ethersproject/properties": "^5.8.0", + "@ethersproject/strings": "^5.8.0" } }, "node_modules/@ethersproject/hdnode": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/hdnode/-/hdnode-5.7.0.tgz", - "integrity": "sha512-OmyYo9EENBPPf4ERhR7oj6uAtUAhYGqOnIS+jE5pTXvdKBS99ikzq1E7Iv0ZQZ5V36Lqx1qZLeak0Ra16qpeOg==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/hdnode/-/hdnode-5.8.0.tgz", + "integrity": "sha512-4bK1VF6E83/3/Im0ERnnUeWOY3P1BZml4ZD3wcH8Ys0/d1h1xaFt6Zc+Dh9zXf9TapGro0T4wvO71UTCp3/uoA==", "funding": [ { "type": "individual", @@ -455,25 +611,26 @@ "url": "https://www.buymeacoffee.com/ricmoo" } ], + "license": "MIT", "dependencies": { - "@ethersproject/abstract-signer": "^5.7.0", - "@ethersproject/basex": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/pbkdf2": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/sha2": "^5.7.0", - "@ethersproject/signing-key": "^5.7.0", - "@ethersproject/strings": "^5.7.0", - "@ethersproject/transactions": "^5.7.0", - "@ethersproject/wordlists": "^5.7.0" + "@ethersproject/abstract-signer": "^5.8.0", + "@ethersproject/basex": "^5.8.0", + "@ethersproject/bignumber": "^5.8.0", + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/logger": "^5.8.0", + "@ethersproject/pbkdf2": "^5.8.0", + "@ethersproject/properties": "^5.8.0", + "@ethersproject/sha2": "^5.8.0", + "@ethersproject/signing-key": "^5.8.0", + "@ethersproject/strings": "^5.8.0", + "@ethersproject/transactions": "^5.8.0", + "@ethersproject/wordlists": "^5.8.0" } }, "node_modules/@ethersproject/json-wallets": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/json-wallets/-/json-wallets-5.7.0.tgz", - "integrity": "sha512-8oee5Xgu6+RKgJTkvEMl2wDgSPSAQ9MB/3JYjFV9jlKvcYHUXZC+cQp0njgmxdHkYWn8s6/IqIZYm0YWCjO/0g==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/json-wallets/-/json-wallets-5.8.0.tgz", + "integrity": "sha512-HxblNck8FVUtNxS3VTEYJAcwiKYsBIF77W15HufqlBF9gGfhmYOJtYZp8fSDZtn9y5EaXTE87zDwzxRoTFk11w==", "funding": [ { "type": "individual", @@ -484,26 +641,33 @@ "url": "https://www.buymeacoffee.com/ricmoo" } ], + "license": "MIT", "dependencies": { - "@ethersproject/abstract-signer": "^5.7.0", - "@ethersproject/address": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/hdnode": "^5.7.0", - "@ethersproject/keccak256": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/pbkdf2": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/random": "^5.7.0", - "@ethersproject/strings": "^5.7.0", - "@ethersproject/transactions": "^5.7.0", + "@ethersproject/abstract-signer": "^5.8.0", + "@ethersproject/address": "^5.8.0", + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/hdnode": "^5.8.0", + "@ethersproject/keccak256": "^5.8.0", + "@ethersproject/logger": "^5.8.0", + "@ethersproject/pbkdf2": "^5.8.0", + "@ethersproject/properties": "^5.8.0", + "@ethersproject/random": "^5.8.0", + "@ethersproject/strings": "^5.8.0", + "@ethersproject/transactions": "^5.8.0", "aes-js": "3.0.0", "scrypt-js": "3.0.1" } }, + "node_modules/@ethersproject/json-wallets/node_modules/aes-js": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.0.0.tgz", + "integrity": "sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw==", + "license": "MIT" + }, "node_modules/@ethersproject/keccak256": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.7.0.tgz", - "integrity": "sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.8.0.tgz", + "integrity": "sha512-A1pkKLZSz8pDaQ1ftutZoaN46I6+jvuqugx5KYNeQOPqq+JZ0Txm7dlWesCHB5cndJSu5vP2VKptKf7cksERng==", "funding": [ { "type": "individual", @@ -514,15 +678,16 @@ "url": "https://www.buymeacoffee.com/ricmoo" } ], + "license": "MIT", "dependencies": { - "@ethersproject/bytes": "^5.7.0", + "@ethersproject/bytes": "^5.8.0", "js-sha3": "0.8.0" } }, "node_modules/@ethersproject/logger": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.7.0.tgz", - "integrity": "sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.8.0.tgz", + "integrity": "sha512-Qe6knGmY+zPPWTC+wQrpitodgBfH7XoceCGL5bJVejmH+yCS3R8jJm8iiWuvWbG76RUmyEG53oqv6GMVWqunjA==", "funding": [ { "type": "individual", @@ -532,12 +697,13 @@ "type": "individual", "url": "https://www.buymeacoffee.com/ricmoo" } - ] + ], + "license": "MIT" }, "node_modules/@ethersproject/networks": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.7.1.tgz", - "integrity": "sha512-n/MufjFYv3yFcUyfhnXotyDlNdFb7onmkSy8aQERi2PjNcnWQ66xXxa3XlS8nCcA8aJKJjIIMNJTC7tu80GwpQ==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.8.0.tgz", + "integrity": "sha512-egPJh3aPVAzbHwq8DD7Po53J4OUSsA1MjQp8Vf/OZPav5rlmWUaFLiq8cvQiGK0Z5K6LYzm29+VA/p4RL1FzNg==", "funding": [ { "type": "individual", @@ -548,14 +714,15 @@ "url": "https://www.buymeacoffee.com/ricmoo" } ], + "license": "MIT", "dependencies": { - "@ethersproject/logger": "^5.7.0" + "@ethersproject/logger": "^5.8.0" } }, "node_modules/@ethersproject/pbkdf2": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/pbkdf2/-/pbkdf2-5.7.0.tgz", - "integrity": "sha512-oR/dBRZR6GTyaofd86DehG72hY6NpAjhabkhxgr3X2FpJtJuodEl2auADWBZfhDHgVCbu3/H/Ocq2uC6dpNjjw==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/pbkdf2/-/pbkdf2-5.8.0.tgz", + "integrity": "sha512-wuHiv97BrzCmfEaPbUFpMjlVg/IDkZThp9Ri88BpjRleg4iePJaj2SW8AIyE8cXn5V1tuAaMj6lzvsGJkGWskg==", "funding": [ { "type": "individual", @@ -566,15 +733,16 @@ "url": "https://www.buymeacoffee.com/ricmoo" } ], + "license": "MIT", "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/sha2": "^5.7.0" + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/sha2": "^5.8.0" } }, "node_modules/@ethersproject/properties": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.7.0.tgz", - "integrity": "sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.8.0.tgz", + "integrity": "sha512-PYuiEoQ+FMaZZNGrStmN7+lWjlsoufGIHdww7454FIaGdbe/p5rnaCXTr5MtBYl3NkeoVhHZuyzChPeGeKIpQw==", "funding": [ { "type": "individual", @@ -585,14 +753,15 @@ "url": "https://www.buymeacoffee.com/ricmoo" } ], + "license": "MIT", "dependencies": { - "@ethersproject/logger": "^5.7.0" + "@ethersproject/logger": "^5.8.0" } }, "node_modules/@ethersproject/providers": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/@ethersproject/providers/-/providers-5.7.2.tgz", - "integrity": "sha512-g34EWZ1WWAVgr4aptGlVBF8mhl3VWjv+8hoAnzStu8Ah22VHBsuGzP17eb6xDVRzw895G4W7vvx60lFFur/1Rg==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/providers/-/providers-5.8.0.tgz", + "integrity": "sha512-3Il3oTzEx3o6kzcg9ZzbE+oCZYyY+3Zh83sKkn4s1DZfTUjIegHnN2Cm0kbn9YFy45FDVcuCLLONhU7ny0SsCw==", "funding": [ { "type": "individual", @@ -603,39 +772,41 @@ "url": "https://www.buymeacoffee.com/ricmoo" } ], + "license": "MIT", "dependencies": { - "@ethersproject/abstract-provider": "^5.7.0", - "@ethersproject/abstract-signer": "^5.7.0", - "@ethersproject/address": "^5.7.0", - "@ethersproject/base64": "^5.7.0", - "@ethersproject/basex": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/constants": "^5.7.0", - "@ethersproject/hash": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/networks": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/random": "^5.7.0", - "@ethersproject/rlp": "^5.7.0", - "@ethersproject/sha2": "^5.7.0", - "@ethersproject/strings": "^5.7.0", - "@ethersproject/transactions": "^5.7.0", - "@ethersproject/web": "^5.7.0", + "@ethersproject/abstract-provider": "^5.8.0", + "@ethersproject/abstract-signer": "^5.8.0", + "@ethersproject/address": "^5.8.0", + "@ethersproject/base64": "^5.8.0", + "@ethersproject/basex": "^5.8.0", + "@ethersproject/bignumber": "^5.8.0", + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/constants": "^5.8.0", + "@ethersproject/hash": "^5.8.0", + "@ethersproject/logger": "^5.8.0", + "@ethersproject/networks": "^5.8.0", + "@ethersproject/properties": "^5.8.0", + "@ethersproject/random": "^5.8.0", + "@ethersproject/rlp": "^5.8.0", + "@ethersproject/sha2": "^5.8.0", + "@ethersproject/strings": "^5.8.0", + "@ethersproject/transactions": "^5.8.0", + "@ethersproject/web": "^5.8.0", "bech32": "1.1.4", - "ws": "7.4.6" + "ws": "8.18.0" } }, "node_modules/@ethersproject/providers/node_modules/ws": { - "version": "7.4.6", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz", - "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "license": "MIT", "engines": { - "node": ">=8.3.0" + "node": ">=10.0.0" }, "peerDependencies": { "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" + "utf-8-validate": ">=5.0.2" }, "peerDependenciesMeta": { "bufferutil": { @@ -647,9 +818,9 @@ } }, "node_modules/@ethersproject/random": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/random/-/random-5.7.0.tgz", - "integrity": "sha512-19WjScqRA8IIeWclFme75VMXSBvi4e6InrUNuaR4s5pTF2qNhcGdCUwdxUVGtDDqC00sDLCO93jPQoDUH4HVmQ==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/random/-/random-5.8.0.tgz", + "integrity": "sha512-E4I5TDl7SVqyg4/kkA/qTfuLWAQGXmSOgYyO01So8hLfwgKvYK5snIlzxJMk72IFdG/7oh8yuSqY2KX7MMwg+A==", "funding": [ { "type": "individual", @@ -660,15 +831,16 @@ "url": "https://www.buymeacoffee.com/ricmoo" } ], + "license": "MIT", "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0" + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/logger": "^5.8.0" } }, "node_modules/@ethersproject/rlp": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.7.0.tgz", - "integrity": "sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.8.0.tgz", + "integrity": "sha512-LqZgAznqDbiEunaUvykH2JAoXTT9NV0Atqk8rQN9nx9SEgThA/WMx5DnW8a9FOufo//6FZOCHZ+XiClzgbqV9Q==", "funding": [ { "type": "individual", @@ -679,15 +851,16 @@ "url": "https://www.buymeacoffee.com/ricmoo" } ], + "license": "MIT", "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0" + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/logger": "^5.8.0" } }, "node_modules/@ethersproject/sha2": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/sha2/-/sha2-5.7.0.tgz", - "integrity": "sha512-gKlH42riwb3KYp0reLsFTokByAKoJdgFCwI+CCiX/k+Jm2mbNs6oOaCjYQSlI1+XBVejwH2KrmCbMAT/GnRDQw==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/sha2/-/sha2-5.8.0.tgz", + "integrity": "sha512-dDOUrXr9wF/YFltgTBYS0tKslPEKr6AekjqDW2dbn1L1xmjGR+9GiKu4ajxovnrDbwxAKdHjW8jNcwfz8PAz4A==", "funding": [ { "type": "individual", @@ -698,16 +871,17 @@ "url": "https://www.buymeacoffee.com/ricmoo" } ], + "license": "MIT", "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0", + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/logger": "^5.8.0", "hash.js": "1.1.7" } }, "node_modules/@ethersproject/signing-key": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.7.0.tgz", - "integrity": "sha512-MZdy2nL3wO0u7gkB4nA/pEf8lu1TlFswPNmy8AiYkfKTdO6eXBJyUdmHO/ehm/htHw9K/qF8ujnTyUAD+Ry54Q==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.8.0.tgz", + "integrity": "sha512-LrPW2ZxoigFi6U6aVkFN/fa9Yx/+4AtIUe4/HACTvKJdhm0eeb107EVCIQcrLZkxaSIgc/eCrX8Q1GtbH+9n3w==", "funding": [ { "type": "individual", @@ -718,19 +892,20 @@ "url": "https://www.buymeacoffee.com/ricmoo" } ], + "license": "MIT", "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/logger": "^5.8.0", + "@ethersproject/properties": "^5.8.0", "bn.js": "^5.2.1", - "elliptic": "6.5.4", + "elliptic": "6.6.1", "hash.js": "1.1.7" } }, "node_modules/@ethersproject/solidity": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/solidity/-/solidity-5.7.0.tgz", - "integrity": "sha512-HmabMd2Dt/raavyaGukF4XxizWKhKQ24DoLtdNbBmNKUOPqwjsKQSdV9GQtj9CBEea9DlzETlVER1gYeXXBGaA==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/solidity/-/solidity-5.8.0.tgz", + "integrity": "sha512-4CxFeCgmIWamOHwYN9d+QWGxye9qQLilpgTU0XhYs1OahkclF+ewO+3V1U0mvpiuQxm5EHHmv8f7ClVII8EHsA==", "funding": [ { "type": "individual", @@ -741,19 +916,20 @@ "url": "https://www.buymeacoffee.com/ricmoo" } ], + "license": "MIT", "dependencies": { - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/keccak256": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/sha2": "^5.7.0", - "@ethersproject/strings": "^5.7.0" + "@ethersproject/bignumber": "^5.8.0", + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/keccak256": "^5.8.0", + "@ethersproject/logger": "^5.8.0", + "@ethersproject/sha2": "^5.8.0", + "@ethersproject/strings": "^5.8.0" } }, "node_modules/@ethersproject/strings": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.7.0.tgz", - "integrity": "sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.8.0.tgz", + "integrity": "sha512-qWEAk0MAvl0LszjdfnZ2uC8xbR2wdv4cDabyHiBh3Cldq/T8dPH3V4BbBsAYJUeonwD+8afVXld274Ls+Y1xXg==", "funding": [ { "type": "individual", @@ -764,16 +940,17 @@ "url": "https://www.buymeacoffee.com/ricmoo" } ], + "license": "MIT", "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/constants": "^5.7.0", - "@ethersproject/logger": "^5.7.0" + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/constants": "^5.8.0", + "@ethersproject/logger": "^5.8.0" } }, "node_modules/@ethersproject/transactions": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.7.0.tgz", - "integrity": "sha512-kmcNicCp1lp8qanMTC3RIikGgoJ80ztTyvtsFvCYpSCfkjhD0jZ2LOrnbcuxuToLIUYYf+4XwD1rP+B/erDIhQ==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.8.0.tgz", + "integrity": "sha512-UglxSDjByHG0TuU17bDfCemZ3AnKO2vYrL5/2n2oXvKzvb7Cz+W9gOWXKARjp2URVwcWlQlPOEQyAviKwT4AHg==", "funding": [ { "type": "individual", @@ -784,22 +961,23 @@ "url": "https://www.buymeacoffee.com/ricmoo" } ], + "license": "MIT", "dependencies": { - "@ethersproject/address": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/constants": "^5.7.0", - "@ethersproject/keccak256": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/rlp": "^5.7.0", - "@ethersproject/signing-key": "^5.7.0" + "@ethersproject/address": "^5.8.0", + "@ethersproject/bignumber": "^5.8.0", + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/constants": "^5.8.0", + "@ethersproject/keccak256": "^5.8.0", + "@ethersproject/logger": "^5.8.0", + "@ethersproject/properties": "^5.8.0", + "@ethersproject/rlp": "^5.8.0", + "@ethersproject/signing-key": "^5.8.0" } }, "node_modules/@ethersproject/units": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/units/-/units-5.7.0.tgz", - "integrity": "sha512-pD3xLMy3SJu9kG5xDGI7+xhTEmGXlEqXU4OfNapmfnxLVY4EMSSRp7j1k7eezutBPH7RBN/7QPnwR7hzNlEFeg==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/units/-/units-5.8.0.tgz", + "integrity": "sha512-lxq0CAnc5kMGIiWW4Mr041VT8IhNM+Pn5T3haO74XZWFulk7wH1Gv64HqE96hT4a7iiNMdOCFEBgaxWuk8ETKQ==", "funding": [ { "type": "individual", @@ -810,16 +988,17 @@ "url": "https://www.buymeacoffee.com/ricmoo" } ], + "license": "MIT", "dependencies": { - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/constants": "^5.7.0", - "@ethersproject/logger": "^5.7.0" + "@ethersproject/bignumber": "^5.8.0", + "@ethersproject/constants": "^5.8.0", + "@ethersproject/logger": "^5.8.0" } }, "node_modules/@ethersproject/wallet": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/wallet/-/wallet-5.7.0.tgz", - "integrity": "sha512-MhmXlJXEJFBFVKrDLB4ZdDzxcBxQ3rLyCkhNqVu3CDYvR97E+8r01UgrI+TI99Le+aYm/in/0vp86guJuM7FCA==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/wallet/-/wallet-5.8.0.tgz", + "integrity": "sha512-G+jnzmgg6UxurVKRKvw27h0kvG75YKXZKdlLYmAHeF32TGUzHkOFd7Zn6QHOTYRFWnfjtSSFjBowKo7vfrXzPA==", "funding": [ { "type": "individual", @@ -830,28 +1009,29 @@ "url": "https://www.buymeacoffee.com/ricmoo" } ], + "license": "MIT", "dependencies": { - "@ethersproject/abstract-provider": "^5.7.0", - "@ethersproject/abstract-signer": "^5.7.0", - "@ethersproject/address": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/hash": "^5.7.0", - "@ethersproject/hdnode": "^5.7.0", - "@ethersproject/json-wallets": "^5.7.0", - "@ethersproject/keccak256": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/random": "^5.7.0", - "@ethersproject/signing-key": "^5.7.0", - "@ethersproject/transactions": "^5.7.0", - "@ethersproject/wordlists": "^5.7.0" + "@ethersproject/abstract-provider": "^5.8.0", + "@ethersproject/abstract-signer": "^5.8.0", + "@ethersproject/address": "^5.8.0", + "@ethersproject/bignumber": "^5.8.0", + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/hash": "^5.8.0", + "@ethersproject/hdnode": "^5.8.0", + "@ethersproject/json-wallets": "^5.8.0", + "@ethersproject/keccak256": "^5.8.0", + "@ethersproject/logger": "^5.8.0", + "@ethersproject/properties": "^5.8.0", + "@ethersproject/random": "^5.8.0", + "@ethersproject/signing-key": "^5.8.0", + "@ethersproject/transactions": "^5.8.0", + "@ethersproject/wordlists": "^5.8.0" } }, "node_modules/@ethersproject/web": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.7.1.tgz", - "integrity": "sha512-Gueu8lSvyjBWL4cYsWsjh6MtMwM0+H4HvqFPZfB6dV8ctbP9zFAO73VG1cMWae0FLPCtz0peKPpZY8/ugJJX2w==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.8.0.tgz", + "integrity": "sha512-j7+Ksi/9KfGviws6Qtf9Q7KCqRhpwrYKQPs+JBA/rKVFF/yaWLHJEH3zfVP2plVu+eys0d2DlFmhoQJayFewcw==", "funding": [ { "type": "individual", @@ -862,18 +1042,19 @@ "url": "https://www.buymeacoffee.com/ricmoo" } ], + "license": "MIT", "dependencies": { - "@ethersproject/base64": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/strings": "^5.7.0" + "@ethersproject/base64": "^5.8.0", + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/logger": "^5.8.0", + "@ethersproject/properties": "^5.8.0", + "@ethersproject/strings": "^5.8.0" } }, "node_modules/@ethersproject/wordlists": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/wordlists/-/wordlists-5.7.0.tgz", - "integrity": "sha512-S2TFNJNfHWVHNE6cNDjbVlZ6MgE17MIxMbMg2zv3wn+3XSJGosL1m9ZVv3GXCf/2ymSsQ+hRI5IzoMJTG6aoVA==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/@ethersproject/wordlists/-/wordlists-5.8.0.tgz", + "integrity": "sha512-2df9bbXicZws2Sb5S6ET493uJ0Z84Fjr3pC4tu/qlnZERibZCeUVuqdtt+7Tv9xxhUxHoIekIA7avrKUWHrezg==", "funding": [ { "type": "individual", @@ -884,18 +1065,20 @@ "url": "https://www.buymeacoffee.com/ricmoo" } ], + "license": "MIT", "dependencies": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/hash": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/strings": "^5.7.0" + "@ethersproject/bytes": "^5.8.0", + "@ethersproject/hash": "^5.8.0", + "@ethersproject/logger": "^5.8.0", + "@ethersproject/properties": "^5.8.0", + "@ethersproject/strings": "^5.8.0" } }, "node_modules/@fastify/busboy": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.0.0.tgz", - "integrity": "sha512-JUFJad5lv7jxj926GPgymrWQxxjPYuJNiNjNMzqT+HiuP6Vl3dk5xzG+8sTX96np0ZAluvaMzPsjhHZ5rNuNQQ==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", + "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", + "license": "MIT", "engines": { "node": ">=14" } @@ -916,11 +1099,36 @@ "node": ">=10.10.0" } }, + "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=12.22" }, @@ -1041,9 +1249,10 @@ } }, "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "license": "MIT", "engines": { "node": ">=6.0.0" } @@ -1058,124 +1267,70 @@ "version": "0.3.9", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" } }, - "node_modules/@metamask/eth-sig-util": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@metamask/eth-sig-util/-/eth-sig-util-4.0.1.tgz", - "integrity": "sha512-tghyZKLHZjcdlDqCA3gNZmLeR0XvOE9U1qoQO9ohyAZT6Pya+H9vkBPcsyXytmYLNgVoin7CKCmweo/R43V+tQ==", - "dependencies": { - "ethereumjs-abi": "^0.6.8", - "ethereumjs-util": "^6.2.1", - "ethjs-util": "^0.1.6", - "tweetnacl": "^1.0.3", - "tweetnacl-util": "^0.15.1" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/@metamask/eth-sig-util/node_modules/@types/bn.js": { - "version": "4.11.6", - "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz", - "integrity": "sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@metamask/eth-sig-util/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" - }, - "node_modules/@metamask/eth-sig-util/node_modules/ethereum-cryptography": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", - "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", - "dependencies": { - "@types/pbkdf2": "^3.0.0", - "@types/secp256k1": "^4.0.1", - "blakejs": "^1.1.0", - "browserify-aes": "^1.2.0", - "bs58check": "^2.1.2", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "hash.js": "^1.1.7", - "keccak": "^3.0.0", - "pbkdf2": "^3.0.17", - "randombytes": "^2.1.0", - "safe-buffer": "^5.1.2", - "scrypt-js": "^3.0.0", - "secp256k1": "^4.0.1", - "setimmediate": "^1.0.5" - } - }, - "node_modules/@metamask/eth-sig-util/node_modules/ethereumjs-util": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz", - "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==", + "node_modules/@napi-rs/wasm-runtime": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.9.tgz", + "integrity": "sha512-OKRBiajrrxB9ATokgEQoG87Z25c67pCpYcCwmXYX8PBftC9pBfN18gnm/fh1wurSLEKIAt+QRFLFCQISrb66Jg==", + "dev": true, + "license": "MIT", + "optional": true, "dependencies": { - "@types/bn.js": "^4.11.3", - "bn.js": "^4.11.0", - "create-hash": "^1.1.2", - "elliptic": "^6.5.2", - "ethereum-cryptography": "^0.1.3", - "ethjs-util": "0.1.6", - "rlp": "^2.2.3" + "@emnapi/core": "^1.4.0", + "@emnapi/runtime": "^1.4.0", + "@tybys/wasm-util": "^0.9.0" } }, "node_modules/@noble/curves": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.4.0.tgz", - "integrity": "sha512-p+4cb332SFCrReJkCYe8Xzm0OWi4Jji5jVdIZRL/PmacmDkFNw6MrrV+gGpiPxLHbV+zKFRywUWbaseT+tZRXg==", + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.8.2.tgz", + "integrity": "sha512-vnI7V6lFNe0tLAuJMu+2sX+FcL14TaCWy1qiczg1VwRmPrpQCdq5ESXQMqUc2tluRNf6irBXrWbl1mGN8uaU/g==", + "license": "MIT", "dependencies": { - "@noble/hashes": "1.4.0" + "@noble/hashes": "1.7.2" + }, + "engines": { + "node": "^14.21.3 || >=16" }, "funding": { "url": "https://paulmillr.com/funding/" } }, - "node_modules/@noble/curves/node_modules/@noble/hashes": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", - "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", + "node_modules/@noble/hashes": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.7.2.tgz", + "integrity": "sha512-biZ0NUSxyjLLqo6KxEJ1b+C2NAx0wtDoFvCaXHGgUkeHzf3Xc1xKumFKREuT7f7DARNZ/slvYUwFG6B0f2b6hQ==", + "license": "MIT", "engines": { - "node": ">= 16" + "node": "^14.21.3 || >=16" }, "funding": { "url": "https://paulmillr.com/funding/" } }, - "node_modules/@noble/hashes": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.1.2.tgz", - "integrity": "sha512-KYRCASVTv6aeUi1tsF8/vpyR7zpfs3FUzy2Jqm+MU+LmUKhQ0y2FpfwqkCcxSg2ua4GALJd8k2R76WxwZGbQpA==", - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ] - }, "node_modules/@noble/secp256k1": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/@noble/secp256k1/-/secp256k1-1.6.3.tgz", - "integrity": "sha512-T04e4iTurVy7I8Sw4+c5OSN9/RkPlo1uKxAomtxQNLq8j1uPAqnsqG1bqvY3Jv7c13gyr6dui0zmh/I3+f/JaQ==", + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@noble/secp256k1/-/secp256k1-1.7.1.tgz", + "integrity": "sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw==", "funding": [ { "type": "individual", "url": "https://paulmillr.com/funding/" } - ] + ], + "license": "MIT" }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dev": true, + "license": "MIT", "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" @@ -1189,6 +1344,7 @@ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "dev": true, + "license": "MIT", "engines": { "node": ">= 8" } @@ -1198,6 +1354,7 @@ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, + "license": "MIT", "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" @@ -1217,98 +1374,92 @@ } }, "node_modules/@nomicfoundation/edr": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr/-/edr-0.6.5.tgz", - "integrity": "sha512-tAqMslLP+/2b2sZP4qe9AuGxG3OkQ5gGgHE4isUuq6dUVjwCRPFhAOhpdFl+OjY5P3yEv3hmq9HjUGRa2VNjng==", + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr/-/edr-0.10.0.tgz", + "integrity": "sha512-ed9qHSNssgh+0hYUx4ilDoMxxgf/sNT8SjnzgmA5A/LSXHaq2ax68bkdQ8otLYTlxHCO9BS5Nhb8bfajV4FZeA==", "license": "MIT", "dependencies": { - "@nomicfoundation/edr-darwin-arm64": "0.6.5", - "@nomicfoundation/edr-darwin-x64": "0.6.5", - "@nomicfoundation/edr-linux-arm64-gnu": "0.6.5", - "@nomicfoundation/edr-linux-arm64-musl": "0.6.5", - "@nomicfoundation/edr-linux-x64-gnu": "0.6.5", - "@nomicfoundation/edr-linux-x64-musl": "0.6.5", - "@nomicfoundation/edr-win32-x64-msvc": "0.6.5" + "@nomicfoundation/edr-darwin-arm64": "0.10.0", + "@nomicfoundation/edr-darwin-x64": "0.10.0", + "@nomicfoundation/edr-linux-arm64-gnu": "0.10.0", + "@nomicfoundation/edr-linux-arm64-musl": "0.10.0", + "@nomicfoundation/edr-linux-x64-gnu": "0.10.0", + "@nomicfoundation/edr-linux-x64-musl": "0.10.0", + "@nomicfoundation/edr-win32-x64-msvc": "0.10.0" }, "engines": { "node": ">= 18" } }, "node_modules/@nomicfoundation/edr-darwin-arm64": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-darwin-arm64/-/edr-darwin-arm64-0.6.5.tgz", - "integrity": "sha512-A9zCCbbNxBpLgjS1kEJSpqxIvGGAX4cYbpDYCU2f3jVqOwaZ/NU761y1SvuCRVpOwhoCXqByN9b7HPpHi0L4hw==", + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-darwin-arm64/-/edr-darwin-arm64-0.10.0.tgz", + "integrity": "sha512-n0N+CVM4LKN9QeGZ5irr94Q4vwSs4u7W6jfuhNLmx1cpUxwE9RpeW+ym93JXDv62iVsbekeI5VsUEBHy0hymtA==", "license": "MIT", "engines": { "node": ">= 18" } }, "node_modules/@nomicfoundation/edr-darwin-x64": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-darwin-x64/-/edr-darwin-x64-0.6.5.tgz", - "integrity": "sha512-x3zBY/v3R0modR5CzlL6qMfFMdgwd6oHrWpTkuuXnPFOX8SU31qq87/230f4szM+ukGK8Hi+mNq7Ro2VF4Fj+w==", + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-darwin-x64/-/edr-darwin-x64-0.10.0.tgz", + "integrity": "sha512-nmImWM/3qWopYzOmicMzK/MF3rFKpm2Biuc8GpQYTLjdXhmItpP9JwEPyjbAWv/1HI09C2pRzgNzKfTxoIgJ6w==", "license": "MIT", "engines": { "node": ">= 18" } }, "node_modules/@nomicfoundation/edr-linux-arm64-gnu": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-arm64-gnu/-/edr-linux-arm64-gnu-0.6.5.tgz", - "integrity": "sha512-HGpB8f1h8ogqPHTyUpyPRKZxUk2lu061g97dOQ/W4CxevI0s/qiw5DB3U3smLvSnBHKOzYS1jkxlMeGN01ky7A==", + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-arm64-gnu/-/edr-linux-arm64-gnu-0.10.0.tgz", + "integrity": "sha512-B/N1IyrCU7J6H4QckkQ1cSWAq1jSrJcXpO8GzRaQD1bgOOvg8wrUOrCD+Mfw7MLa6+X9vdZoXtPZOaaOQ9LmhA==", "license": "MIT", "engines": { "node": ">= 18" } }, "node_modules/@nomicfoundation/edr-linux-arm64-musl": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-arm64-musl/-/edr-linux-arm64-musl-0.6.5.tgz", - "integrity": "sha512-ESvJM5Y9XC03fZg9KaQg3Hl+mbx7dsSkTIAndoJS7X2SyakpL9KZpOSYrDk135o8s9P9lYJdPOyiq+Sh+XoCbQ==", + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-arm64-musl/-/edr-linux-arm64-musl-0.10.0.tgz", + "integrity": "sha512-NA9DFLB0LzcKy9mTCUzgnRDbmmSfW0CdO22ySwOy+MKt4Cr9eJi+XR5ZH933Rxpi6BWNkSPeS2ECETE25sJT3w==", "license": "MIT", "engines": { "node": ">= 18" } }, "node_modules/@nomicfoundation/edr-linux-x64-gnu": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-x64-gnu/-/edr-linux-x64-gnu-0.6.5.tgz", - "integrity": "sha512-HCM1usyAR1Ew6RYf5AkMYGvHBy64cPA5NMbaeY72r0mpKaH3txiMyydcHibByOGdQ8iFLWpyUdpl1egotw+Tgg==", + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-x64-gnu/-/edr-linux-x64-gnu-0.10.0.tgz", + "integrity": "sha512-bDrbRTA9qZ9wSw5mqa8VpLFbf6ue2Z4qmRd08404eKm8RyBEFxjdHflFzCx46gz/Td0e+GLXy6KTVDj5D29r8w==", "license": "MIT", "engines": { "node": ">= 18" } }, "node_modules/@nomicfoundation/edr-linux-x64-musl": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-x64-musl/-/edr-linux-x64-musl-0.6.5.tgz", - "integrity": "sha512-nB2uFRyczhAvWUH7NjCsIO6rHnQrof3xcCe6Mpmnzfl2PYcGyxN7iO4ZMmRcQS7R1Y670VH6+8ZBiRn8k43m7A==", + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-x64-musl/-/edr-linux-x64-musl-0.10.0.tgz", + "integrity": "sha512-wx7yOlC/hx4N1xuIeh5cAebpzCTx8ZH8/z0IyYMf2t4v52KHERz4IyzBz5OLfd+0IqTRg8ZU5EnFBacIoPeP/g==", "license": "MIT", "engines": { "node": ">= 18" } }, "node_modules/@nomicfoundation/edr-win32-x64-msvc": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-win32-x64-msvc/-/edr-win32-x64-msvc-0.6.5.tgz", - "integrity": "sha512-B9QD/4DSSCFtWicO8A3BrsnitO1FPv7axB62wq5Q+qeJ50yJlTmyeGY3cw62gWItdvy2mh3fRM6L1LpnHiB77A==", + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-win32-x64-msvc/-/edr-win32-x64-msvc-0.10.0.tgz", + "integrity": "sha512-DpBdVMimb+BUEs0E+nLGQ5JFHdGHyxQQNA+nh9V1eKtgarsV21S6br/d1vlQBMLQqkIzwmc6n+/O9Zjk2KfB3g==", "license": "MIT", "engines": { "node": ">= 18" } }, - "node_modules/@nomicfoundation/ethereumjs-common": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-common/-/ethereumjs-common-4.0.4.tgz", - "integrity": "sha512-9Rgb658lcWsjiicr5GzNCjI1llow/7r0k50dLL95OJ+6iZJcVbi15r3Y0xh2cIO+zgX0WIHcbzIu6FeQf9KPrg==", - "dependencies": { - "@nomicfoundation/ethereumjs-util": "9.0.4" - } - }, "node_modules/@nomicfoundation/ethereumjs-rlp": { "version": "5.0.4", "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-rlp/-/ethereumjs-rlp-5.0.4.tgz", "integrity": "sha512-8H1S3s8F6QueOc/X92SdrA4RDenpiAEqMg5vJH99kcQaCy/a3Q6fgseo75mgWlbanGJXSlAPtnCeG9jvfTYXlw==", + "dev": true, + "license": "MPL-2.0", "bin": { "rlp": "bin/rlp.cjs" }, @@ -1316,54 +1467,12 @@ "node": ">=18" } }, - "node_modules/@nomicfoundation/ethereumjs-tx": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-tx/-/ethereumjs-tx-5.0.4.tgz", - "integrity": "sha512-Xjv8wAKJGMrP1f0n2PeyfFCCojHd7iS3s/Ab7qzF1S64kxZ8Z22LCMynArYsVqiFx6rzYy548HNVEyI+AYN/kw==", - "dependencies": { - "@nomicfoundation/ethereumjs-common": "4.0.4", - "@nomicfoundation/ethereumjs-rlp": "5.0.4", - "@nomicfoundation/ethereumjs-util": "9.0.4", - "ethereum-cryptography": "0.1.3" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "c-kzg": "^2.1.2" - }, - "peerDependenciesMeta": { - "c-kzg": { - "optional": true - } - } - }, - "node_modules/@nomicfoundation/ethereumjs-tx/node_modules/ethereum-cryptography": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", - "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", - "dependencies": { - "@types/pbkdf2": "^3.0.0", - "@types/secp256k1": "^4.0.1", - "blakejs": "^1.1.0", - "browserify-aes": "^1.2.0", - "bs58check": "^2.1.2", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "hash.js": "^1.1.7", - "keccak": "^3.0.0", - "pbkdf2": "^3.0.17", - "randombytes": "^2.1.0", - "safe-buffer": "^5.1.2", - "scrypt-js": "^3.0.0", - "secp256k1": "^4.0.1", - "setimmediate": "^1.0.5" - } - }, "node_modules/@nomicfoundation/ethereumjs-util": { "version": "9.0.4", "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-util/-/ethereumjs-util-9.0.4.tgz", "integrity": "sha512-sLOzjnSrlx9Bb9EFNtHzK/FJFsfg2re6bsGqinFinH1gCqVfz9YYlXiMWwDM4C/L4ywuHFCYwfKTVr/QHQcU0Q==", + "dev": true, + "license": "MPL-2.0", "dependencies": { "@nomicfoundation/ethereumjs-rlp": "5.0.4", "ethereum-cryptography": "0.1.3" @@ -1380,28 +1489,6 @@ } } }, - "node_modules/@nomicfoundation/ethereumjs-util/node_modules/ethereum-cryptography": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", - "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", - "dependencies": { - "@types/pbkdf2": "^3.0.0", - "@types/secp256k1": "^4.0.1", - "blakejs": "^1.1.0", - "browserify-aes": "^1.2.0", - "bs58check": "^2.1.2", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "hash.js": "^1.1.7", - "keccak": "^3.0.0", - "pbkdf2": "^3.0.17", - "randombytes": "^2.1.0", - "safe-buffer": "^5.1.2", - "scrypt-js": "^3.0.0", - "secp256k1": "^4.0.1", - "setimmediate": "^1.0.5" - } - }, "node_modules/@nomicfoundation/hardhat-chai-matchers": { "version": "2.0.8", "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-chai-matchers/-/hardhat-chai-matchers-2.0.8.tgz", @@ -1450,173 +1537,91 @@ } }, "node_modules/@nomicfoundation/solidity-analyzer": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer/-/solidity-analyzer-0.1.0.tgz", - "integrity": "sha512-xGWAiVCGOycvGiP/qrlf9f9eOn7fpNbyJygcB0P21a1MDuVPlKt0Srp7rvtBEutYQ48ouYnRXm33zlRnlTOPHg==", + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer/-/solidity-analyzer-0.1.2.tgz", + "integrity": "sha512-q4n32/FNKIhQ3zQGGw5CvPF6GTvDCpYwIf7bEY/dZTZbgfDsHyjJwURxUJf3VQuuJj+fDIFl4+KkBVbw4Ef6jA==", + "license": "MIT", "engines": { "node": ">= 12" }, "optionalDependencies": { - "@nomicfoundation/solidity-analyzer-darwin-arm64": "0.1.0", - "@nomicfoundation/solidity-analyzer-darwin-x64": "0.1.0", - "@nomicfoundation/solidity-analyzer-freebsd-x64": "0.1.0", - "@nomicfoundation/solidity-analyzer-linux-arm64-gnu": "0.1.0", - "@nomicfoundation/solidity-analyzer-linux-arm64-musl": "0.1.0", - "@nomicfoundation/solidity-analyzer-linux-x64-gnu": "0.1.0", - "@nomicfoundation/solidity-analyzer-linux-x64-musl": "0.1.0", - "@nomicfoundation/solidity-analyzer-win32-arm64-msvc": "0.1.0", - "@nomicfoundation/solidity-analyzer-win32-ia32-msvc": "0.1.0", - "@nomicfoundation/solidity-analyzer-win32-x64-msvc": "0.1.0" + "@nomicfoundation/solidity-analyzer-darwin-arm64": "0.1.2", + "@nomicfoundation/solidity-analyzer-darwin-x64": "0.1.2", + "@nomicfoundation/solidity-analyzer-linux-arm64-gnu": "0.1.2", + "@nomicfoundation/solidity-analyzer-linux-arm64-musl": "0.1.2", + "@nomicfoundation/solidity-analyzer-linux-x64-gnu": "0.1.2", + "@nomicfoundation/solidity-analyzer-linux-x64-musl": "0.1.2", + "@nomicfoundation/solidity-analyzer-win32-x64-msvc": "0.1.2" } }, "node_modules/@nomicfoundation/solidity-analyzer-darwin-arm64": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-darwin-arm64/-/solidity-analyzer-darwin-arm64-0.1.0.tgz", - "integrity": "sha512-vEF3yKuuzfMHsZecHQcnkUrqm8mnTWfJeEVFHpg+cO+le96xQA4lAJYdUan8pXZohQxv1fSReQsn4QGNuBNuCw==", - "cpu": [ - "arm64" - ], + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-darwin-arm64/-/solidity-analyzer-darwin-arm64-0.1.2.tgz", + "integrity": "sha512-JaqcWPDZENCvm++lFFGjrDd8mxtf+CtLd2MiXvMNTBD33dContTZ9TWETwNFwg7JTJT5Q9HEecH7FA+HTSsIUw==", + "license": "MIT", "optional": true, - "os": [ - "darwin" - ], "engines": { - "node": ">= 10" + "node": ">= 12" } }, "node_modules/@nomicfoundation/solidity-analyzer-darwin-x64": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-darwin-x64/-/solidity-analyzer-darwin-x64-0.1.0.tgz", - "integrity": "sha512-dlHeIg0pTL4dB1l9JDwbi/JG6dHQaU1xpDK+ugYO8eJ1kxx9Dh2isEUtA4d02cQAl22cjOHTvifAk96A+ItEHA==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nomicfoundation/solidity-analyzer-freebsd-x64": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-freebsd-x64/-/solidity-analyzer-freebsd-x64-0.1.0.tgz", - "integrity": "sha512-WFCZYMv86WowDA4GiJKnebMQRt3kCcFqHeIomW6NMyqiKqhK1kIZCxSLDYsxqlx396kKLPN1713Q1S8tu68GKg==", - "cpu": [ - "x64" - ], + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-darwin-x64/-/solidity-analyzer-darwin-x64-0.1.2.tgz", + "integrity": "sha512-fZNmVztrSXC03e9RONBT+CiksSeYcxI1wlzqyr0L7hsQlK1fzV+f04g2JtQ1c/Fe74ZwdV6aQBdd6Uwl1052sw==", + "license": "MIT", "optional": true, - "os": [ - "freebsd" - ], "engines": { - "node": ">= 10" + "node": ">= 12" } }, "node_modules/@nomicfoundation/solidity-analyzer-linux-arm64-gnu": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-linux-arm64-gnu/-/solidity-analyzer-linux-arm64-gnu-0.1.0.tgz", - "integrity": "sha512-DTw6MNQWWlCgc71Pq7CEhEqkb7fZnS7oly13pujs4cMH1sR0JzNk90Mp1zpSCsCs4oKan2ClhMlLKtNat/XRKQ==", - "cpu": [ - "arm64" - ], + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-linux-arm64-gnu/-/solidity-analyzer-linux-arm64-gnu-0.1.2.tgz", + "integrity": "sha512-3d54oc+9ZVBuB6nbp8wHylk4xh0N0Gc+bk+/uJae+rUgbOBwQSfuGIbAZt1wBXs5REkSmynEGcqx6DutoK0tPA==", + "license": "MIT", "optional": true, - "os": [ - "linux" - ], "engines": { - "node": ">= 10" + "node": ">= 12" } }, "node_modules/@nomicfoundation/solidity-analyzer-linux-arm64-musl": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-linux-arm64-musl/-/solidity-analyzer-linux-arm64-musl-0.1.0.tgz", - "integrity": "sha512-wUpUnR/3GV5Da88MhrxXh/lhb9kxh9V3Jya2NpBEhKDIRCDmtXMSqPMXHZmOR9DfCwCvG6vLFPr/+YrPCnUN0w==", - "cpu": [ - "arm64" - ], + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-linux-arm64-musl/-/solidity-analyzer-linux-arm64-musl-0.1.2.tgz", + "integrity": "sha512-iDJfR2qf55vgsg7BtJa7iPiFAsYf2d0Tv/0B+vhtnI16+wfQeTbP7teookbGvAo0eJo7aLLm0xfS/GTkvHIucA==", + "license": "MIT", "optional": true, - "os": [ - "linux" - ], "engines": { - "node": ">= 10" + "node": ">= 12" } }, "node_modules/@nomicfoundation/solidity-analyzer-linux-x64-gnu": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-linux-x64-gnu/-/solidity-analyzer-linux-x64-gnu-0.1.0.tgz", - "integrity": "sha512-lR0AxK1x/MeKQ/3Pt923kPvwigmGX3OxeU5qNtQ9pj9iucgk4PzhbS3ruUeSpYhUxG50jN4RkIGwUMoev5lguw==", - "cpu": [ - "x64" - ], + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-linux-x64-gnu/-/solidity-analyzer-linux-x64-gnu-0.1.2.tgz", + "integrity": "sha512-9dlHMAt5/2cpWyuJ9fQNOUXFB/vgSFORg1jpjX1Mh9hJ/MfZXlDdHQ+DpFCs32Zk5pxRBb07yGvSHk9/fezL+g==", + "license": "MIT", "optional": true, - "os": [ - "linux" - ], "engines": { - "node": ">= 10" + "node": ">= 12" } }, "node_modules/@nomicfoundation/solidity-analyzer-linux-x64-musl": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-linux-x64-musl/-/solidity-analyzer-linux-x64-musl-0.1.0.tgz", - "integrity": "sha512-A1he/8gy/JeBD3FKvmI6WUJrGrI5uWJNr5Xb9WdV+DK0F8msuOqpEByLlnTdLkXMwW7nSl3awvLezOs9xBHJEg==", - "cpu": [ - "x64" - ], - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nomicfoundation/solidity-analyzer-win32-arm64-msvc": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-win32-arm64-msvc/-/solidity-analyzer-win32-arm64-msvc-0.1.0.tgz", - "integrity": "sha512-7x5SXZ9R9H4SluJZZP8XPN+ju7Mx+XeUMWZw7ZAqkdhP5mK19I4vz3x0zIWygmfE8RT7uQ5xMap0/9NPsO+ykw==", - "cpu": [ - "arm64" - ], - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, - "node_modules/@nomicfoundation/solidity-analyzer-win32-ia32-msvc": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-win32-ia32-msvc/-/solidity-analyzer-win32-ia32-msvc-0.1.0.tgz", - "integrity": "sha512-m7w3xf+hnE774YRXu+2mGV7RiF3QJtUoiYU61FascCkQhX3QMQavh7saH/vzb2jN5D24nT/jwvaHYX/MAM9zUw==", - "cpu": [ - "ia32" - ], + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-linux-x64-musl/-/solidity-analyzer-linux-x64-musl-0.1.2.tgz", + "integrity": "sha512-GzzVeeJob3lfrSlDKQw2bRJ8rBf6mEYaWY+gW0JnTDHINA0s2gPR4km5RLIj1xeZZOYz4zRw+AEeYgLRqB2NXg==", + "license": "MIT", "optional": true, - "os": [ - "win32" - ], "engines": { - "node": ">= 10" + "node": ">= 12" } }, "node_modules/@nomicfoundation/solidity-analyzer-win32-x64-msvc": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-win32-x64-msvc/-/solidity-analyzer-win32-x64-msvc-0.1.0.tgz", - "integrity": "sha512-xCuybjY0sLJQnJhupiFAXaek2EqF0AP0eBjgzaalPXSNvCEN6ZYHvUzdA50ENDVeSYFXcUsYf3+FsD3XKaeptA==", - "cpu": [ - "x64" - ], + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-win32-x64-msvc/-/solidity-analyzer-win32-x64-msvc-0.1.2.tgz", + "integrity": "sha512-Fdjli4DCcFHb4Zgsz0uEJXZ2K7VEO+w5KVv7HmT7WO10iODdU9csC2az4jrhEsRtiR9Gfd74FlG0NYlw1BMdyA==", + "license": "MIT", "optional": true, - "os": [ - "win32" - ], "engines": { - "node": ">= 10" + "node": ">= 12" } }, "node_modules/@nomiclabs/hardhat-solhint": { @@ -1633,9 +1638,9 @@ } }, "node_modules/@openzeppelin/contracts": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-5.1.0.tgz", - "integrity": "sha512-p1ULhl7BXzjjbha5aqst+QMLY+4/LCWADXOCsmLHRM77AqiPjnd9vvUN9sosUfhL9JGKpZ0TjEGxgvnizmWGSA==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-5.3.0.tgz", + "integrity": "sha512-zj/KGoW7zxWUE8qOI++rUM18v+VeLTTzKs/DJFkSzHpQFPD/jKKF0TrMxBfGLl3kpdELCNccvB3zmofSzm4nlA==", "license": "MIT" }, "node_modules/@pkgjs/parseargs": { @@ -1650,16 +1655,16 @@ } }, "node_modules/@pkgr/core": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", - "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.4.tgz", + "integrity": "sha512-ROFF39F6ZrnzSUEmQQZUar0Jt4xVoP9WnDRdWwF4NNcXs3xBTLgBUDoOwW141y1jP+S8nahIbdxbFC7IShw9Iw==", "dev": true, "license": "MIT", "engines": { "node": "^12.20.0 || ^14.18.0 || >=16.0.0" }, "funding": { - "url": "https://opencollective.com/unts" + "url": "https://opencollective.com/pkgr" } }, "node_modules/@pnpm/config.env-replace": { @@ -1685,6 +1690,13 @@ "node": ">=12.22.0" } }, + "node_modules/@pnpm/network.ca-file/node_modules/graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "dev": true, + "license": "ISC" + }, "node_modules/@pnpm/npm-conf": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/@pnpm/npm-conf/-/npm-conf-2.3.1.tgz", @@ -1754,19 +1766,6 @@ "scale-ts": "^1.6.0" } }, - "node_modules/@polkadot-api/substrate-bindings/node_modules/@noble/hashes": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.6.1.tgz", - "integrity": "sha512-pq5D8h10hHBjyqX+cfBm0i8JUXJ0UhczFc4r74zbuT9XgewFo2E3J1cOaGtdZynILNmQ685YWGzGE1Zv6io50w==", - "license": "MIT", - "optional": true, - "engines": { - "node": "^14.21.3 || >=16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, "node_modules/@polkadot-api/substrate-client": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/@polkadot-api/substrate-client/-/substrate-client-0.1.4.tgz", @@ -1786,113 +1785,113 @@ "optional": true }, "node_modules/@polkadot/api": { - "version": "15.0.2", - "resolved": "https://registry.npmjs.org/@polkadot/api/-/api-15.0.2.tgz", - "integrity": "sha512-CA8Pq2Gsz2MJvpkpIVNzaBs2eJGCr0sEodAb0vTOZW/ZlIDHcBWyWq3KXE+lBMWVzYBEC4Vz6MafNgq6Bsshlw==", + "version": "15.9.2", + "resolved": "https://registry.npmjs.org/@polkadot/api/-/api-15.9.2.tgz", + "integrity": "sha512-HjKI+na6f3oy9WZdLKVq4LXQoNZ3dhyQRp+7yibIq2MTwxPqlFOe/Be55IjeK2RAlSGIfLCw9rCCVA5aPBR2pA==", "license": "Apache-2.0", "dependencies": { - "@polkadot/api-augment": "15.0.2", - "@polkadot/api-base": "15.0.2", - "@polkadot/api-derive": "15.0.2", - "@polkadot/keyring": "^13.2.3", - "@polkadot/rpc-augment": "15.0.2", - "@polkadot/rpc-core": "15.0.2", - "@polkadot/rpc-provider": "15.0.2", - "@polkadot/types": "15.0.2", - "@polkadot/types-augment": "15.0.2", - "@polkadot/types-codec": "15.0.2", - "@polkadot/types-create": "15.0.2", - "@polkadot/types-known": "15.0.2", - "@polkadot/util": "^13.2.3", - "@polkadot/util-crypto": "^13.2.3", + "@polkadot/api-augment": "15.9.2", + "@polkadot/api-base": "15.9.2", + "@polkadot/api-derive": "15.9.2", + "@polkadot/keyring": "^13.4.4", + "@polkadot/rpc-augment": "15.9.2", + "@polkadot/rpc-core": "15.9.2", + "@polkadot/rpc-provider": "15.9.2", + "@polkadot/types": "15.9.2", + "@polkadot/types-augment": "15.9.2", + "@polkadot/types-codec": "15.9.2", + "@polkadot/types-create": "15.9.2", + "@polkadot/types-known": "15.9.2", + "@polkadot/util": "^13.4.4", + "@polkadot/util-crypto": "^13.4.4", "eventemitter3": "^5.0.1", "rxjs": "^7.8.1", - "tslib": "^2.8.0" + "tslib": "^2.8.1" }, "engines": { "node": ">=18" } }, "node_modules/@polkadot/api-augment": { - "version": "15.0.2", - "resolved": "https://registry.npmjs.org/@polkadot/api-augment/-/api-augment-15.0.2.tgz", - "integrity": "sha512-7qtfTihLKS7cT2kEsd8Y1+MJ+2n4Sl0y9BHuPhdNfKcDbGwCxIB7JzXNujww4Is4bF7w1lXcM2U0E/XwJi1BbQ==", + "version": "15.9.2", + "resolved": "https://registry.npmjs.org/@polkadot/api-augment/-/api-augment-15.9.2.tgz", + "integrity": "sha512-I7hUrrWEJ+pol6DgGRWfTM71b5hzonVmWyCkE7PaTVA1rL0CANo2hwSe24Qve8zUZqtiy6q1YrTXu6HLs9DhRQ==", "license": "Apache-2.0", "dependencies": { - "@polkadot/api-base": "15.0.2", - "@polkadot/rpc-augment": "15.0.2", - "@polkadot/types": "15.0.2", - "@polkadot/types-augment": "15.0.2", - "@polkadot/types-codec": "15.0.2", - "@polkadot/util": "^13.2.3", - "tslib": "^2.8.0" + "@polkadot/api-base": "15.9.2", + "@polkadot/rpc-augment": "15.9.2", + "@polkadot/types": "15.9.2", + "@polkadot/types-augment": "15.9.2", + "@polkadot/types-codec": "15.9.2", + "@polkadot/util": "^13.4.4", + "tslib": "^2.8.1" }, "engines": { "node": ">=18" } }, "node_modules/@polkadot/api-base": { - "version": "15.0.2", - "resolved": "https://registry.npmjs.org/@polkadot/api-base/-/api-base-15.0.2.tgz", - "integrity": "sha512-5++EjpuCxzmrL2JJj511RrPK+IovuIQa8DJhyOp62VDMXPkqS/O6Df5wjYzQh/ftT1ZysftXqJAUA/LSUsH+2g==", + "version": "15.9.2", + "resolved": "https://registry.npmjs.org/@polkadot/api-base/-/api-base-15.9.2.tgz", + "integrity": "sha512-PExkdWIb7zlTkIzAC0PP0fsjaJcZeF1XuPIpSOBYi54om6VR9Ks6PlLB2XEOu6oj8mCdQbYPe5tSGtVhNVA7ig==", "license": "Apache-2.0", "dependencies": { - "@polkadot/rpc-core": "15.0.2", - "@polkadot/types": "15.0.2", - "@polkadot/util": "^13.2.3", + "@polkadot/rpc-core": "15.9.2", + "@polkadot/types": "15.9.2", + "@polkadot/util": "^13.4.4", "rxjs": "^7.8.1", - "tslib": "^2.8.0" + "tslib": "^2.8.1" }, "engines": { "node": ">=18" } }, "node_modules/@polkadot/api-derive": { - "version": "15.0.2", - "resolved": "https://registry.npmjs.org/@polkadot/api-derive/-/api-derive-15.0.2.tgz", - "integrity": "sha512-nD8hXZxEv2/wuhjMmVP09lTAYd8inNgrLpLGUR+7hBQeVEQQTdNatkqMKpNIOk2MO46mtUK35NepvDBK9DWZzA==", + "version": "15.9.2", + "resolved": "https://registry.npmjs.org/@polkadot/api-derive/-/api-derive-15.9.2.tgz", + "integrity": "sha512-/MMu8kRv30BQZzXavvRvnejRTfOHncN0HVxtlYj7hbzfUf6zxvVqpygPJszcH+/IZhuU8y31oZ2E3Wy2dGsdKA==", "license": "Apache-2.0", "dependencies": { - "@polkadot/api": "15.0.2", - "@polkadot/api-augment": "15.0.2", - "@polkadot/api-base": "15.0.2", - "@polkadot/rpc-core": "15.0.2", - "@polkadot/types": "15.0.2", - "@polkadot/types-codec": "15.0.2", - "@polkadot/util": "^13.2.3", - "@polkadot/util-crypto": "^13.2.3", + "@polkadot/api": "15.9.2", + "@polkadot/api-augment": "15.9.2", + "@polkadot/api-base": "15.9.2", + "@polkadot/rpc-core": "15.9.2", + "@polkadot/types": "15.9.2", + "@polkadot/types-codec": "15.9.2", + "@polkadot/util": "^13.4.4", + "@polkadot/util-crypto": "^13.4.4", "rxjs": "^7.8.1", - "tslib": "^2.8.0" + "tslib": "^2.8.1" }, "engines": { "node": ">=18" } }, "node_modules/@polkadot/keyring": { - "version": "13.2.3", - "resolved": "https://registry.npmjs.org/@polkadot/keyring/-/keyring-13.2.3.tgz", - "integrity": "sha512-pgTo6DXNXub0wGD+MnVHYhKxf80Jl+QMOCb818ioGdXz++Uw4mTueFAwtB+N7TGo0HafhChUiNJDxFdlDkcAng==", + "version": "13.4.4", + "resolved": "https://registry.npmjs.org/@polkadot/keyring/-/keyring-13.4.4.tgz", + "integrity": "sha512-pIm+u1lat+mGUABsCZyTm1/qgwL3NS94SC7TPtSzhzFZq6faUFNMyq1gBfTicrb7MjGFc8FlrKlGxFtudnQC9Q==", "license": "Apache-2.0", "dependencies": { - "@polkadot/util": "13.2.3", - "@polkadot/util-crypto": "13.2.3", + "@polkadot/util": "13.4.4", + "@polkadot/util-crypto": "13.4.4", "tslib": "^2.8.0" }, "engines": { "node": ">=18" }, "peerDependencies": { - "@polkadot/util": "13.2.3", - "@polkadot/util-crypto": "13.2.3" + "@polkadot/util": "13.4.4", + "@polkadot/util-crypto": "13.4.4" } }, "node_modules/@polkadot/networks": { - "version": "13.2.3", - "resolved": "https://registry.npmjs.org/@polkadot/networks/-/networks-13.2.3.tgz", - "integrity": "sha512-mG+zkXg/33AyPrkv2xBbAo3LBUwOwBn6qznBU/4jxiZPnVvCwMaxE7xHM22B5riItbNJ169FXv3wy0v6ZmkFbw==", + "version": "13.4.4", + "resolved": "https://registry.npmjs.org/@polkadot/networks/-/networks-13.4.4.tgz", + "integrity": "sha512-I3g9OX3CpZbFKa1C4xQPYOJ2Y209oEb5x9lzgHuAzg64m5vr2y4azWDSQnoOrlFK5ztSrijkWe1gSME1lzy8iA==", "license": "Apache-2.0", "dependencies": { - "@polkadot/util": "13.2.3", + "@polkadot/util": "13.4.4", "@substrate/ss58-registry": "^1.51.0", "tslib": "^2.8.0" }, @@ -1901,56 +1900,56 @@ } }, "node_modules/@polkadot/rpc-augment": { - "version": "15.0.2", - "resolved": "https://registry.npmjs.org/@polkadot/rpc-augment/-/rpc-augment-15.0.2.tgz", - "integrity": "sha512-of88GdzsOs15HP+Gowh4G/iKKFkCNIeF0Wes8LiONfn+j2TmWt8blbyGhrIZZeApzbFUDFjnxUPGT40uWJcMpw==", + "version": "15.9.2", + "resolved": "https://registry.npmjs.org/@polkadot/rpc-augment/-/rpc-augment-15.9.2.tgz", + "integrity": "sha512-wQKo5apcBA0ab1S8aZiZ6CueFsIgrV1MJoXSBa7u+AhEv0Z79h42j8jQyKD//HKEqq06fMWgjDb8djFrRjd65A==", "license": "Apache-2.0", "dependencies": { - "@polkadot/rpc-core": "15.0.2", - "@polkadot/types": "15.0.2", - "@polkadot/types-codec": "15.0.2", - "@polkadot/util": "^13.2.3", - "tslib": "^2.8.0" + "@polkadot/rpc-core": "15.9.2", + "@polkadot/types": "15.9.2", + "@polkadot/types-codec": "15.9.2", + "@polkadot/util": "^13.4.4", + "tslib": "^2.8.1" }, "engines": { "node": ">=18" } }, "node_modules/@polkadot/rpc-core": { - "version": "15.0.2", - "resolved": "https://registry.npmjs.org/@polkadot/rpc-core/-/rpc-core-15.0.2.tgz", - "integrity": "sha512-KOUnfXOAFCN0N23sEbS+FzXhX88JCvJst/nKzO9+q67NgYBEqgcaoG4tqt/VVedgkNi0kA7WAA3wyjt5UYMnrg==", + "version": "15.9.2", + "resolved": "https://registry.npmjs.org/@polkadot/rpc-core/-/rpc-core-15.9.2.tgz", + "integrity": "sha512-mRrD3EdIe0r+Qd5kf8hHlK2Ft4HjNDnPBrRNH531bIUTP/fUysjuOaQb1b8y+aHGNloi3VQ+kV39gqcsErrBvQ==", "license": "Apache-2.0", "dependencies": { - "@polkadot/rpc-augment": "15.0.2", - "@polkadot/rpc-provider": "15.0.2", - "@polkadot/types": "15.0.2", - "@polkadot/util": "^13.2.3", + "@polkadot/rpc-augment": "15.9.2", + "@polkadot/rpc-provider": "15.9.2", + "@polkadot/types": "15.9.2", + "@polkadot/util": "^13.4.4", "rxjs": "^7.8.1", - "tslib": "^2.8.0" + "tslib": "^2.8.1" }, "engines": { "node": ">=18" } }, "node_modules/@polkadot/rpc-provider": { - "version": "15.0.2", - "resolved": "https://registry.npmjs.org/@polkadot/rpc-provider/-/rpc-provider-15.0.2.tgz", - "integrity": "sha512-BwLP8gNskzqtQ2kMk+EX6WK4d9TU0XJ/nJg0TKC2dX5sSTpTF2JQIYp1wuOik4rKNXIU/1hKaDSSylMJj7AHeQ==", + "version": "15.9.2", + "resolved": "https://registry.npmjs.org/@polkadot/rpc-provider/-/rpc-provider-15.9.2.tgz", + "integrity": "sha512-yKakGPz+x1GDqWi2sI6KrAApIYEya6LvUetQ/00d85vK49x8dyy9tHyVmF6abakIOf/eJ16sYgLQj8K6tlbnyg==", "license": "Apache-2.0", "dependencies": { - "@polkadot/keyring": "^13.2.3", - "@polkadot/types": "15.0.2", - "@polkadot/types-support": "15.0.2", - "@polkadot/util": "^13.2.3", - "@polkadot/util-crypto": "^13.2.3", - "@polkadot/x-fetch": "^13.2.3", - "@polkadot/x-global": "^13.2.3", - "@polkadot/x-ws": "^13.2.3", + "@polkadot/keyring": "^13.4.4", + "@polkadot/types": "15.9.2", + "@polkadot/types-support": "15.9.2", + "@polkadot/util": "^13.4.4", + "@polkadot/util-crypto": "^13.4.4", + "@polkadot/x-fetch": "^13.4.4", + "@polkadot/x-global": "^13.4.4", + "@polkadot/x-ws": "^13.4.4", "eventemitter3": "^5.0.1", "mock-socket": "^9.3.1", "nock": "^13.5.5", - "tslib": "^2.8.0" + "tslib": "^2.8.1" }, "engines": { "node": ">=18" @@ -1960,107 +1959,107 @@ } }, "node_modules/@polkadot/types": { - "version": "15.0.2", - "resolved": "https://registry.npmjs.org/@polkadot/types/-/types-15.0.2.tgz", - "integrity": "sha512-6gZBnuXU58hQAXWI2daED2OaQwFMxbQdkE8HVGMovMobEf0PxPfIqf+GdnVmWbe09EU9mv2gCWBcdnvHSRBlQg==", + "version": "15.9.2", + "resolved": "https://registry.npmjs.org/@polkadot/types/-/types-15.9.2.tgz", + "integrity": "sha512-8Xv1t1SeT1r00vRCbYEUCAkFxh34zHPlQQXXeuMqoLTaBEldsrMohm5oYZTOKfIemBZGjraNBAVmXv9NMsrRrQ==", "license": "Apache-2.0", "dependencies": { - "@polkadot/keyring": "^13.2.3", - "@polkadot/types-augment": "15.0.2", - "@polkadot/types-codec": "15.0.2", - "@polkadot/types-create": "15.0.2", - "@polkadot/util": "^13.2.3", - "@polkadot/util-crypto": "^13.2.3", + "@polkadot/keyring": "^13.4.4", + "@polkadot/types-augment": "15.9.2", + "@polkadot/types-codec": "15.9.2", + "@polkadot/types-create": "15.9.2", + "@polkadot/util": "^13.4.4", + "@polkadot/util-crypto": "^13.4.4", "rxjs": "^7.8.1", - "tslib": "^2.8.0" + "tslib": "^2.8.1" }, "engines": { "node": ">=18" } }, "node_modules/@polkadot/types-augment": { - "version": "15.0.2", - "resolved": "https://registry.npmjs.org/@polkadot/types-augment/-/types-augment-15.0.2.tgz", - "integrity": "sha512-UiFJVEYML30+V9GdFAHPbA3s4MVQTL1CevsZMnX0+ApvlgEHJMZnVFfYF7jL2bl9BcUYM/zoxEAhj2MpqFFfxw==", + "version": "15.9.2", + "resolved": "https://registry.npmjs.org/@polkadot/types-augment/-/types-augment-15.9.2.tgz", + "integrity": "sha512-Dw+rs85hPoK3QU9xrzIS7Fk/40YmnUYWtesBzDjBFr+fOENocnPMKeqaI4UrHMmhbcxCA58n0Uhydqf6ZyHvgw==", "license": "Apache-2.0", "dependencies": { - "@polkadot/types": "15.0.2", - "@polkadot/types-codec": "15.0.2", - "@polkadot/util": "^13.2.3", - "tslib": "^2.8.0" + "@polkadot/types": "15.9.2", + "@polkadot/types-codec": "15.9.2", + "@polkadot/util": "^13.4.4", + "tslib": "^2.8.1" }, "engines": { "node": ">=18" } }, "node_modules/@polkadot/types-codec": { - "version": "15.0.2", - "resolved": "https://registry.npmjs.org/@polkadot/types-codec/-/types-codec-15.0.2.tgz", - "integrity": "sha512-44Q40p1rl0t7Bl1QUamewqXNVPway9xgqByyifv6ODSGhtt+lFoarb3U4JzqRUuuK0PP57ePB0L8q81Totxeew==", + "version": "15.9.2", + "resolved": "https://registry.npmjs.org/@polkadot/types-codec/-/types-codec-15.9.2.tgz", + "integrity": "sha512-O7N6kBa87Hs2oMjWy+xeA4HnXf1oep6BPzMYkgK84e2H7VqasWDymBQ2medm3A2h+53EOMfePZOE/JQfIBTuqg==", "license": "Apache-2.0", "dependencies": { - "@polkadot/util": "^13.2.3", - "@polkadot/x-bigint": "^13.2.3", - "tslib": "^2.8.0" + "@polkadot/util": "^13.4.4", + "@polkadot/x-bigint": "^13.4.4", + "tslib": "^2.8.1" }, "engines": { "node": ">=18" } }, "node_modules/@polkadot/types-create": { - "version": "15.0.2", - "resolved": "https://registry.npmjs.org/@polkadot/types-create/-/types-create-15.0.2.tgz", - "integrity": "sha512-YhpcqbH3oI87PkgrV6Fez9jWDqFIep0KcS1YWQcwc9gsBNnuour80t2AAK41/tqAYwOZi6tpJwIevnEhVkxFYA==", + "version": "15.9.2", + "resolved": "https://registry.npmjs.org/@polkadot/types-create/-/types-create-15.9.2.tgz", + "integrity": "sha512-dyzP7ShI40ofkgBtP/9aZE86g4i5BIkZK7RdW6XifzQyWBgCRmDnI9k6+wGljzU/FmwdmPmYPxKpNGvjTQ7z9A==", "license": "Apache-2.0", "dependencies": { - "@polkadot/types-codec": "15.0.2", - "@polkadot/util": "^13.2.3", - "tslib": "^2.8.0" + "@polkadot/types-codec": "15.9.2", + "@polkadot/util": "^13.4.4", + "tslib": "^2.8.1" }, "engines": { "node": ">=18" } }, "node_modules/@polkadot/types-known": { - "version": "15.0.2", - "resolved": "https://registry.npmjs.org/@polkadot/types-known/-/types-known-15.0.2.tgz", - "integrity": "sha512-SyBo4xBoesHYiEfdW/nOgaftKgM7+puBWqQXq1Euz0MM5LDLjxBw22Srgk9ulGM6l9MsekIwCyX8geJ6/6J3Cg==", + "version": "15.9.2", + "resolved": "https://registry.npmjs.org/@polkadot/types-known/-/types-known-15.9.2.tgz", + "integrity": "sha512-46LVfW0KNpj6nzEobyCYglj075FokSqACrDOq+i2zTGywNpBSix+XkCs0m3ExrIlIVage+WI4Dg3IlB5T9mxmg==", "license": "Apache-2.0", "dependencies": { - "@polkadot/networks": "^13.2.3", - "@polkadot/types": "15.0.2", - "@polkadot/types-codec": "15.0.2", - "@polkadot/types-create": "15.0.2", - "@polkadot/util": "^13.2.3", - "tslib": "^2.8.0" + "@polkadot/networks": "^13.4.4", + "@polkadot/types": "15.9.2", + "@polkadot/types-codec": "15.9.2", + "@polkadot/types-create": "15.9.2", + "@polkadot/util": "^13.4.4", + "tslib": "^2.8.1" }, "engines": { "node": ">=18" } }, "node_modules/@polkadot/types-support": { - "version": "15.0.2", - "resolved": "https://registry.npmjs.org/@polkadot/types-support/-/types-support-15.0.2.tgz", - "integrity": "sha512-I7Im/4K2/XDZ1LfeQeeNyvIkfvozIPQs8K1/nsICDOmBbvIsjxSeKWHOcFDMJ8AlPEer6bqNQavOyZA/pg9R/Q==", + "version": "15.9.2", + "resolved": "https://registry.npmjs.org/@polkadot/types-support/-/types-support-15.9.2.tgz", + "integrity": "sha512-0pt5vN5qcSWkzodzZimtPirAEYCSmE3YpzCLL81PEgfUyCf7gzWACvgFK7D9lC8S6Qz7Eg5pOQvSBNscFhnLXA==", "license": "Apache-2.0", "dependencies": { - "@polkadot/util": "^13.2.3", - "tslib": "^2.8.0" + "@polkadot/util": "^13.4.4", + "tslib": "^2.8.1" }, "engines": { "node": ">=18" } }, "node_modules/@polkadot/util": { - "version": "13.2.3", - "resolved": "https://registry.npmjs.org/@polkadot/util/-/util-13.2.3.tgz", - "integrity": "sha512-pioNnsig3qHXrfOKMe4Yqos8B8N3/EZUpS+WfTpWnn1VjYban/0GrTXeavPlAwggnY27b8fS6rBzQBhnVYDw8g==", + "version": "13.4.4", + "resolved": "https://registry.npmjs.org/@polkadot/util/-/util-13.4.4.tgz", + "integrity": "sha512-Lveu+8pZLBoAyyv+8X7FI4aTOwLaNXRc9gz1wVaUoGzk5VgmKp/qbPg0a+mfJD8usjf748OVbShhjXvhV3MLiA==", "license": "Apache-2.0", "dependencies": { - "@polkadot/x-bigint": "13.2.3", - "@polkadot/x-global": "13.2.3", - "@polkadot/x-textdecoder": "13.2.3", - "@polkadot/x-textencoder": "13.2.3", + "@polkadot/x-bigint": "13.4.4", + "@polkadot/x-global": "13.4.4", + "@polkadot/x-textdecoder": "13.4.4", + "@polkadot/x-textencoder": "13.4.4", "@types/bn.js": "^5.1.6", "bn.js": "^5.2.1", "tslib": "^2.8.0" @@ -2070,19 +2069,19 @@ } }, "node_modules/@polkadot/util-crypto": { - "version": "13.2.3", - "resolved": "https://registry.npmjs.org/@polkadot/util-crypto/-/util-crypto-13.2.3.tgz", - "integrity": "sha512-5sbggmLbn5eiuVMyPROPlT5roHRqdKHOfSpioNbGvGIZ1qIWVoC1RfsK0NWJOVGDzy6DpQe0KYT/kgcU5Xsrzw==", + "version": "13.4.4", + "resolved": "https://registry.npmjs.org/@polkadot/util-crypto/-/util-crypto-13.4.4.tgz", + "integrity": "sha512-xuXBNdK3Axlj1ItR6n1kH9zgaDNWri9pb/w1HDFx89bHvw6Bl79wA/oHtVGLbHZ1y/bunpsuapznyswhnsaVog==", "license": "Apache-2.0", "dependencies": { "@noble/curves": "^1.3.0", "@noble/hashes": "^1.3.3", - "@polkadot/networks": "13.2.3", - "@polkadot/util": "13.2.3", + "@polkadot/networks": "13.4.4", + "@polkadot/util": "13.4.4", "@polkadot/wasm-crypto": "^7.4.1", "@polkadot/wasm-util": "^7.4.1", - "@polkadot/x-bigint": "13.2.3", - "@polkadot/x-randomvalues": "13.2.3", + "@polkadot/x-bigint": "13.4.4", + "@polkadot/x-randomvalues": "13.4.4", "@scure/base": "^1.1.7", "tslib": "^2.8.0" }, @@ -2090,38 +2089,18 @@ "node": ">=18" }, "peerDependencies": { - "@polkadot/util": "13.2.3" + "@polkadot/util": "13.4.4" } }, - "node_modules/@polkadot/util-crypto/node_modules/@noble/hashes": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", - "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", - "engines": { - "node": ">= 16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@polkadot/util-crypto/node_modules/@scure/base": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.2.1.tgz", - "integrity": "sha512-DGmGtC8Tt63J5GfHgfl5CuAXh96VF/LD8K9Hr/Gv0J2lAoRGlPOMpqMpMbCTOoOJMZCk2Xt+DskdDyn6dEFdzQ==", - "license": "MIT", - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@polkadot/wasm-bridge": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/@polkadot/wasm-bridge/-/wasm-bridge-7.4.1.tgz", - "integrity": "sha512-tdkJaV453tezBxhF39r4oeG0A39sPKGDJmN81LYLf+Fihb7astzwju+u75BRmDrHZjZIv00un3razJEWCxze6g==", - "license": "Apache-2.0", - "dependencies": { - "@polkadot/wasm-util": "7.4.1", - "tslib": "^2.7.0" - }, + "node_modules/@polkadot/wasm-bridge": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/@polkadot/wasm-bridge/-/wasm-bridge-7.4.1.tgz", + "integrity": "sha512-tdkJaV453tezBxhF39r4oeG0A39sPKGDJmN81LYLf+Fihb7astzwju+u75BRmDrHZjZIv00un3razJEWCxze6g==", + "license": "Apache-2.0", + "dependencies": { + "@polkadot/wasm-util": "7.4.1", + "tslib": "^2.7.0" + }, "engines": { "node": ">=18" }, @@ -2218,12 +2197,12 @@ } }, "node_modules/@polkadot/x-bigint": { - "version": "13.2.3", - "resolved": "https://registry.npmjs.org/@polkadot/x-bigint/-/x-bigint-13.2.3.tgz", - "integrity": "sha512-VKgEAh0LsxTd/Hg517Tt5ZU4CySjBwMpaojbkjgv3fOdg1cN7t4eFEUxpyj7mlO0cp22SzDh7nmy4TO98qhLQA==", + "version": "13.4.4", + "resolved": "https://registry.npmjs.org/@polkadot/x-bigint/-/x-bigint-13.4.4.tgz", + "integrity": "sha512-XjChwagc8TbIoWx9N1JwCMOyte417ngobin6vTmLQsgaOlK84LU0/3uc0ea9qUurPopc/Spf1mSMOFp7lRBrIA==", "license": "Apache-2.0", "dependencies": { - "@polkadot/x-global": "13.2.3", + "@polkadot/x-global": "13.4.4", "tslib": "^2.8.0" }, "engines": { @@ -2231,12 +2210,12 @@ } }, "node_modules/@polkadot/x-fetch": { - "version": "13.2.3", - "resolved": "https://registry.npmjs.org/@polkadot/x-fetch/-/x-fetch-13.2.3.tgz", - "integrity": "sha512-7Nmk+8ieEGzz43nc1rX6nH3rQo6rhGmAaIXJWnXY9gOHY0k1me1bJYbP+xDdh8vcLh8eY3D1sESUwG6QYZW2lg==", + "version": "13.4.4", + "resolved": "https://registry.npmjs.org/@polkadot/x-fetch/-/x-fetch-13.4.4.tgz", + "integrity": "sha512-F7awPlvMgu7kW7p4/TWTH18l14zS/8Og71lVO2WZ7HD1ofGG9SQiiNDmNbXl28L1ECOBGcOD1qjVAGEEXPva0Q==", "license": "Apache-2.0", "dependencies": { - "@polkadot/x-global": "13.2.3", + "@polkadot/x-global": "13.4.4", "node-fetch": "^3.3.2", "tslib": "^2.8.0" }, @@ -2245,9 +2224,9 @@ } }, "node_modules/@polkadot/x-global": { - "version": "13.2.3", - "resolved": "https://registry.npmjs.org/@polkadot/x-global/-/x-global-13.2.3.tgz", - "integrity": "sha512-7MYQIAEwBkRcNrgqac5PbB0kNPlI6ISJEy6/Nb+crj8BFjQ8rf11PF49fq0QsvDeuYM1aNLigrvYZNptQs4lbw==", + "version": "13.4.4", + "resolved": "https://registry.npmjs.org/@polkadot/x-global/-/x-global-13.4.4.tgz", + "integrity": "sha512-kwXpzTXOgL2GdMWMzynj9ZpZdjfNvDlpQdlWzDNqTBeIeuklhmhDCA7ZFj3p5OkNUnZoTxNj4zgArYO3VKmQ1g==", "license": "Apache-2.0", "dependencies": { "tslib": "^2.8.0" @@ -2257,29 +2236,29 @@ } }, "node_modules/@polkadot/x-randomvalues": { - "version": "13.2.3", - "resolved": "https://registry.npmjs.org/@polkadot/x-randomvalues/-/x-randomvalues-13.2.3.tgz", - "integrity": "sha512-Zf0GTfLmVk+VzPUmcQSpXjjmFzMTjPhXoLuIoE7xIu73T+vQ+TX9j7DvorN6bIRsnZ9l1SyTZsSf/NTjNZKIZg==", + "version": "13.4.4", + "resolved": "https://registry.npmjs.org/@polkadot/x-randomvalues/-/x-randomvalues-13.4.4.tgz", + "integrity": "sha512-y6sMx2VrXi+V6SLTsd21DJ2Un9s2S7/G1MLDu6IiDBSKcnmOHPV6X43+Y8g+r8B7d9+1+ee/hn1JV+VY+SKSdg==", "license": "Apache-2.0", "dependencies": { - "@polkadot/x-global": "13.2.3", + "@polkadot/x-global": "13.4.4", "tslib": "^2.8.0" }, "engines": { "node": ">=18" }, "peerDependencies": { - "@polkadot/util": "13.2.3", + "@polkadot/util": "13.4.4", "@polkadot/wasm-util": "*" } }, "node_modules/@polkadot/x-textdecoder": { - "version": "13.2.3", - "resolved": "https://registry.npmjs.org/@polkadot/x-textdecoder/-/x-textdecoder-13.2.3.tgz", - "integrity": "sha512-i8hRXPtGknmdm3FYv6/94I52VXHJZa5sgYNw1+Hqb4Jqmq4awUjea35CKXd/+aw70Qn8Ngg31l2GoiH494fa+Q==", + "version": "13.4.4", + "resolved": "https://registry.npmjs.org/@polkadot/x-textdecoder/-/x-textdecoder-13.4.4.tgz", + "integrity": "sha512-fXvM2ts0IUx6F/Fd1Yg4ypHCffmUtTSwOtFpqBPvWghKYnmvTbGVrSidGizu6as7KAp4dsum9mYKdRmScBHHzg==", "license": "Apache-2.0", "dependencies": { - "@polkadot/x-global": "13.2.3", + "@polkadot/x-global": "13.4.4", "tslib": "^2.8.0" }, "engines": { @@ -2287,12 +2266,12 @@ } }, "node_modules/@polkadot/x-textencoder": { - "version": "13.2.3", - "resolved": "https://registry.npmjs.org/@polkadot/x-textencoder/-/x-textencoder-13.2.3.tgz", - "integrity": "sha512-wJI3Bb/dC4zyBXJFm5+ZhyBXWoI5wvP8k8qX0/ZC0PQsgSAqs7LVhiofk4Wd94n0P41W5re58LrGXLyziSAshw==", + "version": "13.4.4", + "resolved": "https://registry.npmjs.org/@polkadot/x-textencoder/-/x-textencoder-13.4.4.tgz", + "integrity": "sha512-WpPR2vMAiXS2AN8MfolzWbo5WPEmy5FVZFgwZraJZP8RKfzEuntbY5Nb25p/PIjsPJ1zKU0DE8uVvDcGjxIo7A==", "license": "Apache-2.0", "dependencies": { - "@polkadot/x-global": "13.2.3", + "@polkadot/x-global": "13.4.4", "tslib": "^2.8.0" }, "engines": { @@ -2300,12 +2279,12 @@ } }, "node_modules/@polkadot/x-ws": { - "version": "13.2.3", - "resolved": "https://registry.npmjs.org/@polkadot/x-ws/-/x-ws-13.2.3.tgz", - "integrity": "sha512-Y6MTAWgcnrnx/LkBx65X3ZyoJH5EFj3tXtflRoKg1+PLHSLuNBV7Wi5mLcE70z4e5c+4hgBbLq+8SqCqzFtSPw==", + "version": "13.4.4", + "resolved": "https://registry.npmjs.org/@polkadot/x-ws/-/x-ws-13.4.4.tgz", + "integrity": "sha512-qfbFb0Tdjsx5QawICduPTc3326SP+lEdggfyT4HmfrM50nvmCR/82TRAtEWKK7EPhXjoE/cBL/i5VO4d68DBQQ==", "license": "Apache-2.0", "dependencies": { - "@polkadot/x-global": "13.2.3", + "@polkadot/x-global": "13.4.4", "tslib": "^2.8.0", "ws": "^8.18.0" }, @@ -2340,48 +2319,48 @@ "license": "MIT" }, "node_modules/@scure/base": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.6.tgz", - "integrity": "sha512-ok9AWwhcgYuGG3Zfhyqg+zwl+Wn5uE+dwC0NV/2qQkx4dABbb/bx96vWu8NSj+BNjjSjno+JRYRjle1jV08k3g==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.2.4.tgz", + "integrity": "sha512-5Yy9czTO47mqz+/J8GM6GIId4umdCk1wc1q8rKERQulIoc8VP9pzDcghv10Tl2E7R96ZUx/PhND3ESYUQX8NuQ==", + "license": "MIT", "funding": { "url": "https://paulmillr.com/funding/" } }, "node_modules/@scure/bip32": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.1.0.tgz", - "integrity": "sha512-ftTW3kKX54YXLCxH6BB7oEEoJfoE2pIgw7MINKAs5PsS6nqKPuKk1haTF/EuHmYqG330t5GSrdmtRuHaY1a62Q==", - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.6.2.tgz", + "integrity": "sha512-t96EPDMbtGgtb7onKKqxRLfE5g05k7uHnHRM2xdE6BP/ZmxaLtPek4J4KfVn/90IQNrU1IOAqMgiDtUdtbe3nw==", + "dev": true, + "license": "MIT", "dependencies": { - "@noble/hashes": "~1.1.1", - "@noble/secp256k1": "~1.6.0", - "@scure/base": "~1.1.0" + "@noble/curves": "~1.8.1", + "@noble/hashes": "~1.7.1", + "@scure/base": "~1.2.2" + }, + "funding": { + "url": "https://paulmillr.com/funding/" } }, "node_modules/@scure/bip39": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.1.0.tgz", - "integrity": "sha512-pwrPOS16VeTKg98dYXQyIjJEcWfz7/1YJIwxUEPFfQPtc86Ym/1sVgQ2RLoD43AazMk2l/unK4ITySSpW2+82w==", - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.5.4.tgz", + "integrity": "sha512-TFM4ni0vKvCfBpohoh+/lY05i9gRbSwXWngAsF4CABQxoaOHijxuaZ2R6cStDQ5CHtHO9aGJTr4ksVJASRRyMA==", + "dev": true, + "license": "MIT", "dependencies": { - "@noble/hashes": "~1.1.1", - "@scure/base": "~1.1.0" + "@noble/hashes": "~1.7.1", + "@scure/base": "~1.2.4" + }, + "funding": { + "url": "https://paulmillr.com/funding/" } }, "node_modules/@sentry/core": { "version": "5.30.0", "resolved": "https://registry.npmjs.org/@sentry/core/-/core-5.30.0.tgz", "integrity": "sha512-TmfrII8w1PQZSZgPpUESqjB+jC6MvZJZdLtE/0hZ+SrnKhW3x5WlYLvTXZpcWePYBku7rl2wn1RZu6uT0qCTeg==", + "license": "BSD-3-Clause", "dependencies": { "@sentry/hub": "5.30.0", "@sentry/minimal": "5.30.0", @@ -2396,12 +2375,14 @@ "node_modules/@sentry/core/node_modules/tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "license": "0BSD" }, "node_modules/@sentry/hub": { "version": "5.30.0", "resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-5.30.0.tgz", "integrity": "sha512-2tYrGnzb1gKz2EkMDQcfLrDTvmGcQPuWxLnJKXJvYTQDGLlEvi2tWz1VIHjunmOvJrB5aIQLhm+dcMRwFZDCqQ==", + "license": "BSD-3-Clause", "dependencies": { "@sentry/types": "5.30.0", "@sentry/utils": "5.30.0", @@ -2414,12 +2395,14 @@ "node_modules/@sentry/hub/node_modules/tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "license": "0BSD" }, "node_modules/@sentry/minimal": { "version": "5.30.0", "resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-5.30.0.tgz", "integrity": "sha512-BwWb/owZKtkDX+Sc4zCSTNcvZUq7YcH3uAVlmh/gtR9rmUvbzAA3ewLuB3myi4wWRAMEtny6+J/FN/x+2wn9Xw==", + "license": "BSD-3-Clause", "dependencies": { "@sentry/hub": "5.30.0", "@sentry/types": "5.30.0", @@ -2432,12 +2415,14 @@ "node_modules/@sentry/minimal/node_modules/tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "license": "0BSD" }, "node_modules/@sentry/node": { "version": "5.30.0", "resolved": "https://registry.npmjs.org/@sentry/node/-/node-5.30.0.tgz", "integrity": "sha512-Br5oyVBF0fZo6ZS9bxbJZG4ApAjRqAnqFFurMVJJdunNb80brh7a5Qva2kjhm+U6r9NJAB5OmDyPkA1Qnt+QVg==", + "license": "BSD-3-Clause", "dependencies": { "@sentry/core": "5.30.0", "@sentry/hub": "5.30.0", @@ -2453,23 +2438,17 @@ "node": ">=6" } }, - "node_modules/@sentry/node/node_modules/cookie": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", - "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", - "engines": { - "node": ">= 0.6" - } - }, "node_modules/@sentry/node/node_modules/tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "license": "0BSD" }, "node_modules/@sentry/tracing": { "version": "5.30.0", "resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-5.30.0.tgz", "integrity": "sha512-dUFowCr0AIMwiLD7Fs314Mdzcug+gBVo/+NCMyDw8tFxJkwWAKl7Qa2OZxLQ0ZHjakcj1hNKfCQJ9rhyfOl4Aw==", + "license": "MIT", "dependencies": { "@sentry/hub": "5.30.0", "@sentry/minimal": "5.30.0", @@ -2484,12 +2463,14 @@ "node_modules/@sentry/tracing/node_modules/tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "license": "0BSD" }, "node_modules/@sentry/types": { "version": "5.30.0", "resolved": "https://registry.npmjs.org/@sentry/types/-/types-5.30.0.tgz", "integrity": "sha512-R8xOqlSTZ+htqrfteCWU5Nk0CDN5ApUTvrlvBuiH1DyP6czDZ4ktbZB0hAgBlVcK0U+qpD3ag3Tqqpa5Q67rPw==", + "license": "BSD-3-Clause", "engines": { "node": ">=6" } @@ -2498,6 +2479,7 @@ "version": "5.30.0", "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-5.30.0.tgz", "integrity": "sha512-zaYmoH0NWWtvnJjC9/CBseXMtKHm/tm40sz3YfJRxeQjyzRqNQPgivpd9R/oDJCYj999mzdW382p/qi2ypjLww==", + "license": "BSD-3-Clause", "dependencies": { "@sentry/types": "5.30.0", "tslib": "^1.9.3" @@ -2509,24 +2491,26 @@ "node_modules/@sentry/utils/node_modules/tslib": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "license": "0BSD" }, "node_modules/@sindresorhus/is": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", - "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-5.6.0.tgz", + "integrity": "sha512-TV7t8GKYaJWsn00tFDqBw8+Uqmr8A0fRU1tvTQhyZzGv0sJCGRQL3JGMI3ucuKo3XIZdUP+Lx7/gh2t3lewy7g==", "dev": true, + "license": "MIT", "engines": { - "node": ">=10" + "node": ">=14.16" }, "funding": { "url": "https://github.com/sindresorhus/is?sponsor=1" } }, "node_modules/@solidity-parser/parser": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.18.0.tgz", - "integrity": "sha512-yfORGUIPgLck41qyN7nbwJRAx17/jAIXCTanHOJZhB6PJ1iAk/84b/xlsVKFSyNyLXIj0dhppoE0+CRws7wlzA==", + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.19.0.tgz", + "integrity": "sha512-RV16k/qIxW/wWc+mLzV3ARyKUaMUTBy9tOLMzFhtNSKYeTAanQ3a5MudJKf/8arIFnA2L27SNjarQKmFg0w/jA==", "dev": true, "license": "MIT" }, @@ -2545,16 +2529,16 @@ } }, "node_modules/@substrate/connect-extension-protocol": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@substrate/connect-extension-protocol/-/connect-extension-protocol-2.2.1.tgz", - "integrity": "sha512-GoafTgm/Jey9E4Xlj4Z5ZBt/H4drH2CNq8VrAro80rtoznrXnFDNVivLQzZN0Xaj2g8YXSn9pC9Oc9IovYZJXw==", + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/@substrate/connect-extension-protocol/-/connect-extension-protocol-2.2.2.tgz", + "integrity": "sha512-t66jwrXA0s5Goq82ZtjagLNd7DPGCNjHeehRlE/gcJmJ+G56C0W+2plqOMRicJ8XGR1/YFnUSEqUFiSNbjGrAA==", "license": "GPL-3.0-only", "optional": true }, "node_modules/@substrate/connect-known-chains": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/@substrate/connect-known-chains/-/connect-known-chains-1.8.1.tgz", - "integrity": "sha512-WkqXvuLWL1g136nxAoGkclybsVpo8claHeBl/8iA99ECAk4pWLtoCh8PoYrFEE1HfY4rk+A0krPybDlcDa/G4g==", + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@substrate/connect-known-chains/-/connect-known-chains-1.10.0.tgz", + "integrity": "sha512-k0GwwxJE1twaob6qMOBalENDfOEnMt/zdAuUjbrqhjBD6EL1SAWVuTu+bpwXrznd/ims6NSN4TLp9aTf1yE5tg==", "license": "GPL-3.0-only", "optional": true }, @@ -2588,6 +2572,7 @@ "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-5.0.1.tgz", "integrity": "sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==", "dev": true, + "license": "MIT", "dependencies": { "defer-to-connect": "^2.0.1" }, @@ -2596,24 +2581,39 @@ } }, "node_modules/@tsconfig/node10": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", - "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==" + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", + "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", + "license": "MIT" }, "node_modules/@tsconfig/node12": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", - "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==" + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "license": "MIT" }, "node_modules/@tsconfig/node14": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", - "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==" + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "license": "MIT" }, "node_modules/@tsconfig/node16": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz", - "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==" + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "license": "MIT" + }, + "node_modules/@tybys/wasm-util": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.9.0.tgz", + "integrity": "sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } }, "node_modules/@typechain/ethers-v6": { "version": "0.5.1", @@ -2652,6 +2652,7 @@ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", "dev": true, + "license": "MIT", "dependencies": { "at-least-node": "^1.0.0", "graceful-fs": "^4.2.0", @@ -2662,27 +2663,6 @@ "node": ">=10" } }, - "node_modules/@typechain/hardhat/node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/@typechain/hardhat/node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true, - "engines": { - "node": ">= 10.0.0" - } - }, "node_modules/@types/bn.js": { "version": "5.1.6", "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.6.tgz", @@ -2692,18 +2672,6 @@ "@types/node": "*" } }, - "node_modules/@types/cacheable-request": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", - "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", - "dev": true, - "dependencies": { - "@types/http-cache-semantics": "*", - "@types/keyv": "^3.1.4", - "@types/node": "*", - "@types/responselike": "^1.0.0" - } - }, "node_modules/@types/chai": { "version": "4.3.20", "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.20.tgz", @@ -2712,10 +2680,11 @@ "license": "MIT" }, "node_modules/@types/chai-as-promised": { - "version": "7.1.5", - "resolved": "https://registry.npmjs.org/@types/chai-as-promised/-/chai-as-promised-7.1.5.tgz", - "integrity": "sha512-jStwss93SITGBwt/niYrkf2C+/1KTeZCZl1LaeezTlqppAKeoQC7jxyqYuP72sxBGKCIbw7oHgbYssIRzT5FCQ==", + "version": "7.1.8", + "resolved": "https://registry.npmjs.org/@types/chai-as-promised/-/chai-as-promised-7.1.8.tgz", + "integrity": "sha512-ThlRVIJhr69FLlh6IctTXFkmhtP3NpMZ2QGq69StYLyKZFp/HOp1VdKZj7RvfNWYYcJ1xlbLGLLWj1UvP5u/Gw==", "dev": true, + "license": "MIT", "dependencies": { "@types/chai": "*" } @@ -2725,16 +2694,18 @@ "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==", "dev": true, + "license": "MIT", "dependencies": { "@types/minimatch": "*", "@types/node": "*" } }, "node_modules/@types/http-cache-semantics": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.3.tgz", - "integrity": "sha512-V46MYLFp08Wf2mmaBhvgjStM3tPa+2GAdy/iqoX+noX1//zje2x4XmrIU0cAwyClATsTmahbtoQ2EwP7I5WSiA==", - "dev": true + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz", + "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==", + "dev": true, + "license": "MIT" }, "node_modules/@types/json5": { "version": "0.0.29", @@ -2743,25 +2714,18 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/keyv": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", - "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", - "dev": true, - "dependencies": { - "@types/node": "*" - } - }, "node_modules/@types/lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/@types/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw==" + "integrity": "sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw==", + "license": "MIT" }, "node_modules/@types/minimatch": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/mocha": { "version": "10.0.10", @@ -2771,72 +2735,63 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "22.10.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz", - "integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==", + "version": "22.14.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.14.1.tgz", + "integrity": "sha512-u0HuPQwe/dHrItgHHpmw3N2fYCR6x4ivMNbPHRkBVP4CvN+kiRrKHWk3i8tXiO/joPwXLMYvF9TTF0eqgHIuOw==", "license": "MIT", "dependencies": { - "undici-types": "~6.20.0" + "undici-types": "~6.21.0" } }, - "node_modules/@types/node/node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", - "license": "MIT" - }, "node_modules/@types/pbkdf2": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@types/pbkdf2/-/pbkdf2-3.1.0.tgz", - "integrity": "sha512-Cf63Rv7jCQ0LaL8tNXmEyqTHuIJxRdlS5vMh1mj5voN4+QFhVZnlZruezqpWYDiJ8UTzhP0VmeLXCmBk66YrMQ==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@types/pbkdf2/-/pbkdf2-3.1.2.tgz", + "integrity": "sha512-uRwJqmiXmh9++aSu1VNEn3iIxWOhd8AHXNSdlaLfdAAdSTY9jYVeGWnzejM3dvrkbqE3/hyQkQQ29IFATEGlew==", + "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*" } }, "node_modules/@types/prettier": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.2.tgz", - "integrity": "sha512-KufADq8uQqo1pYKVIYzfKbJfBAc0sOeXqGbFaSpv8MRmC/zXgowNZmFcbngndGk922QDmOASEXUZCaY48gs4cg==", - "dev": true + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.3.tgz", + "integrity": "sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==", + "dev": true, + "license": "MIT" }, "node_modules/@types/qs": { - "version": "6.9.7", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", - "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==" - }, - "node_modules/@types/responselike": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.2.tgz", - "integrity": "sha512-/4YQT5Kp6HxUDb4yhRkm0bJ7TbjvTddqX7PZ5hz6qV3pxSo72f/6YPRo+Mu2DU307tm9IioO69l7uAwn5XNcFA==", - "dev": true, - "dependencies": { - "@types/node": "*" - } + "version": "6.9.18", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.18.tgz", + "integrity": "sha512-kK7dgTYDyGqS+e2Q4aK9X3D7q234CIZ1Bv0q/7Z5IwRDoADNU81xXJK/YVyLbLTZCoIwUoDoffFeF+p/eIklAA==", + "license": "MIT" }, "node_modules/@types/secp256k1": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@types/secp256k1/-/secp256k1-4.0.3.tgz", - "integrity": "sha512-Da66lEIFeIz9ltsdMZcpQvmrmmoqrfju8pm1BH8WbYjZSwUgCwXLb9C+9XYogwBITnbsSaMdVPb2ekf7TV+03w==", + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@types/secp256k1/-/secp256k1-4.0.6.tgz", + "integrity": "sha512-hHxJU6PAEUn0TP4S/ZOzuTUvJWuZ6eIKeNKb5RBpODvSl6hp1Wrw4s7ATY50rklRCScUDpHzVA/DQdSjJ3UoYQ==", + "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*" } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.18.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.18.1.tgz", - "integrity": "sha512-Ncvsq5CT3Gvh+uJG0Lwlho6suwDfUXH0HztslDf5I+F2wAFAZMRwYLEorumpKLzmO2suAXZ/td1tBg4NZIi9CQ==", + "version": "8.30.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.30.1.tgz", + "integrity": "sha512-v+VWphxMjn+1t48/jO4t950D6KR8JaJuNXzi33Ve6P8sEmPr5k6CEXjdGwT6+LodVnEa91EQCtwjWNUCPweo+Q==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.18.1", - "@typescript-eslint/type-utils": "8.18.1", - "@typescript-eslint/utils": "8.18.1", - "@typescript-eslint/visitor-keys": "8.18.1", + "@typescript-eslint/scope-manager": "8.30.1", + "@typescript-eslint/type-utils": "8.30.1", + "@typescript-eslint/utils": "8.30.1", + "@typescript-eslint/visitor-keys": "8.30.1", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", - "ts-api-utils": "^1.3.0" + "ts-api-utils": "^2.0.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2848,20 +2803,20 @@ "peerDependencies": { "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.8.0" + "typescript": ">=4.8.4 <5.9.0" } }, "node_modules/@typescript-eslint/parser": { - "version": "8.18.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.18.1.tgz", - "integrity": "sha512-rBnTWHCdbYM2lh7hjyXqxk70wvon3p2FyaniZuey5TrcGBpfhVp0OxOa6gxr9Q9YhZFKyfbEnxc24ZnVbbUkCA==", + "version": "8.30.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.30.1.tgz", + "integrity": "sha512-H+vqmWwT5xoNrXqWs/fesmssOW70gxFlgcMlYcBaWNPIEWDgLa4W9nkSPmhuOgLnXq9QYgkZ31fhDyLhleCsAg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.18.1", - "@typescript-eslint/types": "8.18.1", - "@typescript-eslint/typescript-estree": "8.18.1", - "@typescript-eslint/visitor-keys": "8.18.1", + "@typescript-eslint/scope-manager": "8.30.1", + "@typescript-eslint/types": "8.30.1", + "@typescript-eslint/typescript-estree": "8.30.1", + "@typescript-eslint/visitor-keys": "8.30.1", "debug": "^4.3.4" }, "engines": { @@ -2873,18 +2828,18 @@ }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.8.0" + "typescript": ">=4.8.4 <5.9.0" } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.18.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.18.1.tgz", - "integrity": "sha512-HxfHo2b090M5s2+/9Z3gkBhI6xBH8OJCFjH9MhQ+nnoZqxU3wNxkLT+VWXWSFWc3UF3Z+CfPAyqdCTdoXtDPCQ==", + "version": "8.30.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.30.1.tgz", + "integrity": "sha512-+C0B6ChFXZkuaNDl73FJxRYT0G7ufVPOSQkqkpM/U198wUwUFOtgo1k/QzFh1KjpBitaK7R1tgjVz6o9HmsRPg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.18.1", - "@typescript-eslint/visitor-keys": "8.18.1" + "@typescript-eslint/types": "8.30.1", + "@typescript-eslint/visitor-keys": "8.30.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2895,16 +2850,16 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.18.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.18.1.tgz", - "integrity": "sha512-jAhTdK/Qx2NJPNOTxXpMwlOiSymtR2j283TtPqXkKBdH8OAMmhiUfP0kJjc/qSE51Xrq02Gj9NY7MwK+UxVwHQ==", + "version": "8.30.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.30.1.tgz", + "integrity": "sha512-64uBF76bfQiJyHgZISC7vcNz3adqQKIccVoKubyQcOnNcdJBvYOILV1v22Qhsw3tw3VQu5ll8ND6hycgAR5fEA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.18.1", - "@typescript-eslint/utils": "8.18.1", + "@typescript-eslint/typescript-estree": "8.30.1", + "@typescript-eslint/utils": "8.30.1", "debug": "^4.3.4", - "ts-api-utils": "^1.3.0" + "ts-api-utils": "^2.0.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2915,13 +2870,13 @@ }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.8.0" + "typescript": ">=4.8.4 <5.9.0" } }, "node_modules/@typescript-eslint/types": { - "version": "8.18.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.18.1.tgz", - "integrity": "sha512-7uoAUsCj66qdNQNpH2G8MyTFlgerum8ubf21s3TSM3XmKXuIn+H2Sifh/ES2nPOPiYSRJWAk0fDkW0APBWcpfw==", + "version": "8.30.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.30.1.tgz", + "integrity": "sha512-81KawPfkuulyWo5QdyG/LOKbspyyiW+p4vpn4bYO7DM/hZImlVnFwrpCTnmNMOt8CvLRr5ojI9nU1Ekpw4RcEw==", "dev": true, "license": "MIT", "engines": { @@ -2933,20 +2888,20 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.18.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.18.1.tgz", - "integrity": "sha512-z8U21WI5txzl2XYOW7i9hJhxoKKNG1kcU4RzyNvKrdZDmbjkmLBo8bgeiOJmA06kizLI76/CCBAAGlTlEeUfyg==", + "version": "8.30.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.30.1.tgz", + "integrity": "sha512-kQQnxymiUy9tTb1F2uep9W6aBiYODgq5EMSk6Nxh4Z+BDUoYUSa029ISs5zTzKBFnexQEh71KqwjKnRz58lusQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.18.1", - "@typescript-eslint/visitor-keys": "8.18.1", + "@typescript-eslint/types": "8.30.1", + "@typescript-eslint/visitor-keys": "8.30.1", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", - "ts-api-utils": "^1.3.0" + "ts-api-utils": "^2.0.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2956,59 +2911,20 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "typescript": ">=4.8.4 <5.8.0" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" + "typescript": ">=4.8.4 <5.9.0" } }, "node_modules/@typescript-eslint/utils": { - "version": "8.18.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.18.1.tgz", - "integrity": "sha512-8vikiIj2ebrC4WRdcAdDcmnu9Q/MXXwg+STf40BVfT8exDqBCUPdypvzcUPxEqRGKg9ALagZ0UWcYCtn+4W2iQ==", + "version": "8.30.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.30.1.tgz", + "integrity": "sha512-T/8q4R9En2tcEsWPQgB5BQ0XJVOtfARcUvOa8yJP3fh9M/mXraLxZrkCfGb6ChrO/V3W+Xbd04RacUEqk1CFEQ==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.18.1", - "@typescript-eslint/types": "8.18.1", - "@typescript-eslint/typescript-estree": "8.18.1" + "@typescript-eslint/scope-manager": "8.30.1", + "@typescript-eslint/types": "8.30.1", + "@typescript-eslint/typescript-estree": "8.30.1" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -3019,17 +2935,17 @@ }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <5.8.0" + "typescript": ">=4.8.4 <5.9.0" } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.18.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.18.1.tgz", - "integrity": "sha512-Vj0WLm5/ZsD013YeUKn+K0y8p1M0jPpxOkKdbD1wB0ns53a5piVY02zjf072TblEweAbcYiFiPoSMF3kp+VhhQ==", + "version": "8.30.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.30.1.tgz", + "integrity": "sha512-aEhgas7aJ6vZnNFC7K4/vMGDGyOiqWcYZPpIWrTKuTAlsvDNKy2GFDqh9smL+iq069ZvR0YzEeq0B8NJlLzjFA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.18.1", + "@typescript-eslint/types": "8.30.1", "eslint-visitor-keys": "^4.2.0" }, "engines": { @@ -3054,56 +2970,311 @@ } }, "node_modules/@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", + "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", "dev": true, "license": "ISC" }, - "node_modules/abbrev": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", - "integrity": "sha512-LEyx4aLEC3x6T0UguF6YILf+ntvmOaWsVfENmIW0E9H09vKlLDGelMjjSm0jkDHALj8A8quZ/HapKNigzwge+Q==", - "dev": true - }, - "node_modules/abort-controller": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "node_modules/@unrs/resolver-binding-darwin-arm64": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.5.0.tgz", + "integrity": "sha512-YmocNlEcX/AgJv8gI41bhjMOTcKcea4D2nRIbZj+MhRtSH5+vEU8r/pFuTuoF+JjVplLsBueU+CILfBPVISyGQ==", + "cpu": [ + "arm64" + ], "dev": true, - "dependencies": { - "event-target-shim": "^5.0.0" - }, - "engines": { - "node": ">=6.5" - } + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] }, - "node_modules/acorn": { - "version": "8.14.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", - "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", + "node_modules/@unrs/resolver-binding-darwin-x64": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.5.0.tgz", + "integrity": "sha512-qpUrXgH4e/0xu1LOhPEdfgSY3vIXOxDQv370NEL8npN8h40HcQDA+Pl2r4HBW6tTXezWIjxUFcP7tj529RZtDw==", + "cpu": [ + "x64" + ], + "dev": true, "license": "MIT", - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } + "optional": true, + "os": [ + "darwin" + ] }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "node_modules/@unrs/resolver-binding-freebsd-x64": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.5.0.tgz", + "integrity": "sha512-3tX8r8vgjvZzaJZB4jvxUaaFCDCb3aWDCpZN3EjhGnnwhztslI05KSG5NY/jNjlcZ5QWZ7dEZZ/rNBFsmTaSPw==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.5.0.tgz", + "integrity": "sha512-FH+ixzBKaUU9fWOj3TYO+Yn/eO6kYvMLV9eNJlJlkU7OgrxkCmiMS6wUbyT0KA3FOZGxnEQ2z3/BHgYm2jqeLA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.5.0.tgz", + "integrity": "sha512-pxCgXMgwB/4PfqFQg73lMhmWwcC0j5L+dNXhZoz/0ek0iS/oAWl65fxZeT/OnU7fVs52MgdP2q02EipqJJXHSg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-gnu": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.5.0.tgz", + "integrity": "sha512-FX2FV7vpLE/+Z0NZX9/1pwWud5Wocm/2PgpUXbT5aSV3QEB10kBPJAzssOQylvdj8mOHoKl5pVkXpbCwww/T2g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-musl": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.5.0.tgz", + "integrity": "sha512-+gF97xst1BZb28T3nwwzEtq2ewCoMDGKsenYsZuvpmNrW0019G1iUAunZN+FG55L21y+uP7zsGX06OXDQ/viKw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.5.0.tgz", + "integrity": "sha512-5bEmVcQw9js8JYM2LkUBw5SeELSIxX+qKf9bFrfFINKAp4noZ//hUxLpbF7u/3gTBN1GsER6xOzIZlw/VTdXtA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.5.0.tgz", + "integrity": "sha512-GGk/8TPUsf1Q99F+lzMdjE6sGL26uJCwQ9TlvBs8zR3cLQNw/MIumPN7zrs3GFGySjnwXc8gA6J3HKbejywmqA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-s390x-gnu": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.5.0.tgz", + "integrity": "sha512-5uRkFYYVNAeVaA4W/CwugjFN3iDOHCPqsBLCCOoJiMfFMMz4evBRsg+498OFa9w6VcTn2bD5aI+RRayaIgk2Sw==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-gnu": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.5.0.tgz", + "integrity": "sha512-j905CZH3nehYy6NimNqC2B14pxn4Ltd7guKMyPTzKehbFXTUgihQS/ZfHQTdojkMzbSwBOSgq1dOrY+IpgxDsA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-musl": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.5.0.tgz", + "integrity": "sha512-dmLevQTuzQRwu5A+mvj54R5aye5I4PVKiWqGxg8tTaYP2k2oTs/3Mo8mgnhPk28VoYCi0fdFYpgzCd4AJndQvQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-wasm32-wasi": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.5.0.tgz", + "integrity": "sha512-LtJMhwu7avhoi+kKfAZOKN773RtzLBVVF90YJbB0wyMpUj9yQPeA+mteVUI9P70OG/opH47FeV5AWeaNWWgqJg==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@napi-rs/wasm-runtime": "^0.2.8" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@unrs/resolver-binding-win32-arm64-msvc": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.5.0.tgz", + "integrity": "sha512-FTZBxLL4SO1mgIM86KykzJmPeTPisBDHQV6xtfDXbTMrentuZ6SdQKJUV5BWaoUK3p8kIULlrCcucqdCnk8Npg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-ia32-msvc": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.5.0.tgz", + "integrity": "sha512-i5bB7vJ1waUsFciU/FKLd4Zw0VnAkvhiJ4//jYQXyDUuiLKodmtQZVTcOPU7pp97RrNgCFtXfC1gnvj/DHPJTw==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-x64-msvc": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.5.0.tgz", + "integrity": "sha512-wAvXp4k7jhioi4SebXW/yfzzYwsUCr9kIX4gCsUFKpCTUf8Mi7vScJXI3S+kupSUf0LbVHudR8qBbe2wFMSNUw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/abbrev": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", + "integrity": "sha512-LEyx4aLEC3x6T0UguF6YILf+ntvmOaWsVfENmIW0E9H09vKlLDGelMjjSm0jkDHALj8A8quZ/HapKNigzwge+Q==", + "dev": true, + "license": "ISC" + }, + "node_modules/abitype": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/abitype/-/abitype-1.0.8.tgz", + "integrity": "sha512-ZeiI6h3GnW06uYDLx0etQtX/p8E24UaHHBj57RSjK7YBFe7iuVn07EDpOeP451D06sF27VOz9JJPlIKJmXgkEg==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/wevm" + }, + "peerDependencies": { + "typescript": ">=5.0.4", + "zod": "^3 >=3.22.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + }, + "zod": { + "optional": true + } + } + }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "dev": true, + "license": "MIT", + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, + "node_modules/acorn": { + "version": "8.14.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz", + "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==", + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } }, "node_modules/acorn-walk": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "version": "8.3.4", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz", + "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==", + "license": "MIT", + "dependencies": { + "acorn": "^8.11.0" + }, "engines": { "node": ">=0.4.0" } @@ -3112,19 +3283,22 @@ "version": "0.4.16", "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.16.tgz", "integrity": "sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg==", + "license": "MIT", "engines": { "node": ">=0.3.0" } }, "node_modules/aes-js": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.0.0.tgz", - "integrity": "sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw==" + "version": "4.0.0-beta.5", + "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-4.0.0-beta.5.tgz", + "integrity": "sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==", + "license": "MIT" }, "node_modules/agent-base": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "license": "MIT", "dependencies": { "debug": "4" }, @@ -3136,6 +3310,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "license": "MIT", "dependencies": { "clean-stack": "^2.0.0", "indent-string": "^4.0.0" @@ -3149,6 +3324,7 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -3165,6 +3341,7 @@ "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", "integrity": "sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg==", "dev": true, + "license": "BSD-3-Clause OR MIT", "optional": true, "engines": { "node": ">=0.4.2" @@ -3174,29 +3351,42 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", + "license": "ISC", "dependencies": { "string-width": "^4.1.0" } }, "node_modules/ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/ansi-escapes": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.0.0.tgz", - "integrity": "sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==", - "dev": true, + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", "license": "MIT", "dependencies": { - "environment": "^1.0.0" + "type-fest": "^0.21.3" }, "engines": { - "node": ">=18" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-escapes/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -3206,6 +3396,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", "engines": { "node": ">=8" } @@ -3214,6 +3405,7 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, @@ -3238,6 +3430,7 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "license": "ISC", "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -3249,31 +3442,34 @@ "node_modules/arg": { "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==" + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "license": "MIT" }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "license": "Python-2.0" }, "node_modules/array-back": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/array-buffer-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", - "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", + "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.5", - "is-array-buffer": "^3.0.4" + "call-bound": "^1.0.3", + "is-array-buffer": "^3.0.5" }, "engines": { "node": ">= 0.4" @@ -3308,23 +3504,25 @@ "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/array.prototype.findlastindex": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", - "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.6.tgz", + "integrity": "sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", + "es-abstract": "^1.23.9", "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "es-shim-unscopables": "^1.0.2" + "es-object-atoms": "^1.1.1", + "es-shim-unscopables": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -3334,16 +3532,16 @@ } }, "node_modules/array.prototype.flat": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", - "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz", + "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -3353,17 +3551,17 @@ } }, "node_modules/array.prototype.flatmap": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", - "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz", + "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" - }, + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" + }, "engines": { "node": ">= 0.4" }, @@ -3372,20 +3570,19 @@ } }, "node_modules/arraybuffer.prototype.slice": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", - "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", + "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", "dev": true, "license": "MIT", "dependencies": { "array-buffer-byte-length": "^1.0.1", - "call-bind": "^1.0.5", + "call-bind": "^1.0.8", "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", - "es-errors": "^1.2.1", - "get-intrinsic": "^1.2.3", - "is-array-buffer": "^3.0.4", - "is-shared-array-buffer": "^1.0.2" + "es-abstract": "^1.23.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "is-array-buffer": "^3.0.4" }, "engines": { "node": ">= 0.4" @@ -3399,26 +3596,31 @@ "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", "dev": true, + "license": "MIT", "engines": { "node": "*" } }, "node_modules/assertion-tools": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/assertion-tools/-/assertion-tools-2.2.1.tgz", - "integrity": "sha512-JlA1S16Ox93PnYb45HvxNcax/Ii4gqTO8HLGa/ykj/ddp8EEHlokn6inJR2yMiz173WSFkCc0ciLJzGeaYBANw==", + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/assertion-tools/-/assertion-tools-8.0.3.tgz", + "integrity": "sha512-Z+GFFmEv7ZU7OxjnE/e9d2r4YlBZW7lT7GB4AxtkqsonxUMb24PL/3lOJd17OC7louN6Gx0NbzeVIwqtVOwIgg==", "dev": true, + "hasInstallScript": true, "license": "ISC", "dependencies": { "ethers": "^5.7.2", "jsonld": "^8.1.0", - "merkletreejs": "^0.3.2" + "merkletreejs": "^0.3.2", + "n3": "^1.23.1", + "rdf-canonize": "^4.0.1", + "uuid": "^8.3.2" } }, "node_modules/assertion-tools/node_modules/ethers": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.7.2.tgz", - "integrity": "sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.8.0.tgz", + "integrity": "sha512-DUq+7fHrCg1aPDFCHx6UIPb3nmt2XMpM7Y/g2gLhsl3lIBqeAfOJIl1qEvRf2uq3BiKxmh6Fh5pfp2ieyek7Kg==", "dev": true, "funding": [ { @@ -3432,36 +3634,36 @@ ], "license": "MIT", "dependencies": { - "@ethersproject/abi": "5.7.0", - "@ethersproject/abstract-provider": "5.7.0", - "@ethersproject/abstract-signer": "5.7.0", - "@ethersproject/address": "5.7.0", - "@ethersproject/base64": "5.7.0", - "@ethersproject/basex": "5.7.0", - "@ethersproject/bignumber": "5.7.0", - "@ethersproject/bytes": "5.7.0", - "@ethersproject/constants": "5.7.0", - "@ethersproject/contracts": "5.7.0", - "@ethersproject/hash": "5.7.0", - "@ethersproject/hdnode": "5.7.0", - "@ethersproject/json-wallets": "5.7.0", - "@ethersproject/keccak256": "5.7.0", - "@ethersproject/logger": "5.7.0", - "@ethersproject/networks": "5.7.1", - "@ethersproject/pbkdf2": "5.7.0", - "@ethersproject/properties": "5.7.0", - "@ethersproject/providers": "5.7.2", - "@ethersproject/random": "5.7.0", - "@ethersproject/rlp": "5.7.0", - "@ethersproject/sha2": "5.7.0", - "@ethersproject/signing-key": "5.7.0", - "@ethersproject/solidity": "5.7.0", - "@ethersproject/strings": "5.7.0", - "@ethersproject/transactions": "5.7.0", - "@ethersproject/units": "5.7.0", - "@ethersproject/wallet": "5.7.0", - "@ethersproject/web": "5.7.1", - "@ethersproject/wordlists": "5.7.0" + "@ethersproject/abi": "5.8.0", + "@ethersproject/abstract-provider": "5.8.0", + "@ethersproject/abstract-signer": "5.8.0", + "@ethersproject/address": "5.8.0", + "@ethersproject/base64": "5.8.0", + "@ethersproject/basex": "5.8.0", + "@ethersproject/bignumber": "5.8.0", + "@ethersproject/bytes": "5.8.0", + "@ethersproject/constants": "5.8.0", + "@ethersproject/contracts": "5.8.0", + "@ethersproject/hash": "5.8.0", + "@ethersproject/hdnode": "5.8.0", + "@ethersproject/json-wallets": "5.8.0", + "@ethersproject/keccak256": "5.8.0", + "@ethersproject/logger": "5.8.0", + "@ethersproject/networks": "5.8.0", + "@ethersproject/pbkdf2": "5.8.0", + "@ethersproject/properties": "5.8.0", + "@ethersproject/providers": "5.8.0", + "@ethersproject/random": "5.8.0", + "@ethersproject/rlp": "5.8.0", + "@ethersproject/sha2": "5.8.0", + "@ethersproject/signing-key": "5.8.0", + "@ethersproject/solidity": "5.8.0", + "@ethersproject/strings": "5.8.0", + "@ethersproject/transactions": "5.8.0", + "@ethersproject/units": "5.8.0", + "@ethersproject/wallet": "5.8.0", + "@ethersproject/web": "5.8.0", + "@ethersproject/wordlists": "5.8.0" } }, "node_modules/ast-parents": { @@ -3485,18 +3687,31 @@ "version": "1.5.2", "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", "integrity": "sha512-nSVgobk4rv61R9PUSDtYt7mPVB2olxNR5RWJcAsH676/ef11bUZwvu7+RGYrYauVdDPcO519v68wRhXQtxsV9w==", - "dev": true + "dev": true, + "license": "MIT" + }, + "node_modules/async-function": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", + "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" }, "node_modules/at-least-node": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", "dev": true, + "license": "ISC", "engines": { "node": ">= 4.0.0" } @@ -3521,6 +3736,7 @@ "version": "0.21.4", "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", + "license": "MIT", "dependencies": { "follow-redirects": "^1.14.0" } @@ -3528,52 +3744,86 @@ "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "license": "MIT" }, "node_modules/base-x": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.9.tgz", - "integrity": "sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==", + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.11.tgz", + "integrity": "sha512-xz7wQ8xDhdyP7tQxwdteLYeFfS68tSMNCZ/Y37WJ4bhGfKPpqEIlmIyueQHqOyoPhE6xNUqjzRr8ra0eF9VRvA==", + "dev": true, + "license": "MIT", "dependencies": { "safe-buffer": "^5.0.1" } }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, "node_modules/bech32": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz", - "integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==" + "integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==", + "license": "MIT" }, "node_modules/bignumber.js": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.0.tgz", - "integrity": "sha512-4LwHK4nfDOraBCtst+wOWIHbu1vhvAPJK8g8nROd4iuc3PSEjWif/qwbkh8jwCJz6yDBvtU4KPynETgrfh7y3A==", + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.2.1.tgz", + "integrity": "sha512-+NzaKgOUvInq9TIUZ1+DRspzf/HApkCwD4btfuasFTdrfnOxqx853TgDpMolp+uv4RpRp7bPcEU2zKr9+fRmyw==", "dev": true, + "license": "MIT", "engines": { "node": "*" } }, "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "license": "MIT", "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/blakejs": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/blakejs/-/blakejs-1.2.1.tgz", - "integrity": "sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ==" + "integrity": "sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ==", + "dev": true, + "license": "MIT" }, "node_modules/bn.js": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", - "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==" + "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==", + "license": "MIT" }, "node_modules/boxen": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz", "integrity": "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==", + "license": "MIT", "dependencies": { "ansi-align": "^3.0.0", "camelcase": "^6.2.0", @@ -3592,18 +3842,19 @@ } }, "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "balanced-match": "^1.0.0" } }, "node_modules/braces": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "license": "MIT", "dependencies": { "fill-range": "^7.1.1" }, @@ -3614,7 +3865,8 @@ "node_modules/brorand": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==" + "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==", + "license": "MIT" }, "node_modules/brotli-wasm": { "version": "2.0.1", @@ -3626,12 +3878,15 @@ "node_modules/browser-stdout": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==" + "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", + "license": "ISC" }, "node_modules/browserify-aes": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "dev": true, + "license": "MIT", "dependencies": { "buffer-xor": "^1.0.3", "cipher-base": "^1.0.0", @@ -3645,6 +3900,8 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", "integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==", + "dev": true, + "license": "MIT", "dependencies": { "base-x": "^3.0.2" } @@ -3653,112 +3910,150 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/bs58check/-/bs58check-2.1.2.tgz", "integrity": "sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==", + "dev": true, + "license": "MIT", "dependencies": { "bs58": "^4.0.0", "create-hash": "^1.1.0", "safe-buffer": "^5.1.2" } }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "license": "MIT" }, "node_modules/buffer-reverse": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/buffer-reverse/-/buffer-reverse-1.0.1.tgz", "integrity": "sha512-M87YIUBsZ6N924W57vDwT/aOu8hw7ZgdByz6ijksLjmHJELBASmYTTlNHRgjE+pTsT9oJXGaDSgqqwfdHotDUg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/buffer-xor": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", - "integrity": "sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==" - }, - "node_modules/bufferutil": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.6.tgz", - "integrity": "sha512-jduaYOYtnio4aIAyc6UbvPCVcgq7nYpVnucyxr6eCYg/Woad9Hf/oxxBRDnGGjPfjUm6j5O/uBWhIu4iLebFaw==", - "hasInstallScript": true, - "optional": true, - "peer": true, - "dependencies": { - "node-gyp-build": "^4.3.0" - }, - "engines": { - "node": ">=6.14.2" - } + "integrity": "sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==", + "dev": true, + "license": "MIT" }, "node_modules/bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", "engines": { "node": ">= 0.8" } }, "node_modules/cacheable-lookup": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-6.1.0.tgz", - "integrity": "sha512-KJ/Dmo1lDDhmW2XDPMo+9oiy/CeqosPguPCrgcVzKyZrL6pM1gU2GmPY/xo6OQPTUaA/c0kwHuywB4E6nmT9ww==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-7.0.0.tgz", + "integrity": "sha512-+qJyx4xiKra8mZrcwhjMRMUhD5NR1R8esPkzIYxX96JiecFoxAXFuz/GpR3+ev4PE1WamHip78wV0vcmPQtp8w==", "dev": true, + "license": "MIT", "engines": { - "node": ">=10.6.0" + "node": ">=14.16" } }, "node_modules/cacheable-request": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.4.tgz", - "integrity": "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==", + "version": "10.2.14", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-10.2.14.tgz", + "integrity": "sha512-zkDT5WAF4hSSoUgyfg5tFIxz8XQK+25W/TLVojJTMKBaxevLBBtLxgqguAuVQB8PVW79FVjHcU+GJ9tVbDZ9mQ==", "dev": true, + "license": "MIT", "dependencies": { - "clone-response": "^1.0.2", - "get-stream": "^5.1.0", - "http-cache-semantics": "^4.0.0", - "keyv": "^4.0.0", - "lowercase-keys": "^2.0.0", - "normalize-url": "^6.0.1", - "responselike": "^2.0.0" + "@types/http-cache-semantics": "^4.0.2", + "get-stream": "^6.0.1", + "http-cache-semantics": "^4.1.1", + "keyv": "^4.5.3", + "mimic-response": "^4.0.0", + "normalize-url": "^8.0.0", + "responselike": "^3.0.0" }, "engines": { - "node": ">=8" + "node": ">=14.16" } }, "node_modules/cacheable-request/node_modules/get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", "dev": true, - "dependencies": { - "pump": "^3.0.0" - }, + "license": "MIT", "engines": { - "node": ">=8" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/cacheable-request/node_modules/lowercase-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "node_modules/call-bind": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", + "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.0", + "es-define-property": "^1.0.0", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.2" + }, "engines": { - "node": ">=8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/call-bind": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", - "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", "license": "MIT", "dependencies": { - "es-define-property": "^1.0.0", "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.1" + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" }, "engines": { "node": ">= 0.4" @@ -3772,14 +4067,16 @@ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/camelcase": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.1.tgz", - "integrity": "sha512-tVI4q5jjFV5CavAU8DXfza/TJcZutVKo/5Foskmsqcm0MsL91moHvwiGNnqaa2o6PF/7yT5ikDRcVcl8Rj6LCA==", + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "license": "MIT", "engines": { "node": ">=10" }, @@ -3791,7 +4088,8 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/canonicalize/-/canonicalize-1.0.8.tgz", "integrity": "sha512-0CNTVCLZggSh7bc5VkX5WWPWO+cyZbNd07IHIsSXLia/eAq+r836hgk+8BKoEh7949Mda87VUOitx5OddVj64A==", - "dev": true + "dev": true, + "license": "Apache-2.0" }, "node_modules/chai": { "version": "4.5.0", @@ -3813,21 +4111,23 @@ } }, "node_modules/chai-as-promised": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-7.1.1.tgz", - "integrity": "sha512-azL6xMoi+uxu6z4rhWQ1jbdUhOMhis2PvscD/xjLqNMkv3BPPp2JyyuTHOrf9BOosGpNQ11v6BKv/g57RXbiaA==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-7.1.2.tgz", + "integrity": "sha512-aBDHZxRzYnUYuIAIPBH2s511DjlKPzXNlXSGFC8CwmroWQLfrW0LtE1nK3MAwwNhJPa9raEjNCmRoFpG0Hurdw==", "dev": true, + "license": "WTFPL", "dependencies": { "check-error": "^1.0.2" }, "peerDependencies": { - "chai": ">= 2.1.2 < 5" + "chai": ">= 2.1.2 < 6" } }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -3863,60 +4163,45 @@ } }, "node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "license": "MIT", "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" + "readdirp": "^4.0.1" }, "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/chokidar/node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dependencies": { - "picomatch": "^2.2.1" + "node": ">= 14.16.0" }, - "engines": { - "node": ">=8.10.0" + "funding": { + "url": "https://paulmillr.com/funding/" } }, "node_modules/ci-info": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", - "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==" + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "license": "MIT" }, "node_modules/cipher-base": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.6.tgz", + "integrity": "sha512-3Ek9H3X6pj5TgenXYtNWdaBon1tgYCaebd+XPg0keyjEbEfkD4KkmAxkQ/i1vYvxdcT5nscLBfq9VJRmCBcFSw==", + "dev": true, + "license": "MIT", "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" + "inherits": "^2.0.4", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">= 0.10" } }, "node_modules/clean-stack": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "license": "MIT", "engines": { "node": ">=6" } @@ -3925,6 +4210,7 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", + "license": "MIT", "engines": { "node": ">=6" }, @@ -3953,6 +4239,7 @@ "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.5.tgz", "integrity": "sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==", "dev": true, + "license": "MIT", "dependencies": { "string-width": "^4.2.0" }, @@ -3993,56 +4280,13 @@ "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "node_modules/cli-truncate/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/cli-truncate/node_modules/emoji-regex": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", - "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", + "node_modules/cli-truncate/node_modules/emoji-regex": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", + "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", "dev": true, "license": "MIT" }, - "node_modules/cli-truncate/node_modules/is-fullwidth-code-point": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", - "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-truncate/node_modules/slice-ansi": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", - "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.0.0", - "is-fullwidth-code-point": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" - } - }, "node_modules/cli-truncate/node_modules/string-width": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", @@ -4081,28 +4325,18 @@ "version": "7.0.4", "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "license": "ISC", "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", "wrap-ansi": "^7.0.0" } }, - "node_modules/clone-response": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", - "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", - "dev": true, - "dependencies": { - "mimic-response": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "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==", + "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -4113,7 +4347,8 @@ "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==" + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" }, "node_modules/colorette": { "version": "2.0.20", @@ -4126,6 +4361,7 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", "dependencies": { "delayed-stream": "~1.0.0" }, @@ -4144,6 +4380,7 @@ "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.2.1.tgz", "integrity": "sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg==", "dev": true, + "license": "MIT", "dependencies": { "array-back": "^3.1.0", "find-replace": "^3.0.0", @@ -4159,6 +4396,7 @@ "resolved": "https://registry.npmjs.org/command-line-usage/-/command-line-usage-6.1.3.tgz", "integrity": "sha512-sH5ZSPr+7UStsloltmDh7Ce5fb8XPlHyoPzTpyyMuYCtervL65+ubVZ6Q61cFtFl62UyJlc8/JwERRbAFPUqgw==", "dev": true, + "license": "MIT", "dependencies": { "array-back": "^4.0.2", "chalk": "^2.4.2", @@ -4174,6 +4412,7 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, + "license": "MIT", "dependencies": { "color-convert": "^1.9.0" }, @@ -4186,6 +4425,7 @@ "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.2.tgz", "integrity": "sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -4195,6 +4435,7 @@ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -4209,6 +4450,7 @@ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "1.1.3" } @@ -4217,13 +4459,15 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/command-line-usage/node_modules/escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.8.0" } @@ -4233,6 +4477,7 @@ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -4242,6 +4487,7 @@ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^3.0.0" }, @@ -4254,24 +4500,27 @@ "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/commander": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", - "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "version": "13.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-13.1.0.tgz", + "integrity": "sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==", "dev": true, "license": "MIT", "engines": { - "node": ">=14" + "node": ">=18" } }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" }, "node_modules/config-chain": { "version": "1.1.13", @@ -4284,6 +4533,15 @@ "proto-list": "~1.2.1" } }, + "node_modules/cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/cosmiconfig": { "version": "8.3.6", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", @@ -4315,6 +4573,8 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "dev": true, + "license": "MIT", "dependencies": { "cipher-base": "^1.0.1", "inherits": "^2.0.1", @@ -4327,6 +4587,8 @@ "version": "1.1.7", "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "dev": true, + "license": "MIT", "dependencies": { "cipher-base": "^1.0.3", "create-hash": "^1.1.0", @@ -4339,13 +4601,15 @@ "node_modules/create-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==" + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "license": "MIT" }, "node_modules/cross-env": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", "dev": true, + "license": "MIT", "dependencies": { "cross-spawn": "^7.0.1" }, @@ -4360,10 +4624,11 @@ } }, "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", "dev": true, + "license": "MIT", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -4387,26 +4652,28 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz", "integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/data-uri-to-buffer": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.0.tgz", - "integrity": "sha512-Vr3mLBA8qWmcuschSLAOogKgQ/Jwxulv3RNE4FXnYWRGujzrRWQI4m12fQqRkwX06C0KanhLr4hK+GydchZsaA==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", + "license": "MIT", "engines": { "node": ">= 12" } }, "node_modules/data-view-buffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", - "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", + "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.6", + "call-bound": "^1.0.3", "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" + "is-data-view": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -4416,31 +4683,31 @@ } }, "node_modules/data-view-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", - "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", + "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bound": "^1.0.3", "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" + "is-data-view": "^1.0.2" }, "engines": { "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/inspect-js" } }, "node_modules/data-view-byte-offset": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", - "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", + "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.6", + "call-bound": "^1.0.2", "es-errors": "^1.3.0", "is-data-view": "^1.0.1" }, @@ -4478,6 +4745,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", + "license": "MIT", "engines": { "node": ">=10" }, @@ -4490,6 +4758,7 @@ "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", "dev": true, + "license": "MIT", "dependencies": { "mimic-response": "^3.1.0" }, @@ -4505,6 +4774,7 @@ "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -4513,10 +4783,11 @@ } }, "node_modules/deep-eql": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", - "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==", + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.4.tgz", + "integrity": "sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==", "dev": true, + "license": "MIT", "dependencies": { "type-detect": "^4.0.0" }, @@ -4529,6 +4800,7 @@ "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", "dev": true, + "license": "MIT", "engines": { "node": ">=4.0.0" } @@ -4537,13 +4809,15 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/defer-to-connect": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" } @@ -4552,6 +4826,7 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, "license": "MIT", "dependencies": { "es-define-property": "^1.0.0", @@ -4587,6 +4862,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", "engines": { "node": ">=0.4.0" } @@ -4596,6 +4872,7 @@ "resolved": "https://registry.npmjs.org/delete-empty/-/delete-empty-3.0.0.tgz", "integrity": "sha512-ZUyiwo76W+DYnKsL3Kim6M/UOavPdBJgDYWOmuQhYaZvJH0AXAHbUNyEDtRbBra8wqqr686+63/0azfEk1ebUQ==", "dev": true, + "license": "MIT", "dependencies": { "ansi-colors": "^4.1.0", "minimist": "^1.2.0", @@ -4609,12 +4886,59 @@ "node": ">=10" } }, + "node_modules/delete-empty/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/delete-empty/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/delete-empty/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/delete-empty/node_modules/rimraf": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", "deprecated": "Rimraf versions prior to v4 are no longer supported", "dev": true, + "license": "ISC", "dependencies": { "glob": "^7.1.3" }, @@ -4626,14 +4950,16 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", "engines": { "node": ">= 0.8" } }, "node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", + "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", + "license": "BSD-3-Clause", "engines": { "node": ">=0.3.1" } @@ -4655,6 +4981,7 @@ "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", "dev": true, + "license": "MIT", "dependencies": { "path-type": "^4.0.0" }, @@ -4667,6 +4994,7 @@ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", "dev": true, + "license": "Apache-2.0", "dependencies": { "esutils": "^2.0.2" }, @@ -4675,9 +5003,9 @@ } }, "node_modules/dotenv": { - "version": "16.4.7", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz", - "integrity": "sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==", + "version": "16.5.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.5.0.tgz", + "integrity": "sha512-m/C+AwOAr9/W1UOIZUo232ejMNnJAJtYQjUbHoNTBNTJSvqzzDh7vnrei3o3r3m9blf6ZoDkvcw0VmozNRFJxg==", "license": "BSD-2-Clause", "engines": { "node": ">=12" @@ -4686,16 +5014,32 @@ "url": "https://dotenvx.com" } }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/elliptic": { - "version": "6.5.4", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", - "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", + "version": "6.6.1", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.6.1.tgz", + "integrity": "sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==", + "license": "MIT", "dependencies": { "bn.js": "^4.11.9", "brorand": "^1.1.0", @@ -4707,54 +5051,31 @@ } }, "node_modules/elliptic/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" - }, - "node_modules/elliptic/node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", + "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", + "license": "MIT" }, "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==" + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" }, "node_modules/encode-utf8": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/encode-utf8/-/encode-utf8-1.0.3.tgz", - "integrity": "sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw==" - }, - "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "dependencies": { - "once": "^1.4.0" - } - }, - "node_modules/enhanced-resolve": { - "version": "5.17.1", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", - "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - }, - "engines": { - "node": ">=10.13.0" - } + "integrity": "sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw==", + "license": "MIT" }, "node_modules/enquirer": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", - "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.4.1.tgz", + "integrity": "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==", + "license": "MIT", "dependencies": { - "ansi-colors": "^4.1.1" + "ansi-colors": "^4.1.1", + "strip-ansi": "^6.0.1" }, "engines": { "node": ">=8.6" @@ -4764,6 +5085,7 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "license": "MIT", "engines": { "node": ">=6" } @@ -4786,63 +5108,69 @@ "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", "dev": true, + "license": "MIT", "dependencies": { "is-arrayish": "^0.2.1" } }, "node_modules/es-abstract": { - "version": "1.23.5", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.5.tgz", - "integrity": "sha512-vlmniQ0WNPwXqA0BnmwV3Ng7HxiGlh6r5U6JcTMNx8OilcAGqVJBHJcPjqOMaczU9fRuRK5Px2BdVyPRnKMMVQ==", + "version": "1.23.9", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.9.tgz", + "integrity": "sha512-py07lI0wjxAC/DcfK1S6G7iANonniZwTISvdPzk9hzeH0IZIshbuuFxLIU96OyF89Yb9hiqWn8M/bY83KY5vzA==", "dev": true, "license": "MIT", "dependencies": { - "array-buffer-byte-length": "^1.0.1", - "arraybuffer.prototype.slice": "^1.0.3", + "array-buffer-byte-length": "^1.0.2", + "arraybuffer.prototype.slice": "^1.0.4", "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", - "data-view-buffer": "^1.0.1", - "data-view-byte-length": "^1.0.1", - "data-view-byte-offset": "^1.0.0", - "es-define-property": "^1.0.0", + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "data-view-buffer": "^1.0.2", + "data-view-byte-length": "^1.0.2", + "data-view-byte-offset": "^1.0.1", + "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", - "es-set-tostringtag": "^2.0.3", - "es-to-primitive": "^1.2.1", - "function.prototype.name": "^1.1.6", - "get-intrinsic": "^1.2.4", - "get-symbol-description": "^1.0.2", + "es-set-tostringtag": "^2.1.0", + "es-to-primitive": "^1.3.0", + "function.prototype.name": "^1.1.8", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.0", + "get-symbol-description": "^1.1.0", "globalthis": "^1.0.4", - "gopd": "^1.0.1", + "gopd": "^1.2.0", "has-property-descriptors": "^1.0.2", - "has-proto": "^1.0.3", - "has-symbols": "^1.0.3", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", "hasown": "^2.0.2", - "internal-slot": "^1.0.7", - "is-array-buffer": "^3.0.4", + "internal-slot": "^1.1.0", + "is-array-buffer": "^3.0.5", "is-callable": "^1.2.7", - "is-data-view": "^1.0.1", - "is-negative-zero": "^2.0.3", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.3", - "is-string": "^1.0.7", - "is-typed-array": "^1.1.13", - "is-weakref": "^1.0.2", + "is-data-view": "^1.0.2", + "is-regex": "^1.2.1", + "is-shared-array-buffer": "^1.0.4", + "is-string": "^1.1.1", + "is-typed-array": "^1.1.15", + "is-weakref": "^1.1.0", + "math-intrinsics": "^1.1.0", "object-inspect": "^1.13.3", "object-keys": "^1.1.1", - "object.assign": "^4.1.5", + "object.assign": "^4.1.7", + "own-keys": "^1.0.1", "regexp.prototype.flags": "^1.5.3", - "safe-array-concat": "^1.1.2", - "safe-regex-test": "^1.0.3", - "string.prototype.trim": "^1.2.9", - "string.prototype.trimend": "^1.0.8", + "safe-array-concat": "^1.1.3", + "safe-push-apply": "^1.0.0", + "safe-regex-test": "^1.1.0", + "set-proto": "^1.0.0", + "string.prototype.trim": "^1.2.10", + "string.prototype.trimend": "^1.0.9", "string.prototype.trimstart": "^1.0.8", - "typed-array-buffer": "^1.0.2", - "typed-array-byte-length": "^1.0.1", - "typed-array-byte-offset": "^1.0.2", - "typed-array-length": "^1.0.6", - "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.15" + "typed-array-buffer": "^1.0.3", + "typed-array-byte-length": "^1.0.3", + "typed-array-byte-offset": "^1.0.4", + "typed-array-length": "^1.0.7", + "unbox-primitive": "^1.1.0", + "which-typed-array": "^1.1.18" }, "engines": { "node": ">= 0.4" @@ -4852,13 +5180,10 @@ } }, "node_modules/es-define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", - "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", "license": "MIT", - "dependencies": { - "get-intrinsic": "^1.2.4" - }, "engines": { "node": ">= 0.4" } @@ -4873,10 +5198,9 @@ } }, "node_modules/es-object-atoms": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", - "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", - "dev": true, + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", "license": "MIT", "dependencies": { "es-errors": "^1.3.0" @@ -4886,28 +5210,31 @@ } }, "node_modules/es-set-tostringtag": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", - "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", - "dev": true, + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", "license": "MIT", "dependencies": { - "get-intrinsic": "^1.2.4", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", "has-tostringtag": "^1.0.2", - "hasown": "^2.0.1" + "hasown": "^2.0.2" }, "engines": { "node": ">= 0.4" } }, "node_modules/es-shim-unscopables": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", - "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz", + "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==", "dev": true, "license": "MIT", "dependencies": { - "hasown": "^2.0.0" + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" } }, "node_modules/es-to-primitive": { @@ -4929,9 +5256,10 @@ } }, "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "license": "MIT", "engines": { "node": ">=6" } @@ -4940,6 +5268,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "license": "MIT", "engines": { "node": ">=10" }, @@ -4952,6 +5281,7 @@ "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", "integrity": "sha512-yhi5S+mNTOuRvyW4gWlg5W1byMaQGWWSYHXsuFZ7GBo7tpyOwi2EdzMP/QWxh9hwkD2m+wDVHJsxhRIj+v/b/A==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "esprima": "^2.7.1", "estraverse": "^1.9.1", @@ -4969,19 +5299,6 @@ "source-map": "~0.2.0" } }, - "node_modules/escodegen/node_modules/esprima": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", - "integrity": "sha512-OarPfz0lFCiW4/AV2Oy1Rp9qu0iusTKqykwTspGCZtPxmF81JR4MmIebvF1F9+UOKth2ZubLQ4XGGaU+hSn99A==", - "dev": true, - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/escodegen/node_modules/estraverse": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", @@ -4996,6 +5313,7 @@ "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", "dev": true, + "license": "MIT", "dependencies": { "prelude-ls": "~1.1.2", "type-check": "~0.3.2" @@ -5009,6 +5327,7 @@ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", "dev": true, + "license": "MIT", "dependencies": { "deep-is": "~0.1.3", "fast-levenshtein": "~2.0.6", @@ -5035,6 +5354,7 @@ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", "dev": true, + "license": "MIT", "dependencies": { "prelude-ls": "~1.1.2" }, @@ -5135,26 +5455,25 @@ } }, "node_modules/eslint-import-resolver-typescript": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.7.0.tgz", - "integrity": "sha512-Vrwyi8HHxY97K5ebydMtffsWAn1SCR9eol49eCd5fJS4O1WV7PaAjbcjmbfJJSMz/t4Mal212Uz/fQZrOB8mow==", + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.10.0.tgz", + "integrity": "sha512-aV3/dVsT0/H9BtpNwbaqvl+0xGMRGzncLyhm793NFGvbwGGvzyAykqWZ8oZlZuGwuHkwJjhWJkG1cM3ynvd2pQ==", "dev": true, "license": "ISC", "dependencies": { "@nolyfill/is-core-module": "1.0.39", - "debug": "^4.3.7", - "enhanced-resolve": "^5.15.0", - "fast-glob": "^3.3.2", - "get-tsconfig": "^4.7.5", - "is-bun-module": "^1.0.2", - "is-glob": "^4.0.3", - "stable-hash": "^0.0.4" + "debug": "^4.4.0", + "get-tsconfig": "^4.10.0", + "is-bun-module": "^2.0.0", + "stable-hash": "^0.0.5", + "tinyglobby": "^0.2.12", + "unrs-resolver": "^1.3.2" }, "engines": { "node": "^14.18.0 || >=16.0.0" }, "funding": { - "url": "https://opencollective.com/unts/projects/eslint-import-resolver-ts" + "url": "https://opencollective.com/eslint-import-resolver-typescript" }, "peerDependencies": { "eslint": "*", @@ -5232,9 +5551,20 @@ "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" } }, - "node_modules/eslint-plugin-import/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "node_modules/eslint-plugin-import/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, "license": "MIT", @@ -5247,6 +5577,7 @@ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", "dev": true, + "license": "Apache-2.0", "dependencies": { "esutils": "^2.0.2" }, @@ -5254,6 +5585,29 @@ "node": ">=0.10.0" } }, + "node_modules/eslint-plugin-import/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eslint-plugin-import/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/eslint-plugin-mocha": { "version": "10.5.0", "resolved": "https://registry.npmjs.org/eslint-plugin-mocha/-/eslint-plugin-mocha-10.5.0.tgz", @@ -5273,14 +5627,14 @@ } }, "node_modules/eslint-plugin-prettier": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.1.tgz", - "integrity": "sha512-gH3iR3g4JfF+yYPaJYkN7jEl9QbweL/YfkoRlNnuIEHEz1vHVlCmWOS+eGGiRuzHQXdJFCOTxRgvju9b8VUmrw==", + "version": "5.2.6", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.6.tgz", + "integrity": "sha512-mUcf7QG2Tjk7H055Jk0lGBjbgDnfrvqjhXh9t2xLMSCjZVcw9Rb1V6sVNXO0th3jgeO7zllWPTNRil3JW94TnQ==", "dev": true, "license": "MIT", "dependencies": { "prettier-linter-helpers": "^1.0.0", - "synckit": "^0.9.1" + "synckit": "^0.11.0" }, "engines": { "node": "^14.18.0 || >=16.0.0" @@ -5291,7 +5645,7 @@ "peerDependencies": { "@types/eslint": ">=8.0.0", "eslint": ">=8.0.0", - "eslint-config-prettier": "*", + "eslint-config-prettier": ">= 7.0.0 <10.0.0 || >=10.1.0", "prettier": ">=3.0.0" }, "peerDependenciesMeta": { @@ -5325,6 +5679,7 @@ "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", "dev": true, + "license": "MIT", "dependencies": { "eslint-visitor-keys": "^2.0.0" }, @@ -5343,6 +5698,7 @@ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=10" } @@ -5360,16 +5716,28 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, + "license": "MIT", "dependencies": { - "is-glob": "^4.0.3" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=10.13.0" + "node": "*" } }, "node_modules/espree": { @@ -5390,6 +5758,20 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/esprima": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha512-OarPfz0lFCiW4/AV2Oy1Rp9qu0iusTKqykwTspGCZtPxmF81JR4MmIebvF1F9+UOKth2ZubLQ4XGGaU+hSn99A==", + "dev": true, + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/esquery": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", @@ -5431,56 +5813,27 @@ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=0.10.0" } }, "node_modules/ethereum-bloom-filters": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/ethereum-bloom-filters/-/ethereum-bloom-filters-1.0.10.tgz", - "integrity": "sha512-rxJ5OFN3RwjQxDcFP2Z5+Q9ho4eIdEmSc2ht0fCu8Se9nbXjZ7/031uXoUYJ87KHCOdVeiUuwSnoS7hmYAGVHA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/ethereum-bloom-filters/-/ethereum-bloom-filters-1.2.0.tgz", + "integrity": "sha512-28hyiE7HVsWubqhpVLVmZXFd4ITeHi+BUu05o9isf0GUpMtzBUi+8/gFrGaGYzvGAJQmJ3JKj77Mk9G98T84rA==", "dev": true, - "dependencies": { - "js-sha3": "^0.8.0" - } - }, - "node_modules/ethereum-cryptography": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-1.1.2.tgz", - "integrity": "sha512-XDSJlg4BD+hq9N2FjvotwUET9Tfxpxc3kWGE2AqUG5vcbeunnbImVk3cj6e/xT3phdW21mE8R5IugU4fspQDcQ==", - "dependencies": { - "@noble/hashes": "1.1.2", - "@noble/secp256k1": "1.6.3", - "@scure/bip32": "1.1.0", - "@scure/bip39": "1.1.0" - } - }, - "node_modules/ethereumjs-abi": { - "version": "0.6.8", - "resolved": "git+ssh://git@github.com/ethereumjs/ethereumjs-abi.git#ee3994657fa7a427238e6ba92a84d0b529bbcde0", "license": "MIT", "dependencies": { - "bn.js": "^4.11.8", - "ethereumjs-util": "^6.0.0" - } - }, - "node_modules/ethereumjs-abi/node_modules/@types/bn.js": { - "version": "4.11.6", - "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz", - "integrity": "sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==", - "dependencies": { - "@types/node": "*" + "@noble/hashes": "^1.4.0" } }, - "node_modules/ethereumjs-abi/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" - }, - "node_modules/ethereumjs-abi/node_modules/ethereum-cryptography": { + "node_modules/ethereum-cryptography": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", + "dev": true, + "license": "MIT", "dependencies": { "@types/pbkdf2": "^3.0.0", "@types/secp256k1": "^4.0.1", @@ -5499,25 +5852,12 @@ "setimmediate": "^1.0.5" } }, - "node_modules/ethereumjs-abi/node_modules/ethereumjs-util": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz", - "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==", - "dependencies": { - "@types/bn.js": "^4.11.3", - "bn.js": "^4.11.0", - "create-hash": "^1.1.2", - "elliptic": "^6.5.2", - "ethereum-cryptography": "^0.1.3", - "ethjs-util": "0.1.6", - "rlp": "^2.2.3" - } - }, "node_modules/ethereumjs-util": { "version": "7.1.5", "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.1.5.tgz", "integrity": "sha512-SDl5kKrQAudFBUe5OJM9Ac6WmMyYmXX/6sTmLZ3ffG2eY6ZIGBes3pEDxNN6V72WyOw4CPD5RomKdsa8DAAwLg==", "dev": true, + "license": "MPL-2.0", "dependencies": { "@types/bn.js": "^5.1.0", "bn.js": "^5.1.2", @@ -5529,33 +5869,10 @@ "node": ">=10.0.0" } }, - "node_modules/ethereumjs-util/node_modules/ethereum-cryptography": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", - "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", - "dev": true, - "dependencies": { - "@types/pbkdf2": "^3.0.0", - "@types/secp256k1": "^4.0.1", - "blakejs": "^1.1.0", - "browserify-aes": "^1.2.0", - "bs58check": "^2.1.2", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "hash.js": "^1.1.7", - "keccak": "^3.0.0", - "pbkdf2": "^3.0.17", - "randombytes": "^2.1.0", - "safe-buffer": "^5.1.2", - "scrypt-js": "^3.0.0", - "secp256k1": "^4.0.1", - "setimmediate": "^1.0.5" - } - }, "node_modules/ethers": { - "version": "6.13.4", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.13.4.tgz", - "integrity": "sha512-21YtnZVg4/zKkCQPjrDj38B1r4nQvTZLopUGMLQ1ePU2zV/joCfDC3t3iKQjWRzjjjbzR+mdAIoikeBRNkdllA==", + "version": "6.13.5", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.13.5.tgz", + "integrity": "sha512-+knKNieu5EKRThQJWwqaJ10a6HE9sSehGeqWN65//wE7j47ZpFhKAnHB/JJFibwwg61I/koxaPsXbXpD/skNOQ==", "funding": [ { "type": "individual", @@ -5580,12 +5897,6 @@ "node": ">=14.0.0" } }, - "node_modules/ethers/node_modules/@adraffy/ens-normalize": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz", - "integrity": "sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==", - "license": "MIT" - }, "node_modules/ethers/node_modules/@noble/curves": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz", @@ -5619,18 +5930,18 @@ "undici-types": "~6.19.2" } }, - "node_modules/ethers/node_modules/aes-js": { - "version": "4.0.0-beta.5", - "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-4.0.0-beta.5.tgz", - "integrity": "sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==", - "license": "MIT" - }, "node_modules/ethers/node_modules/tslib": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", "license": "0BSD" }, + "node_modules/ethers/node_modules/undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "license": "MIT" + }, "node_modules/ethers/node_modules/ws": { "version": "8.17.1", "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", @@ -5657,6 +5968,7 @@ "resolved": "https://registry.npmjs.org/ethjs-unit/-/ethjs-unit-0.1.6.tgz", "integrity": "sha512-/Sn9Y0oKl0uqQuvgFk/zQgR7aw1g36qX/jzSQ5lSwlO0GigPymk4eGQfeNTD03w1dPOqfz8V77Cy43jH56pagw==", "dev": true, + "license": "MIT", "dependencies": { "bn.js": "4.11.6", "number-to-bn": "1.7.0" @@ -5670,26 +5982,15 @@ "version": "4.11.6", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", "integrity": "sha512-XWwnNNFCuuSQ0m3r3C4LE3EiORltHd9M05pq6FOlVeiophzRbMo50Sbz1ehl8K3Z+jw9+vmgnXefY1hz8X+2wA==", - "dev": true - }, - "node_modules/ethjs-util": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/ethjs-util/-/ethjs-util-0.1.6.tgz", - "integrity": "sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==", - "dependencies": { - "is-hex-prefixed": "1.0.0", - "strip-hex-prefix": "1.0.0" - }, - "engines": { - "node": ">=6.5.0", - "npm": ">=3" - } + "dev": true, + "license": "MIT" }, "node_modules/event-target-shim": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -5700,10 +6001,22 @@ "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", "license": "MIT" }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.x" + } + }, "node_modules/evp_bytestokey": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "dev": true, + "license": "MIT", "dependencies": { "md5.js": "^1.3.4", "safe-buffer": "^5.1.1" @@ -5733,35 +6046,24 @@ "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "node_modules/execa/node_modules/get-stream": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", - "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/fast-diff": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", - "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", - "dev": true + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "dev": true, + "license": "Apache-2.0" }, "node_modules/fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", "dev": true, "license": "MIT", "dependencies": { @@ -5769,36 +6071,62 @@ "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", - "micromatch": "^4.0.4" + "micromatch": "^4.0.8" }, "engines": { "node": ">=8.6.0" } }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/fast-uri": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.3.tgz", - "integrity": "sha512-aLrHthzCjH5He4Z2H9YZ+v6Ujb9ocRuW6ZzkJQOrTxleEijANq4v1TsaPaVG1PZcuurEzrLcWRyYBYXD5cEiaw==", + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.6.tgz", + "integrity": "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], "license": "BSD-3-Clause" }, "node_modules/fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", "dev": true, + "license": "ISC", "dependencies": { "reusify": "^1.0.4" } @@ -5817,6 +6145,7 @@ "url": "https://paypal.me/jimmywarting" } ], + "license": "MIT", "dependencies": { "node-domexception": "^1.0.0", "web-streams-polyfill": "^3.0.3" @@ -5830,6 +6159,7 @@ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", "dev": true, + "license": "MIT", "dependencies": { "flat-cache": "^3.0.4" }, @@ -5841,6 +6171,7 @@ "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" }, @@ -5853,6 +6184,7 @@ "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-3.0.0.tgz", "integrity": "sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ==", "dev": true, + "license": "MIT", "dependencies": { "array-back": "^3.0.1" }, @@ -5864,6 +6196,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "license": "MIT", "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" @@ -5879,17 +6212,20 @@ "version": "5.0.2", "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "license": "BSD-3-Clause", "bin": { "flat": "cli.js" } }, "node_modules/flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", "dev": true, + "license": "MIT", "dependencies": { - "flatted": "^3.1.0", + "flatted": "^3.2.9", + "keyv": "^4.5.3", "rimraf": "^3.0.2" }, "engines": { @@ -5897,29 +6233,32 @@ } }, "node_modules/flatted": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", - "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", - "dev": true + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "dev": true, + "license": "ISC" }, "node_modules/fmix": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/fmix/-/fmix-0.1.0.tgz", "integrity": "sha512-Y6hyofImk9JdzU8k5INtTXX1cu8LDlePWDFU5sftm9H+zKCr5SGrVjdhkvsim646cw5zD0nADj8oHyXMZmCZ9w==", + "license": "MIT", "dependencies": { "imul": "^1.0.0" } }, "node_modules/follow-redirects": { - "version": "1.15.6", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", - "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", "funding": [ { "type": "individual", "url": "https://github.com/sponsors/RubenVerborgh" } ], + "license": "MIT", "engines": { "node": ">=4.0" }, @@ -5930,22 +6269,29 @@ } }, "node_modules/for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", "dev": true, + "license": "MIT", "dependencies": { - "is-callable": "^1.1.3" + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/foreground-child": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", - "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", "dev": true, "license": "ISC", "dependencies": { - "cross-spawn": "^7.0.0", + "cross-spawn": "^7.0.6", "signal-exit": "^4.0.1" }, "engines": { @@ -5956,12 +6302,14 @@ } }, "node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz", + "integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==", + "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", "mime-types": "^2.1.12" }, "engines": { @@ -5969,15 +6317,20 @@ } }, "node_modules/form-data-encoder": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-1.7.1.tgz", - "integrity": "sha512-EFRDrsMm/kyqbTQocNvRXMLjc7Es2Vk+IQFx/YW7hkUH1eBl4J1fqiP34l74Yt0pFLCNpc06fkbVk00008mzjg==", - "dev": true + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-2.1.4.tgz", + "integrity": "sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.17" + } }, "node_modules/formdata-polyfill": { "version": "4.0.10", "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "license": "MIT", "dependencies": { "fetch-blob": "^3.1.2" }, @@ -5988,12 +6341,13 @@ "node_modules/fp-ts": { "version": "1.19.3", "resolved": "https://registry.npmjs.org/fp-ts/-/fp-ts-1.19.3.tgz", - "integrity": "sha512-H5KQDspykdHuztLTg+ajGN0Z2qUjcEf3Ybxc6hLt0k7/zPkn29XnKnxlBPyW2XIddWrGaJBzBl4VLYOtk39yZg==" + "integrity": "sha512-H5KQDspykdHuztLTg+ajGN0Z2qUjcEf3Ybxc6hLt0k7/zPkn29XnKnxlBPyW2XIddWrGaJBzBl4VLYOtk39yZg==", + "license": "MIT" }, "node_modules/fs-extra": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", - "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "version": "11.3.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.0.tgz", + "integrity": "sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==", "dev": true, "license": "MIT", "dependencies": { @@ -6005,39 +6359,18 @@ "node": ">=14.14" } }, - "node_modules/fs-extra/node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, "license": "MIT", - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/fs-extra/node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" - }, - "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "hasInstallScript": true, "optional": true, "os": [ "darwin" @@ -6056,16 +6389,18 @@ } }, "node_modules/function.prototype.name": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", - "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz", + "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "functions-have-names": "^1.2.3" + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "functions-have-names": "^1.2.3", + "hasown": "^2.0.2", + "is-callable": "^1.2.7" }, "engines": { "node": ">= 0.4" @@ -6088,6 +6423,7 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "license": "ISC", "engines": { "node": "6.* || 8.* || >= 10.*" } @@ -6116,16 +6452,21 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", "license": "MIT", "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -6134,28 +6475,42 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", "dev": true, + "license": "MIT", "engines": { - "node": ">=10" + "node": ">=16" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/get-symbol-description": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", - "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", + "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.5", + "call-bound": "^1.0.3", "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4" + "get-intrinsic": "^1.2.6" }, "engines": { "node": ">= 0.4" @@ -6165,9 +6520,9 @@ } }, "node_modules/get-tsconfig": { - "version": "4.8.1", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.8.1.tgz", - "integrity": "sha512-k9PN+cFBmaLWtVz29SkUoqU5O0slLuHJXt/2P+tMVFT+phsSGXGkp9t3rQIqdz0e+06EHNGs3oM6ZX1s2zHxRg==", + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.10.0.tgz", + "integrity": "sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A==", "dev": true, "license": "MIT", "dependencies": { @@ -6182,6 +6537,7 @@ "resolved": "https://registry.npmjs.org/ghost-testrpc/-/ghost-testrpc-0.0.2.tgz", "integrity": "sha512-i08dAEgJ2g8z5buJIrCTduwPIhih3DP+hOCTyyryikfV8T0bNvHnGXO67i0DD1H4GBDETTclPy9njZbfluQYrQ==", "dev": true, + "license": "ISC", "dependencies": { "chalk": "^2.4.2", "node-emoji": "^1.10.0" @@ -6195,6 +6551,7 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, + "license": "MIT", "dependencies": { "color-convert": "^1.9.0" }, @@ -6207,6 +6564,7 @@ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -6221,6 +6579,7 @@ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "1.1.3" } @@ -6229,13 +6588,15 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/ghost-testrpc/node_modules/escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.8.0" } @@ -6245,6 +6606,7 @@ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -6254,6 +6616,7 @@ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^3.0.0" }, @@ -6262,31 +6625,37 @@ } }, "node_modules/glob": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", - "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", "dev": true, + "license": "ISC", "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" }, - "engines": { - "node": "*" + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", "dependencies": { - "is-glob": "^4.0.1" + "is-glob": "^4.0.3" }, "engines": { - "node": ">= 6" + "node": ">=10.13.0" } }, "node_modules/global-modules": { @@ -6294,6 +6663,7 @@ "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", "dev": true, + "license": "MIT", "dependencies": { "global-prefix": "^3.0.0" }, @@ -6306,6 +6676,7 @@ "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", "dev": true, + "license": "MIT", "dependencies": { "ini": "^1.3.5", "kind-of": "^6.0.2", @@ -6320,6 +6691,7 @@ "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "dev": true, + "license": "ISC", "dependencies": { "isexe": "^2.0.0" }, @@ -6360,6 +6732,72 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/globby": { + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/globby/-/globby-10.0.2.tgz", + "integrity": "sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/glob": "^7.1.1", + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.0.3", + "glob": "^7.1.3", + "ignore": "^5.1.1", + "merge2": "^1.2.3", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/globby/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/globby/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/globby/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/gopd": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", @@ -6373,24 +6811,23 @@ } }, "node_modules/got": { - "version": "12.1.0", - "resolved": "https://registry.npmjs.org/got/-/got-12.1.0.tgz", - "integrity": "sha512-hBv2ty9QN2RdbJJMK3hesmSkFTjVIHyIDDbssCKnSmq62edGgImJWD10Eb1k77TiV1bxloxqcFAVK8+9pkhOig==", + "version": "12.6.1", + "resolved": "https://registry.npmjs.org/got/-/got-12.6.1.tgz", + "integrity": "sha512-mThBblvlAF1d4O5oqyvN+ZxLAYwIJK7bpMxgYqPD9okW0C3qm5FFn7k811QrcuEBwaogR3ngOFoCfs6mRv7teQ==", "dev": true, + "license": "MIT", "dependencies": { - "@sindresorhus/is": "^4.6.0", + "@sindresorhus/is": "^5.2.0", "@szmarczak/http-timer": "^5.0.1", - "@types/cacheable-request": "^6.0.2", - "@types/responselike": "^1.0.0", - "cacheable-lookup": "^6.0.4", - "cacheable-request": "^7.0.2", + "cacheable-lookup": "^7.0.0", + "cacheable-request": "^10.2.8", "decompress-response": "^6.0.0", - "form-data-encoder": "1.7.1", + "form-data-encoder": "^2.1.2", "get-stream": "^6.0.1", "http2-wrapper": "^2.1.10", "lowercase-keys": "^3.0.0", "p-cancelable": "^3.0.0", - "responselike": "^2.0.0" + "responselike": "^3.0.0" }, "engines": { "node": ">=14.16" @@ -6399,10 +6836,23 @@ "url": "https://github.com/sindresorhus/got?sponsor=1" } }, + "node_modules/got/node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "license": "ISC" }, "node_modules/graphemer": { @@ -6417,6 +6867,7 @@ "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", "dev": true, + "license": "MIT", "dependencies": { "minimist": "^1.2.5", "neo-async": "^2.6.2", @@ -6438,22 +6889,20 @@ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } }, "node_modules/hardhat": { - "version": "2.22.17", - "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-2.22.17.tgz", - "integrity": "sha512-tDlI475ccz4d/dajnADUTRc1OJ3H8fpP9sWhXhBPpYsQOg8JHq5xrDimo53UhWPl7KJmAeDCm1bFG74xvpGRpg==", + "version": "2.23.0", + "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-2.23.0.tgz", + "integrity": "sha512-xnORx1LgX46TxylOFme96JmSAIjXuHUVpOlUnaCt8MKMGsgy0NGsfPo5rJI/ncCBPLFLURGfZUQ2Uc6ZYN4kYg==", "license": "MIT", "dependencies": { + "@ethereumjs/util": "^9.1.0", "@ethersproject/abi": "^5.1.2", - "@metamask/eth-sig-util": "^4.0.0", - "@nomicfoundation/edr": "^0.6.5", - "@nomicfoundation/ethereumjs-common": "4.0.4", - "@nomicfoundation/ethereumjs-tx": "5.0.4", - "@nomicfoundation/ethereumjs-util": "9.0.4", + "@nomicfoundation/edr": "^0.10.0", "@nomicfoundation/solidity-analyzer": "^0.1.0", "@sentry/node": "^5.18.1", "@types/bn.js": "^5.1.0", @@ -6468,7 +6917,6 @@ "enquirer": "^2.3.0", "env-paths": "^2.2.0", "ethereum-cryptography": "^1.0.3", - "ethereumjs-abi": "^0.6.8", "find-up": "^5.0.0", "fp-ts": "1.19.3", "fs-extra": "^7.0.1", @@ -6477,6 +6925,7 @@ "json-stream-stringify": "^3.1.4", "keccak": "^3.0.2", "lodash": "^4.17.11", + "micro-eth-signer": "^0.14.0", "mnemonist": "^0.38.0", "mocha": "^10.0.0", "p-map": "^4.0.0", @@ -6510,12 +6959,13 @@ } }, "node_modules/hardhat-abi-exporter": { - "version": "2.10.1", - "resolved": "https://registry.npmjs.org/hardhat-abi-exporter/-/hardhat-abi-exporter-2.10.1.tgz", - "integrity": "sha512-X8GRxUTtebMAd2k4fcPyVnCdPa6dYK4lBsrwzKP5yiSq4i+WadWPIumaLfce53TUf/o2TnLpLOduyO1ylE2NHQ==", + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/hardhat-abi-exporter/-/hardhat-abi-exporter-2.11.0.tgz", + "integrity": "sha512-hBC4Xzncew9pdqVpzWoEEBJUthp99TCH39cHlMehVxBBQ6EIsIFyj3N0yd0hkVDfM8/s/FMRAuO5jntZBpwCZQ==", "dev": true, + "license": "MIT", "dependencies": { - "@ethersproject/abi": "^5.5.0", + "@ethersproject/abi": "^5.7.0", "delete-empty": "^3.0.0" }, "engines": { @@ -6530,6 +6980,7 @@ "resolved": "https://registry.npmjs.org/hardhat-contract-sizer/-/hardhat-contract-sizer-2.10.0.tgz", "integrity": "sha512-QiinUgBD5MqJZJh1hl1jc9dNnpJg7eE/w4/4GEnrcmZJJTDbVFNe3+/3Ep24XqISSkYxRz36czcPHKHd/a0dwA==", "dev": true, + "license": "MIT", "dependencies": { "chalk": "^4.0.0", "cli-table3": "^0.6.0", @@ -6582,10 +7033,34 @@ "hardhat-deploy": "^0.12.0" } }, + "node_modules/hardhat-deploy/node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, "node_modules/hardhat-deploy/node_modules/ethers": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.7.2.tgz", - "integrity": "sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg==", + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.8.0.tgz", + "integrity": "sha512-DUq+7fHrCg1aPDFCHx6UIPb3nmt2XMpM7Y/g2gLhsl3lIBqeAfOJIl1qEvRf2uq3BiKxmh6Fh5pfp2ieyek7Kg==", "funding": [ { "type": "individual", @@ -6598,42 +7073,43 @@ ], "license": "MIT", "dependencies": { - "@ethersproject/abi": "5.7.0", - "@ethersproject/abstract-provider": "5.7.0", - "@ethersproject/abstract-signer": "5.7.0", - "@ethersproject/address": "5.7.0", - "@ethersproject/base64": "5.7.0", - "@ethersproject/basex": "5.7.0", - "@ethersproject/bignumber": "5.7.0", - "@ethersproject/bytes": "5.7.0", - "@ethersproject/constants": "5.7.0", - "@ethersproject/contracts": "5.7.0", - "@ethersproject/hash": "5.7.0", - "@ethersproject/hdnode": "5.7.0", - "@ethersproject/json-wallets": "5.7.0", - "@ethersproject/keccak256": "5.7.0", - "@ethersproject/logger": "5.7.0", - "@ethersproject/networks": "5.7.1", - "@ethersproject/pbkdf2": "5.7.0", - "@ethersproject/properties": "5.7.0", - "@ethersproject/providers": "5.7.2", - "@ethersproject/random": "5.7.0", - "@ethersproject/rlp": "5.7.0", - "@ethersproject/sha2": "5.7.0", - "@ethersproject/signing-key": "5.7.0", - "@ethersproject/solidity": "5.7.0", - "@ethersproject/strings": "5.7.0", - "@ethersproject/transactions": "5.7.0", - "@ethersproject/units": "5.7.0", - "@ethersproject/wallet": "5.7.0", - "@ethersproject/web": "5.7.1", - "@ethersproject/wordlists": "5.7.0" + "@ethersproject/abi": "5.8.0", + "@ethersproject/abstract-provider": "5.8.0", + "@ethersproject/abstract-signer": "5.8.0", + "@ethersproject/address": "5.8.0", + "@ethersproject/base64": "5.8.0", + "@ethersproject/basex": "5.8.0", + "@ethersproject/bignumber": "5.8.0", + "@ethersproject/bytes": "5.8.0", + "@ethersproject/constants": "5.8.0", + "@ethersproject/contracts": "5.8.0", + "@ethersproject/hash": "5.8.0", + "@ethersproject/hdnode": "5.8.0", + "@ethersproject/json-wallets": "5.8.0", + "@ethersproject/keccak256": "5.8.0", + "@ethersproject/logger": "5.8.0", + "@ethersproject/networks": "5.8.0", + "@ethersproject/pbkdf2": "5.8.0", + "@ethersproject/properties": "5.8.0", + "@ethersproject/providers": "5.8.0", + "@ethersproject/random": "5.8.0", + "@ethersproject/rlp": "5.8.0", + "@ethersproject/sha2": "5.8.0", + "@ethersproject/signing-key": "5.8.0", + "@ethersproject/solidity": "5.8.0", + "@ethersproject/strings": "5.8.0", + "@ethersproject/transactions": "5.8.0", + "@ethersproject/units": "5.8.0", + "@ethersproject/wallet": "5.8.0", + "@ethersproject/web": "5.8.0", + "@ethersproject/wordlists": "5.8.0" } }, "node_modules/hardhat-deploy/node_modules/fs-extra": { "version": "10.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "license": "MIT", "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", @@ -6643,29 +7119,34 @@ "node": ">=12" } }, - "node_modules/hardhat-deploy/node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "node_modules/hardhat-deploy/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "license": "ISC", "dependencies": { - "universalify": "^2.0.0" + "is-glob": "^4.0.1" }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" + "engines": { + "node": ">= 6" } }, - "node_modules/hardhat-deploy/node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "node_modules/hardhat-deploy/node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, "engines": { - "node": ">= 10.0.0" + "node": ">=8.10.0" } }, "node_modules/hardhat-gas-reporter": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/hardhat-gas-reporter/-/hardhat-gas-reporter-2.2.2.tgz", - "integrity": "sha512-xlg3d00wrgUvP2S5tw3Zf6nO7OyS5crK3P6/ZP69i24pz4grM+6oFHGW/eJPSGqiDWBYX+gKp9XoqP4rwRXrdQ==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/hardhat-gas-reporter/-/hardhat-gas-reporter-2.2.3.tgz", + "integrity": "sha512-/52fDR0WOgPTjImmx4j179SAgxPv/499TD0o0qnMhaRr24i2cqlcmCW92FJi0QAKu7HcnxdBGZWQP/5aPjQqUw==", "dev": true, "license": "MIT", "dependencies": { @@ -6683,7 +7164,7 @@ "lodash": "^4.17.21", "markdown-table": "2.0.0", "sha1": "^1.1.1", - "viem": "2.7.14" + "viem": "^2.27.0" }, "peerDependencies": { "hardhat": "^2.16.0" @@ -6715,7 +7196,17 @@ "url": "https://paulmillr.com/funding/" } }, - "node_modules/hardhat-gas-reporter/node_modules/@scure/bip32": { + "node_modules/hardhat-gas-reporter/node_modules/@scure/base": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.9.tgz", + "integrity": "sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/hardhat-gas-reporter/node_modules/@scure/bip32": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.4.0.tgz", "integrity": "sha512-sVUpc0Vq3tXCkDGYVWGIZTRfnvu8LoTDaev7vbwh0omSvVORONr960MQWdKqJDCReIEmTj3PAr73O3aoxz7OPg==", @@ -6744,39 +7235,10 @@ "url": "https://paulmillr.com/funding/" } }, - "node_modules/hardhat-gas-reporter/node_modules/@solidity-parser/parser": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.19.0.tgz", - "integrity": "sha512-RV16k/qIxW/wWc+mLzV3ARyKUaMUTBy9tOLMzFhtNSKYeTAanQ3a5MudJKf/8arIFnA2L27SNjarQKmFg0w/jA==", - "dev": true, - "license": "MIT" - }, - "node_modules/hardhat-gas-reporter/node_modules/abitype": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/abitype/-/abitype-1.0.0.tgz", - "integrity": "sha512-NMeMah//6bJ56H5XRj8QCV4AwuW6hB6zqz2LnhhLdcWVQOsXki6/Pn3APeqxCma62nXIcmZWdu1DlHWS74umVQ==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/wevm" - }, - "peerDependencies": { - "typescript": ">=5.0.4", - "zod": "^3 >=3.22.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - }, - "zod": { - "optional": true - } - } - }, "node_modules/hardhat-gas-reporter/node_modules/axios": { - "version": "1.7.9", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.9.tgz", - "integrity": "sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==", + "version": "1.8.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.8.4.tgz", + "integrity": "sha512-eBSYY4Y68NNlHbHBMdeDmKNtDgXWhQsJcGqzO3iLUM0GraQFSS9cVgPX5I9b3lbdFKyYoAEGAZF1DwhTaljNAw==", "dev": true, "license": "MIT", "dependencies": { @@ -6785,16 +7247,6 @@ "proxy-from-env": "^1.1.0" } }, - "node_modules/hardhat-gas-reporter/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, "node_modules/hardhat-gas-reporter/node_modules/ethereum-cryptography": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.2.1.tgz", @@ -6808,151 +7260,202 @@ "@scure/bip39": "1.3.0" } }, - "node_modules/hardhat-gas-reporter/node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "node_modules/hardhat-tracer": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/hardhat-tracer/-/hardhat-tracer-3.1.0.tgz", + "integrity": "sha512-Ip16HQAuzbqbNJUIEVfqmbPmOY90bxZSpwu5Q73cwloy+LUYA04BATUM9Gui5H7zcgsgZ1IVy7pSYn6ZMjLmag==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" + "chalk": "^4.1.2", + "debug": "^4.3.4", + "ethers": "^5.6.1", + "semver": "^7.6.2" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "peerDependencies": { + "chai": "4.x", + "hardhat": ">=2.22.5 <3.x" } }, - "node_modules/hardhat-gas-reporter/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "node_modules/hardhat-tracer/node_modules/ethers": { + "version": "5.8.0", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.8.0.tgz", + "integrity": "sha512-DUq+7fHrCg1aPDFCHx6UIPb3nmt2XMpM7Y/g2gLhsl3lIBqeAfOJIl1qEvRf2uq3BiKxmh6Fh5pfp2ieyek7Kg==", "dev": true, - "license": "ISC", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, + "@ethersproject/abi": "5.8.0", + "@ethersproject/abstract-provider": "5.8.0", + "@ethersproject/abstract-signer": "5.8.0", + "@ethersproject/address": "5.8.0", + "@ethersproject/base64": "5.8.0", + "@ethersproject/basex": "5.8.0", + "@ethersproject/bignumber": "5.8.0", + "@ethersproject/bytes": "5.8.0", + "@ethersproject/constants": "5.8.0", + "@ethersproject/contracts": "5.8.0", + "@ethersproject/hash": "5.8.0", + "@ethersproject/hdnode": "5.8.0", + "@ethersproject/json-wallets": "5.8.0", + "@ethersproject/keccak256": "5.8.0", + "@ethersproject/logger": "5.8.0", + "@ethersproject/networks": "5.8.0", + "@ethersproject/pbkdf2": "5.8.0", + "@ethersproject/properties": "5.8.0", + "@ethersproject/providers": "5.8.0", + "@ethersproject/random": "5.8.0", + "@ethersproject/rlp": "5.8.0", + "@ethersproject/sha2": "5.8.0", + "@ethersproject/signing-key": "5.8.0", + "@ethersproject/solidity": "5.8.0", + "@ethersproject/strings": "5.8.0", + "@ethersproject/transactions": "5.8.0", + "@ethersproject/units": "5.8.0", + "@ethersproject/wallet": "5.8.0", + "@ethersproject/web": "5.8.0", + "@ethersproject/wordlists": "5.8.0" + } + }, + "node_modules/hardhat/node_modules/@noble/hashes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.2.0.tgz", + "integrity": "sha512-FZfhjEDbT5GRswV3C6uvLPHMiVD6lQBmpoX5+eSiPaMTXte/IKqI5dykDxzZB/WBeK/CDuQRBWarPdi3FNY2zQ==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "license": "MIT" + }, + "node_modules/hardhat/node_modules/@scure/base": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.9.tgz", + "integrity": "sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg==", + "license": "MIT", "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://paulmillr.com/funding/" } }, - "node_modules/hardhat-gas-reporter/node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=16 || 14 >=14.17" + "node_modules/hardhat/node_modules/@scure/bip32": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.1.5.tgz", + "integrity": "sha512-XyNh1rB0SkEqd3tXcXMi+Xe1fvg+kUIcoRIEujP1Jgv7DqW2r9lg3Ah0NkFaCs9sTkQAQA8kw7xiRXzENi9Rtw==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "license": "MIT", + "dependencies": { + "@noble/hashes": "~1.2.0", + "@noble/secp256k1": "~1.7.0", + "@scure/base": "~1.1.0" } }, - "node_modules/hardhat-gas-reporter/node_modules/viem": { - "version": "2.7.14", - "resolved": "https://registry.npmjs.org/viem/-/viem-2.7.14.tgz", - "integrity": "sha512-5b1KB1gXli02GOQHZIUsRluNUwssl2t4hqdFAzyWPwJ744N83jAOBOjOkrGz7K3qMIv9b0GQt3DoZIErSQTPkQ==", - "dev": true, + "node_modules/hardhat/node_modules/@scure/bip39": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.1.1.tgz", + "integrity": "sha512-t+wDck2rVkh65Hmv280fYdVdY25J9YeEUIgn2LG1WM6gxFkGzcksoDiUkWVpVp3Oex9xGC68JU2dSbUfwZ2jPg==", "funding": [ { - "type": "github", - "url": "https://github.com/sponsors/wevm" + "type": "individual", + "url": "https://paulmillr.com/funding/" } ], "license": "MIT", "dependencies": { - "@adraffy/ens-normalize": "1.10.0", - "@noble/curves": "1.2.0", - "@noble/hashes": "1.3.2", - "@scure/bip32": "1.3.2", - "@scure/bip39": "1.2.1", - "abitype": "1.0.0", - "isows": "1.0.3", - "ws": "8.13.0" - }, - "peerDependencies": { - "typescript": ">=5.0.4" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "@noble/hashes": "~1.2.0", + "@scure/base": "~1.1.0" } }, - "node_modules/hardhat-gas-reporter/node_modules/viem/node_modules/@noble/curves": { + "node_modules/hardhat/node_modules/ethereum-cryptography": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz", - "integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==", - "dev": true, + "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-1.2.0.tgz", + "integrity": "sha512-6yFQC9b5ug6/17CQpCyE3k9eKBMdhyVjzUy1WkiuY/E4vj/SXDBbCw8QEIaXqf0Mf2SnY6RmpDcwlUmBSS0EJw==", "license": "MIT", "dependencies": { - "@noble/hashes": "1.3.2" - }, - "funding": { - "url": "https://paulmillr.com/funding/" + "@noble/hashes": "1.2.0", + "@noble/secp256k1": "1.7.1", + "@scure/bip32": "1.1.5", + "@scure/bip39": "1.1.1" } }, - "node_modules/hardhat-gas-reporter/node_modules/viem/node_modules/@noble/hashes": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", - "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==", - "dev": true, + "node_modules/hardhat/node_modules/fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", "license": "MIT", - "engines": { - "node": ">= 16" + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" }, - "funding": { - "url": "https://paulmillr.com/funding/" + "engines": { + "node": ">=6 <7 || >=8" } }, - "node_modules/hardhat-gas-reporter/node_modules/viem/node_modules/@scure/bip32": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.3.2.tgz", - "integrity": "sha512-N1ZhksgwD3OBlwTv3R6KFEcPojl/W4ElJOeCZdi+vuI5QmTFwLq3OFf2zd2ROpKvxFdgZ6hUpb0dx9bVNEwYCA==", - "dev": true, + "node_modules/hardhat/node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", "license": "MIT", - "dependencies": { - "@noble/curves": "~1.2.0", - "@noble/hashes": "~1.3.2", - "@scure/base": "~1.1.2" - }, - "funding": { - "url": "https://paulmillr.com/funding/" + "optionalDependencies": { + "graceful-fs": "^4.1.6" } }, - "node_modules/hardhat-gas-reporter/node_modules/viem/node_modules/@scure/bip39": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.2.1.tgz", - "integrity": "sha512-Z3/Fsz1yr904dduJD0NpiyRHhRYHdcnyh73FZWiV+/qhWi83wNJ3NWolYqCEN+ZWsUz2TWwajJggcRE9r1zUYg==", - "dev": true, + "node_modules/hardhat/node_modules/resolve": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", + "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", "license": "MIT", "dependencies": { - "@noble/hashes": "~1.3.0", - "@scure/base": "~1.1.0" + "path-parse": "^1.0.6" }, "funding": { - "url": "https://paulmillr.com/funding/" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/hardhat-gas-reporter/node_modules/ws": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", - "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", - "dev": true, + "node_modules/hardhat/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/hardhat/node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", "license": "MIT", "engines": { - "node": ">=10.0.0" + "node": ">= 4.0.0" + } + }, + "node_modules/hardhat/node_modules/ws": { + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", + "license": "MIT", + "engines": { + "node": ">=8.3.0" }, "peerDependencies": { "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" + "utf-8-validate": "^5.0.2" }, "peerDependenciesMeta": { "bufferutil": { @@ -6963,230 +7466,33 @@ } } }, - "node_modules/hardhat-tracer": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/hardhat-tracer/-/hardhat-tracer-3.1.0.tgz", - "integrity": "sha512-Ip16HQAuzbqbNJUIEVfqmbPmOY90bxZSpwu5Q73cwloy+LUYA04BATUM9Gui5H7zcgsgZ1IVy7pSYn6ZMjLmag==", + "node_modules/has-bigints": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", + "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", "dev": true, "license": "MIT", - "dependencies": { - "chalk": "^4.1.2", - "debug": "^4.3.4", - "ethers": "^5.6.1", - "semver": "^7.6.2" + "engines": { + "node": ">= 0.4" }, - "peerDependencies": { - "chai": "4.x", - "hardhat": ">=2.22.5 <3.x" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/hardhat-tracer/node_modules/ethers": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.7.2.tgz", - "integrity": "sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg==", + "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==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "dependencies": { - "@ethersproject/abi": "5.7.0", - "@ethersproject/abstract-provider": "5.7.0", - "@ethersproject/abstract-signer": "5.7.0", - "@ethersproject/address": "5.7.0", - "@ethersproject/base64": "5.7.0", - "@ethersproject/basex": "5.7.0", - "@ethersproject/bignumber": "5.7.0", - "@ethersproject/bytes": "5.7.0", - "@ethersproject/constants": "5.7.0", - "@ethersproject/contracts": "5.7.0", - "@ethersproject/hash": "5.7.0", - "@ethersproject/hdnode": "5.7.0", - "@ethersproject/json-wallets": "5.7.0", - "@ethersproject/keccak256": "5.7.0", - "@ethersproject/logger": "5.7.0", - "@ethersproject/networks": "5.7.1", - "@ethersproject/pbkdf2": "5.7.0", - "@ethersproject/properties": "5.7.0", - "@ethersproject/providers": "5.7.2", - "@ethersproject/random": "5.7.0", - "@ethersproject/rlp": "5.7.0", - "@ethersproject/sha2": "5.7.0", - "@ethersproject/signing-key": "5.7.0", - "@ethersproject/solidity": "5.7.0", - "@ethersproject/strings": "5.7.0", - "@ethersproject/transactions": "5.7.0", - "@ethersproject/units": "5.7.0", - "@ethersproject/wallet": "5.7.0", - "@ethersproject/web": "5.7.1", - "@ethersproject/wordlists": "5.7.0" - } - }, - "node_modules/hardhat-tracer/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/hardhat/node_modules/ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "dependencies": { - "type-fest": "^0.21.3" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/hardhat/node_modules/chokidar": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.1.tgz", - "integrity": "sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA==", - "license": "MIT", - "dependencies": { - "readdirp": "^4.0.1" - }, - "engines": { - "node": ">= 14.16.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/hardhat/node_modules/commander": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", - "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", - "license": "MIT", - "engines": { - "node": ">= 12" - } - }, - "node_modules/hardhat/node_modules/fs-extra": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", - "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", - "dependencies": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - }, - "engines": { - "node": ">=6 <7 || >=8" - } - }, - "node_modules/hardhat/node_modules/resolve": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", - "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", - "dependencies": { - "path-parse": "^1.0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/hardhat/node_modules/solc": { - "version": "0.8.26", - "resolved": "https://registry.npmjs.org/solc/-/solc-0.8.26.tgz", - "integrity": "sha512-yiPQNVf5rBFHwN6SIf3TUUvVAFKcQqmSUFeq+fb6pNRCo0ZCgpYOZDi3BVoezCPIAcKrVYd/qXlBLUP9wVrZ9g==", - "license": "MIT", - "dependencies": { - "command-exists": "^1.2.8", - "commander": "^8.1.0", - "follow-redirects": "^1.12.1", - "js-sha3": "0.8.0", - "memorystream": "^0.3.1", - "semver": "^5.5.0", - "tmp": "0.0.33" - }, - "bin": { - "solcjs": "solc.js" - }, - "engines": { - "node": ">=10.0.0" - } - }, - "node_modules/hardhat/node_modules/solc/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "license": "ISC", - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/hardhat/node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/hardhat/node_modules/ws": { - "version": "7.5.10", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", - "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", - "engines": { - "node": ">=8.3.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/has-bigints": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", - "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "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/has-property-descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "license": "MIT", "dependencies": { "es-define-property": "^1.0.0" @@ -7196,12 +7502,13 @@ } }, "node_modules/has-proto": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.1.0.tgz", - "integrity": "sha512-QLdzI9IIO1Jg7f9GT1gXpPpXArAn6cS31R1eEZqz08Gc+uQ8/XiqHWt17Fiw+2p6oTTIq5GXEpQkAlA88YRl/Q==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", + "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", + "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.7" + "dunder-proto": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -7211,9 +7518,10 @@ } }, "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -7225,7 +7533,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", - "dev": true, "license": "MIT", "dependencies": { "has-symbols": "^1.0.3" @@ -7241,6 +7548,8 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", + "dev": true, + "license": "MIT", "dependencies": { "inherits": "^2.0.4", "readable-stream": "^3.6.0", @@ -7250,15 +7559,11 @@ "node": ">=4" } }, - "node_modules/hash-base/node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, "node_modules/hash.js": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "license": "MIT", "dependencies": { "inherits": "^2.0.3", "minimalistic-assert": "^1.0.1" @@ -7280,6 +7585,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "license": "MIT", "bin": { "he": "bin/he" } @@ -7288,12 +7594,14 @@ "version": "0.2.7", "resolved": "https://registry.npmjs.org/heap/-/heap-0.2.7.tgz", "integrity": "sha512-2bsegYkkHO+h/9MGbn6KWcE45cHZgPANo5LXF7EvWdT0yT2EguSVO1nDgU5c8+ZOPwp2vMNa7YFsJhVcDR9Sdg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/hmac-drbg": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==", + "license": "MIT", "dependencies": { "hash.js": "^1.0.3", "minimalistic-assert": "^1.0.0", @@ -7304,12 +7612,14 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", - "dev": true + "dev": true, + "license": "BSD-2-Clause" }, "node_modules/http-errors": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "license": "MIT", "dependencies": { "depd": "2.0.0", "inherits": "2.0.4", @@ -7321,16 +7631,12 @@ "node": ">= 0.8" } }, - "node_modules/http-errors/node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - }, "node_modules/http2-wrapper": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-2.2.0.tgz", - "integrity": "sha512-kZB0wxMo0sh1PehyjJUWRFEd99KC5TLjZ2cULC4f9iqJBAmKQQXEICjxl5iPJRwP40dpeHFqqhm7tYCvODpqpQ==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-2.2.1.tgz", + "integrity": "sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ==", "dev": true, + "license": "MIT", "dependencies": { "quick-lru": "^5.1.1", "resolve-alpn": "^1.2.0" @@ -7343,6 +7649,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "license": "MIT", "dependencies": { "agent-base": "6", "debug": "4" @@ -7381,6 +7688,7 @@ "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3" }, @@ -7388,6 +7696,27 @@ "node": ">=0.10.0" } }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, "node_modules/ignore": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", @@ -7399,15 +7728,17 @@ } }, "node_modules/immutable": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.1.0.tgz", - "integrity": "sha512-oNkuqVTA8jqG1Q6c+UglTOD1xhC1BtjKI7XkCXRkZHrN5m18/XsnUp8Q89GkQO/z+0WjonSvl0FLhDYftp46nQ==" + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.7.tgz", + "integrity": "sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw==", + "license": "MIT" }, "node_modules/import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", "dev": true, + "license": "MIT", "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" @@ -7423,6 +7754,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/imul/-/imul-1.0.1.tgz", "integrity": "sha512-WFAgfwPLAjU66EKt6vRdTlKj4nAgIDQzh29JonLa4Bqtl6D8JrIMvWjCnx7xEjVNmP3U0fM5o8ZObk7d0f62bA==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -7432,6 +7764,7 @@ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.8.19" } @@ -7440,6 +7773,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "license": "MIT", "engines": { "node": ">=8" } @@ -7448,32 +7782,36 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "license": "ISC", "dependencies": { "once": "^1.3.0", "wrappy": "1" } }, "node_modules/inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==" + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" }, "node_modules/ini": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/internal-slot": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", - "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", + "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", "dev": true, "license": "MIT", "dependencies": { "es-errors": "^1.3.0", - "hasown": "^2.0.0", - "side-channel": "^1.0.4" + "hasown": "^2.0.2", + "side-channel": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -7484,6 +7822,7 @@ "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.10" } @@ -7492,19 +7831,21 @@ "version": "1.10.4", "resolved": "https://registry.npmjs.org/io-ts/-/io-ts-1.10.4.tgz", "integrity": "sha512-b23PteSnYXSONJ6JQXRAlvJhuw8KOtkqa87W4wDtvMrud/DTJd5X+NpOOI+O/zZwVq6v0VLAaJ+1EDViKEuN9g==", + "license": "MIT", "dependencies": { "fp-ts": "^1.0.0" } }, "node_modules/is-array-buffer": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", - "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", + "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.1" + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" }, "engines": { "node": ">= 0.4" @@ -7517,16 +7858,21 @@ "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/is-async-function": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", - "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", + "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", "dev": true, "license": "MIT", "dependencies": { - "has-tostringtag": "^1.0.0" + "async-function": "^1.0.0", + "call-bound": "^1.0.3", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -7555,6 +7901,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "license": "MIT", "dependencies": { "binary-extensions": "^2.0.0" }, @@ -7563,13 +7910,13 @@ } }, "node_modules/is-boolean-object": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.0.tgz", - "integrity": "sha512-kR5g0+dXf/+kXnqI+lu0URKYPKgICtHGGNCDSB10AaUFj3o/HkB3u7WfpRBJGFopxxY0oH3ux7ZsDjLtK7xqvw==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", + "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bound": "^1.0.3", "has-tostringtag": "^1.0.2" }, "engines": { @@ -7580,26 +7927,13 @@ } }, "node_modules/is-bun-module": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/is-bun-module/-/is-bun-module-1.3.0.tgz", - "integrity": "sha512-DgXeu5UWI0IsMQundYb5UAOzm6G2eVnarJ0byP6Tm55iZNKceD59LNPA2L4VvsScTtHcw0yEkVwSf7PC+QoLSA==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-bun-module/-/is-bun-module-2.0.0.tgz", + "integrity": "sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ==", "dev": true, "license": "MIT", "dependencies": { - "semver": "^7.6.3" - } - }, - "node_modules/is-bun-module/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" + "semver": "^7.7.1" } }, "node_modules/is-callable": { @@ -7607,6 +7941,7 @@ "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -7615,9 +7950,9 @@ } }, "node_modules/is-core-module": { - "version": "2.15.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", - "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", "dev": true, "license": "MIT", "dependencies": { @@ -7631,12 +7966,14 @@ } }, "node_modules/is-data-view": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", - "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", + "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", "dev": true, "license": "MIT", "dependencies": { + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", "is-typed-array": "^1.1.13" }, "engines": { @@ -7647,13 +7984,14 @@ } }, "node_modules/is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", + "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", "dev": true, "license": "MIT", "dependencies": { - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -7666,18 +8004,19 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/is-finalizationregistry": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.0.tgz", - "integrity": "sha512-qfMdqbAQEwBw78ZyReKnlA8ezmPdb9BemzIIip/JkjaZUhitfXDkkr+3QTboW0JrSXT1QWyYShpvnNHGZ4c4yA==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", + "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.7" + "call-bound": "^1.0.3" }, "engines": { "node": ">= 0.4" @@ -7687,20 +8026,29 @@ } }, "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==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", + "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/is-generator-function": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", - "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.0.tgz", + "integrity": "sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==", "dev": true, + "license": "MIT", "dependencies": { - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.3", + "get-proto": "^1.0.0", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -7713,6 +8061,7 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "license": "MIT", "dependencies": { "is-extglob": "^2.1.1" }, @@ -7724,6 +8073,8 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz", "integrity": "sha512-WvtOiug1VFrE9v1Cydwm+FnXd3+w9GaeVUss5W4v/SLy3UW00vP+6iNF2SdnfiBoLy4bTqVdkftNGTUeOFVsbA==", + "dev": true, + "license": "MIT", "engines": { "node": ">=6.5.0", "npm": ">=3" @@ -7742,35 +8093,23 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-negative-zero": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", - "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "license": "MIT", "engines": { "node": ">=0.12.0" } }, "node_modules/is-number-object": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.0.tgz", - "integrity": "sha512-KVSZV0Dunv9DTPkhXwcZ3Q+tUc9TsaE1ZwX5J2WMvsSGS6Md8TFPun5uwh0yRdrNerI6vf/tbJxqSx4c1ZI1Lw==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", + "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bound": "^1.0.3", "has-tostringtag": "^1.0.2" }, "engines": { @@ -7785,19 +8124,29 @@ "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/is-regex": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.0.tgz", - "integrity": "sha512-B6ohK4ZmoftlUe+uvenXSbPJFo6U37BH7oO1B3nQH8f/7h27N56s85MhUtbFJAziz5dcmuR3i8ovUl35zp8pFA==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", - "gopd": "^1.1.0", + "call-bound": "^1.0.2", + "gopd": "^1.2.0", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" }, @@ -7822,13 +8171,13 @@ } }, "node_modules/is-shared-array-buffer": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", - "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", + "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.7" + "call-bound": "^1.0.3" }, "engines": { "node": ">= 0.4" @@ -7851,13 +8200,13 @@ } }, "node_modules/is-string": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.0.tgz", - "integrity": "sha512-PlfzajuF9vSo5wErv3MJAKD/nqf9ngAs1NFQYm16nUYFO2IzxJ2hcm+IOCg+EEopdykNNUhVq5cz35cAUxU8+g==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", + "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bound": "^1.0.3", "has-tostringtag": "^1.0.2" }, "engines": { @@ -7868,15 +8217,15 @@ } }, "node_modules/is-symbol": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.0.tgz", - "integrity": "sha512-qS8KkNNXUZ/I+nX6QT8ZS1/Yx0A444yhzdTKxCzKkNjQ9sHErBxJnJAgh+f5YhusYECEcjo4XcyH87hn6+ks0A==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", + "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", - "has-symbols": "^1.0.3", - "safe-regex-test": "^1.0.3" + "call-bound": "^1.0.2", + "has-symbols": "^1.1.0", + "safe-regex-test": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -7886,13 +8235,13 @@ } }, "node_modules/is-typed-array": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", - "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", "dev": true, "license": "MIT", "dependencies": { - "which-typed-array": "^1.1.14" + "which-typed-array": "^1.1.16" }, "engines": { "node": ">= 0.4" @@ -7905,6 +8254,7 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "license": "MIT", "engines": { "node": ">=10" }, @@ -7926,27 +8276,30 @@ } }, "node_modules/is-weakref": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", - "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz", + "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.2" + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/is-weakset": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.3.tgz", - "integrity": "sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", + "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", - "get-intrinsic": "^1.2.4" + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" }, "engines": { "node": ">= 0.4" @@ -7966,17 +8319,18 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/isows": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/isows/-/isows-1.0.3.tgz", - "integrity": "sha512-2cKei4vlmg2cxEjm3wVSqn8pcoRF/LX/wpifuuNquFO4SQmPwarClT+SUCA2lt+l581tTeZIPIZuIDo2jWN1fg==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/isows/-/isows-1.0.6.tgz", + "integrity": "sha512-lPHCayd40oW98/I0uvgaHKWCSvkzY27LjWLbtzOm64yQ+G3Q5npjjbdppU65iZXkK1Zt+kH9pfegli0AYfwYYw==", "dev": true, "funding": [ { "type": "github", - "url": "https://github.com/sponsors/wagmi-dev" + "url": "https://github.com/sponsors/wevm" } ], "license": "MIT", @@ -8003,7 +8357,8 @@ "node_modules/js-sha3": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", - "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==" + "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==", + "license": "MIT" }, "node_modules/js-tokens": { "version": "4.0.0", @@ -8016,6 +8371,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "license": "MIT", "dependencies": { "argparse": "^2.0.1" }, @@ -8027,7 +8383,8 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", @@ -8040,13 +8397,15 @@ "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/json-stream-stringify": { "version": "3.1.6", @@ -8077,42 +8436,62 @@ } }, "node_modules/jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "node_modules/jsonld": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/jsonld/-/jsonld-8.1.0.tgz", - "integrity": "sha512-6tYhiEVYO3rTcoYCGCArw8SqawuW0hf/cqmaE5WbX44CGb7d8N2UFvmUj9OYkJhChD98bfdPljUj7S39MrzsHg==", + "version": "8.3.3", + "resolved": "https://registry.npmjs.org/jsonld/-/jsonld-8.3.3.tgz", + "integrity": "sha512-9YcilrF+dLfg9NTEof/mJLMtbdX1RJ8dbWtJgE00cMOIohb1lIyJl710vFiTaiHTl6ZYODJuBd32xFvUhmv3kg==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { - "@digitalbazaar/http-client": "^3.2.0", + "@digitalbazaar/http-client": "^3.4.1", "canonicalize": "^1.0.1", "lru-cache": "^6.0.0", - "rdf-canonize": "^3.0.0" + "rdf-canonize": "^3.4.0" }, "engines": { "node": ">=14" } }, + "node_modules/jsonld/node_modules/rdf-canonize": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/rdf-canonize/-/rdf-canonize-3.4.0.tgz", + "integrity": "sha512-fUeWjrkOO0t1rg7B2fdyDTvngj+9RlUyL92vOdiB7c0FPguWVsniIMjEtHH+meLBO9rzkUlUzBVXgWrjI8P9LA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "setimmediate": "^1.0.5" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/jsonschema": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.4.1.tgz", - "integrity": "sha512-S6cATIPVv1z0IlxdN+zUk5EPjkGCdnhN4wVSBlvoUO1tOLJootbo9CquNJmbIh4yikWHiUedhRYrNPn1arpEmQ==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.5.0.tgz", + "integrity": "sha512-K+A9hhqbn0f3pJX17Q/7H6yQfD/5OXgdrR5UE12gMXCiN9D5Xq2o5mddV2QEcX/bjla99ASsAAQUyMCCRWAEhw==", "dev": true, + "license": "MIT", "engines": { "node": "*" } }, "node_modules/keccak": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.2.tgz", - "integrity": "sha512-PyKKjkH53wDMLGrvmRGSNWgmSxZOUqbnXwKL9tmgbFYA1iAYqW21kfR7mZXV0MlESiefxQQE9X9fTa3X+2MPDQ==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.4.tgz", + "integrity": "sha512-3vKuW0jV8J3XNTzvfyicFR5qvxrSAGl7KIhvgOu5cmWwM7tZRj3fMbj/pfIf4be7aznbc+prBWGjywox/g2Y6Q==", "hasInstallScript": true, + "license": "MIT", "dependencies": { "node-addon-api": "^2.0.0", "node-gyp-build": "^4.2.0", @@ -8127,6 +8506,7 @@ "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", "dev": true, + "license": "MIT", "dependencies": { "json-buffer": "3.0.1" } @@ -8136,40 +8516,43 @@ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/ky": { - "version": "0.30.0", - "resolved": "https://registry.npmjs.org/ky/-/ky-0.30.0.tgz", - "integrity": "sha512-X/u76z4JtDVq10u1JA5UQfatPxgPaVDMYTrgHyiTpGN2z4TMEJkIHsoSBBSg9SWZEIXTKsi9kHgiQ9o3Y/4yog==", + "version": "0.33.3", + "resolved": "https://registry.npmjs.org/ky/-/ky-0.33.3.tgz", + "integrity": "sha512-CasD9OCEQSFIam2U8efFK81Yeg8vNMTBUqtMOHlrcWQHqUX3HeCl9Dr31u4toV7emlH8Mymk5+9p0lL6mKb/Xw==", "dev": true, + "license": "MIT", "engines": { - "node": ">=12" + "node": ">=14.16" }, "funding": { "url": "https://github.com/sindresorhus/ky?sponsor=1" } }, "node_modules/ky-universal": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/ky-universal/-/ky-universal-0.10.1.tgz", - "integrity": "sha512-r8909k+ELKZAxhVA5c440x22hqw5XcMRwLRbgpPQk4JHy3/ddJnvzcnSo5Ww3HdKdNeS3Y8dBgcIYyVahMa46g==", + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/ky-universal/-/ky-universal-0.11.0.tgz", + "integrity": "sha512-65KyweaWvk+uKKkCrfAf+xqN2/epw1IJDtlyCPxYffFCMR8u1sp2U65NtWpnozYfZxQ6IUzIlvUcw+hQ82U2Xw==", "dev": true, + "license": "MIT", "dependencies": { "abort-controller": "^3.0.0", - "node-fetch": "^3.2.2" + "node-fetch": "^3.2.10" }, "engines": { - "node": ">=14" + "node": ">=14.16" }, "funding": { "url": "https://github.com/sindresorhus/ky-universal?sponsor=1" }, "peerDependencies": { - "ky": ">=0.26.0", - "web-streams-polyfill": ">=3.0.1" + "ky": ">=0.31.4", + "web-streams-polyfill": ">=3.2.1" }, "peerDependenciesMeta": { "web-streams-polyfill": { @@ -8228,22 +8611,22 @@ "license": "MIT" }, "node_modules/lint-staged": { - "version": "15.2.11", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.11.tgz", - "integrity": "sha512-Ev6ivCTYRTGs9ychvpVw35m/bcNDuBN+mnTeObCL5h+boS5WzBEC6LHI4I9F/++sZm1m+J2LEiy0gxL/R9TBqQ==", + "version": "15.5.1", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.5.1.tgz", + "integrity": "sha512-6m7u8mue4Xn6wK6gZvSCQwBvMBR36xfY24nF5bMTf2MHDYG6S3yhJuOgdYVw99hsjyDt2d4z168b3naI8+NWtQ==", "dev": true, "license": "MIT", "dependencies": { - "chalk": "~5.3.0", - "commander": "~12.1.0", - "debug": "~4.4.0", - "execa": "~8.0.1", - "lilconfig": "~3.1.3", - "listr2": "~8.2.5", - "micromatch": "~4.0.8", - "pidtree": "~0.6.0", - "string-argv": "~0.3.2", - "yaml": "~2.6.1" + "chalk": "^5.4.1", + "commander": "^13.1.0", + "debug": "^4.4.0", + "execa": "^8.0.1", + "lilconfig": "^3.1.3", + "listr2": "^8.2.5", + "micromatch": "^4.0.8", + "pidtree": "^0.6.0", + "string-argv": "^0.3.2", + "yaml": "^2.7.0" }, "bin": { "lint-staged": "bin/lint-staged.js" @@ -8256,9 +8639,9 @@ } }, "node_modules/lint-staged/node_modules/chalk": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", - "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz", + "integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==", "dev": true, "license": "MIT", "engines": { @@ -8268,20 +8651,10 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/lint-staged/node_modules/commander": { - "version": "12.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", - "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - } - }, "node_modules/listr2": { - "version": "8.2.5", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.2.5.tgz", - "integrity": "sha512-iyAZCeyD+c1gPyE9qpFu8af0Y+MRtmKOncdGoA2S5EY8iFq99dmmvkNnHiWo+pj0s7yH7l3KPIgee77tKpXPWQ==", + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.3.2.tgz", + "integrity": "sha512-vsBzcU4oE+v0lj4FhVLzr9dBTv4/fHIa57l+GCwovP8MoFNZJTOhGU8PXd4v2VJCbECAaijBiHntiekFMLvo0g==", "dev": true, "license": "MIT", "dependencies": { @@ -8385,6 +8758,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "license": "MIT", "dependencies": { "p-locate": "^5.0.0" }, @@ -8398,25 +8772,30 @@ "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "license": "MIT" }, "node_modules/lodash.camelcase": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/lodash.isequal": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==", + "deprecated": "This package is deprecated. Use require('node:util').isDeepStrictEqual instead.", + "license": "MIT", "peer": true }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/lodash.truncate": { "version": "4.4.2", @@ -8429,6 +8808,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "license": "MIT", "dependencies": { "chalk": "^4.1.0", "is-unicode-supported": "^0.1.0" @@ -8460,6 +8840,22 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/log-update/node_modules/ansi-escapes": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.0.0.tgz", + "integrity": "sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==", + "dev": true, + "license": "MIT", + "dependencies": { + "environment": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/log-update/node_modules/ansi-regex": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", @@ -8593,6 +8989,7 @@ "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-3.0.0.tgz", "integrity": "sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==", "dev": true, + "license": "MIT", "engines": { "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, @@ -8603,13 +9000,15 @@ "node_modules/lru_map": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/lru_map/-/lru_map-0.3.3.tgz", - "integrity": "sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ==" + "integrity": "sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ==", + "license": "MIT" }, "node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, + "license": "ISC", "dependencies": { "yallist": "^4.0.0" }, @@ -8620,7 +9019,8 @@ "node_modules/make-error": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==" + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "license": "ISC" }, "node_modules/markdown-table": { "version": "2.0.0", @@ -8637,14 +9037,26 @@ } }, "node_modules/match-all": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/match-all/-/match-all-1.2.6.tgz", - "integrity": "sha512-0EESkXiTkWzrQQntBu2uzKvLu6vVkUGz40nGPbSZuegcfE5UuSzNjLaIu76zJWuaT/2I3Z/8M06OlUOZLGwLlQ==" + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/match-all/-/match-all-1.2.7.tgz", + "integrity": "sha512-qSpsBKarh55r9KyXzFC3xBLRf2GlGasba2em9kbpRsSlGvdTAqjx3QD0r3FKSARiW+OE4iMHYsolM3aX9n5djw==", + "license": "MIT" + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } }, "node_modules/md5.js": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "dev": true, + "license": "MIT", "dependencies": { "hash-base": "^3.0.0", "inherits": "^2.0.1", @@ -8671,6 +9083,7 @@ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 8" } @@ -8680,6 +9093,7 @@ "resolved": "https://registry.npmjs.org/merkletreejs/-/merkletreejs-0.3.11.tgz", "integrity": "sha512-LJKTl4iVNTndhL+3Uz/tfkjD0klIWsHlUzgtuNnNrsf7bAlXR30m+xYB7lHr5Z/l6e/yAIsr26Dabx6Buo4VGQ==", "dev": true, + "license": "MIT", "dependencies": { "bignumber.js": "^9.0.1", "buffer-reverse": "^1.0.1", @@ -8691,6 +9105,36 @@ "node": ">= 7.6.0" } }, + "node_modules/micro-eth-signer": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/micro-eth-signer/-/micro-eth-signer-0.14.0.tgz", + "integrity": "sha512-5PLLzHiVYPWClEvZIXXFu5yutzpadb73rnQCpUqIHu3No3coFuWQNfE5tkBQJ7djuLYl6aRLaS0MgWJYGoqiBw==", + "license": "MIT", + "dependencies": { + "@noble/curves": "~1.8.1", + "@noble/hashes": "~1.7.1", + "micro-packed": "~0.7.2" + } + }, + "node_modules/micro-ftch": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/micro-ftch/-/micro-ftch-0.3.1.tgz", + "integrity": "sha512-/0LLxhzP0tfiR5hcQebtudP56gUurs2CLkGarnCiB/OqEyUFQ6U3paQi/tgLv0hBJYt2rnr9MNpxz4fiiugstg==", + "dev": true, + "license": "MIT" + }, + "node_modules/micro-packed": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/micro-packed/-/micro-packed-0.7.2.tgz", + "integrity": "sha512-HJ/u8+tMzgrJVAl6P/4l8KGjJSA3SCZaRb1m4wpbovNScCSmVOGUYbkkcoPPcknCHWPpRAdjy+yqXqyQWf+k8g==", + "license": "MIT", + "dependencies": { + "@scure/base": "~1.2.2" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/micromatch": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", @@ -8706,19 +9150,21 @@ } }, "node_modules/mime-db": { - "version": "1.51.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", - "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==", + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/mime-types": { - "version": "2.1.34", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", - "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", "dependencies": { - "mime-db": "1.51.0" + "mime-db": "1.52.0" }, "engines": { "node": ">= 0.6" @@ -8751,164 +9197,184 @@ } }, "node_modules/mimic-response": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", - "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-4.0.0.tgz", + "integrity": "sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==", "dev": true, + "license": "MIT", "engines": { - "node": ">=4" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/minimalistic-assert": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "license": "ISC" }, "node_modules/minimalistic-crypto-utils": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==" + "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==", + "license": "MIT" }, "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, + "license": "ISC", "dependencies": { - "brace-expansion": "^1.1.7" + "brace-expansion": "^2.0.1" }, "engines": { - "node": "*" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", - "dev": true + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } }, "node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", "dev": true, + "license": "MIT", + "dependencies": { + "minimist": "^1.2.6" + }, "bin": { "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" } }, "node_modules/mnemonist": { "version": "0.38.5", "resolved": "https://registry.npmjs.org/mnemonist/-/mnemonist-0.38.5.tgz", "integrity": "sha512-bZTFT5rrPKtPJxj8KSV0WkPyNxl72vQepqqVUAW2ARUpUSF2qXMB6jZj7hW5/k7C1rtpzqbD/IIbJwLXUjCHeg==", + "license": "MIT", "dependencies": { "obliterator": "^2.0.0" } }, "node_modules/mocha": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.2.0.tgz", - "integrity": "sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==", - "dependencies": { - "ansi-colors": "4.1.1", - "browser-stdout": "1.3.1", - "chokidar": "3.5.3", - "debug": "4.3.4", - "diff": "5.0.0", - "escape-string-regexp": "4.0.0", - "find-up": "5.0.0", - "glob": "7.2.0", - "he": "1.2.0", - "js-yaml": "4.1.0", - "log-symbols": "4.1.0", - "minimatch": "5.0.1", - "ms": "2.1.3", - "nanoid": "3.3.3", - "serialize-javascript": "6.0.0", - "strip-json-comments": "3.1.1", - "supports-color": "8.1.1", - "workerpool": "6.2.1", - "yargs": "16.2.0", - "yargs-parser": "20.2.4", - "yargs-unparser": "2.0.0" - }, + "version": "10.8.2", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.8.2.tgz", + "integrity": "sha512-VZlYo/WE8t1tstuRmqgeyBgCbJc/lEdopaa+axcKzTBJ+UIdlAB9XnmvTCAH4pwR4ElNInaedhEBmZD8iCSVEg==", + "license": "MIT", + "dependencies": { + "ansi-colors": "^4.1.3", + "browser-stdout": "^1.3.1", + "chokidar": "^3.5.3", + "debug": "^4.3.5", + "diff": "^5.2.0", + "escape-string-regexp": "^4.0.0", + "find-up": "^5.0.0", + "glob": "^8.1.0", + "he": "^1.2.0", + "js-yaml": "^4.1.0", + "log-symbols": "^4.1.0", + "minimatch": "^5.1.6", + "ms": "^2.1.3", + "serialize-javascript": "^6.0.2", + "strip-json-comments": "^3.1.1", + "supports-color": "^8.1.1", + "workerpool": "^6.5.1", + "yargs": "^16.2.0", + "yargs-parser": "^20.2.9", + "yargs-unparser": "^2.0.0" + }, "bin": { "_mocha": "bin/_mocha", "mocha": "bin/mocha.js" }, "engines": { "node": ">= 14.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mochajs" } }, - "node_modules/mocha/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "node_modules/mocha/node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "license": "MIT", "dependencies": { - "ms": "2.1.2" + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" }, "engines": { - "node": ">=6.0" + "node": ">= 8.10.0" }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/mocha/node_modules/debug/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "node_modules/mocha/node_modules/diff": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", - "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", - "engines": { - "node": ">=0.3.1" + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" } }, "node_modules/mocha/node_modules/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "minimatch": "^5.0.1", + "once": "^1.3.0" }, "engines": { - "node": "*" + "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/mocha/node_modules/glob/node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "node_modules/mocha/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "license": "ISC", "dependencies": { - "brace-expansion": "^1.1.7" + "is-glob": "^4.0.1" }, "engines": { - "node": "*" + "node": ">= 6" } }, "node_modules/mocha/node_modules/minimatch": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", - "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" }, @@ -8916,29 +9382,23 @@ "node": ">=10" } }, - "node_modules/mocha/node_modules/minimatch/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "node_modules/mocha/node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/mocha/node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "engines": { - "node": ">=8" + "picomatch": "^2.2.1" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">=8.10.0" } }, "node_modules/mocha/node_modules/supports-color": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -8968,34 +9428,57 @@ "version": "0.2.1", "resolved": "https://registry.npmjs.org/murmur-128/-/murmur-128-0.2.1.tgz", "integrity": "sha512-WseEgiRkI6aMFBbj8Cg9yBj/y+OdipwVC7zUo3W2W1JAJITwouUOtpqsmGSg67EQmwwSyod7hsVsWY5LsrfQVg==", + "license": "MIT", "dependencies": { "encode-utf8": "^1.0.2", "fmix": "^0.1.0", "imul": "^1.0.0" } }, - "node_modules/nanoid": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", - "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==", - "bin": { - "nanoid": "bin/nanoid.cjs" + "node_modules/n3": { + "version": "1.25.1", + "resolved": "https://registry.npmjs.org/n3/-/n3-1.25.1.tgz", + "integrity": "sha512-5vqp6Wcolb57WLC4DC0Nf6ieFPnTOLWwvIG0mmSzTpcRcNyd7xquVSlYSU6clvAZUEfs/OHWGNDRNwQi+m912Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer": "^6.0.3", + "readable-stream": "^4.0.0" + }, + "engines": { + "node": ">=12.0" + } + }, + "node_modules/n3/node_modules/readable-stream": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz", + "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==", + "dev": true, + "license": "MIT", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" }, "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/neo-async": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/nock": { "version": "13.5.6", @@ -9014,7 +9497,8 @@ "node_modules/node-addon-api": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz", - "integrity": "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==" + "integrity": "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==", + "license": "MIT" }, "node_modules/node-domexception": { "version": "1.0.0", @@ -9030,6 +9514,7 @@ "url": "https://paypal.me/jimmywarting" } ], + "license": "MIT", "engines": { "node": ">=10.5.0" } @@ -9039,6 +9524,7 @@ "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz", "integrity": "sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==", "dev": true, + "license": "MIT", "dependencies": { "lodash": "^4.17.21" } @@ -9047,6 +9533,7 @@ "version": "3.3.2", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "license": "MIT", "dependencies": { "data-uri-to-buffer": "^4.0.0", "fetch-blob": "^3.1.4", @@ -9061,9 +9548,10 @@ } }, "node_modules/node-gyp-build": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.5.0.tgz", - "integrity": "sha512-2iGbaQBV+ITgCz76ZEjmhUKAKVf7xfY1sRl4UiKQspfZMH2h06SyhNsnSVy50cwkFQDGLyif6m/6uFXHkOZ6rg==", + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz", + "integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==", + "license": "MIT", "bin": { "node-gyp-build": "bin.js", "node-gyp-build-optional": "optional.js", @@ -9075,6 +9563,7 @@ "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", "integrity": "sha512-4GUt3kSEYmk4ITxzB/b9vaIDfUVWN/Ml1Fwl11IlnIG2iaJ9O6WXZ9SrYM9NLI8OCBieN2Y8SWC2oJV0RQ7qYg==", "dev": true, + "license": "ISC", "dependencies": { "abbrev": "1" }, @@ -9086,17 +9575,19 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/normalize-url": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", - "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-8.0.1.tgz", + "integrity": "sha512-IO9QvjUMWxPQQhs60oOu10CRkWCiZzSUkzbXGGV9pviYl1fXYcvkzQ5jV9z8Y6un8ARoVRl4EtC6v6jNqbaJ/w==", "dev": true, + "license": "MIT", "engines": { - "node": ">=10" + "node": ">=14.16" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -9136,6 +9627,7 @@ "resolved": "https://registry.npmjs.org/number-to-bn/-/number-to-bn-1.7.0.tgz", "integrity": "sha512-wsJ9gfSz1/s4ZsJN01lyonwuxA1tml6X1yBDnfpMglypcBRFZZkus26EdPSlqS5GJfYddVZa22p3VNb3z5m5Ig==", "dev": true, + "license": "MIT", "dependencies": { "bn.js": "4.11.6", "strip-hex-prefix": "1.0.0" @@ -9149,12 +9641,13 @@ "version": "4.11.6", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", "integrity": "sha512-XWwnNNFCuuSQ0m3r3C4LE3EiORltHd9M05pq6FOlVeiophzRbMo50Sbz1ehl8K3Z+jw9+vmgnXefY1hz8X+2wA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/object-inspect": { - "version": "1.13.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.3.tgz", - "integrity": "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==", + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", "license": "MIT", "engines": { "node": ">= 0.4" @@ -9174,15 +9667,17 @@ } }, "node_modules/object.assign": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", - "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", + "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.5", + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", "define-properties": "^1.2.1", - "has-symbols": "^1.0.3", + "es-object-atoms": "^1.0.0", + "has-symbols": "^1.1.0", "object-keys": "^1.1.1" }, "engines": { @@ -9227,13 +9722,14 @@ } }, "node_modules/object.values": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", - "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz", + "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" }, @@ -9245,14 +9741,16 @@ } }, "node_modules/obliterator": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/obliterator/-/obliterator-2.0.4.tgz", - "integrity": "sha512-lgHwxlxV1qIg1Eap7LgIeoBWIMFibOjbrYPIPJZcI1mmGAI2m3lNYpK12Y+GBdPQ0U1hRwSord7GIaawz962qQ==" + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/obliterator/-/obliterator-2.0.5.tgz", + "integrity": "sha512-42CPE9AhahZRsMNslczq0ctAEtqk8Eka26QofnqC346BZdHDySk3LWka23LI7ULIw11NmltpiLagIq8gBozxTw==", + "license": "MIT" }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", "dependencies": { "wrappy": "1" } @@ -9295,21 +9793,72 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/ordinal/-/ordinal-1.0.3.tgz", "integrity": "sha512-cMddMgb2QElm8G7vdaa02jhUNbTSrhsgAGUz1OokD83uJTwSUn+nKoNoKVVaRa08yF6sgfO7Maou1+bgLd9rdQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", + "license": "MIT", "engines": { "node": ">=0.10.0" } }, + "node_modules/own-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", + "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.2.6", + "object-keys": "^1.1.1", + "safe-push-apply": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ox": { + "version": "0.6.9", + "resolved": "https://registry.npmjs.org/ox/-/ox-0.6.9.tgz", + "integrity": "sha512-wi5ShvzE4eOcTwQVsIPdFr+8ycyX+5le/96iAJutaZAvCes1J0+RvpEPg5QDPDiaR0XQQAvZVl7AwqQcINuUug==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/wevm" + } + ], + "license": "MIT", + "dependencies": { + "@adraffy/ens-normalize": "^1.10.1", + "@noble/curves": "^1.6.0", + "@noble/hashes": "^1.5.0", + "@scure/bip32": "^1.5.0", + "@scure/bip39": "^1.4.0", + "abitype": "^1.0.6", + "eventemitter3": "5.0.1" + }, + "peerDependencies": { + "typescript": ">=5.4.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, "node_modules/p-cancelable": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-3.0.0.tgz", "integrity": "sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==", "dev": true, + "license": "MIT", "engines": { "node": ">=12.20" } @@ -9318,6 +9867,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "license": "MIT", "dependencies": { "yocto-queue": "^0.1.0" }, @@ -9332,6 +9882,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "license": "MIT", "dependencies": { "p-limit": "^3.0.2" }, @@ -9346,6 +9897,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "license": "MIT", "dependencies": { "aggregate-error": "^3.0.0" }, @@ -9382,24 +9934,12 @@ "dev": true, "license": "BlueOak-1.0.0" }, - "node_modules/package-json/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dev": true, + "license": "MIT", "dependencies": { "callsites": "^3.0.0" }, @@ -9430,6 +9970,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "license": "MIT", "engines": { "node": ">=8" } @@ -9438,6 +9979,8 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -9447,6 +9990,7 @@ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -9454,7 +9998,8 @@ "node_modules/path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "license": "MIT" }, "node_modules/path-scurry": { "version": "1.11.1", @@ -9480,21 +10025,12 @@ "dev": true, "license": "ISC" }, - "node_modules/path-scurry/node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, "node_modules/path-starts-with": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/path-starts-with/-/path-starts-with-2.0.1.tgz", "integrity": "sha512-wZ3AeiRBRlNwkdUxvBANh0+esnt38DLffHDujZyRHkqkaKHTglnY2EP5UX3b8rdeiSutgO4y9NEJwXezNP5vHg==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -9504,6 +10040,7 @@ "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -9513,6 +10050,7 @@ "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", "dev": true, + "license": "MIT", "engines": { "node": "*" } @@ -9521,6 +10059,8 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", + "dev": true, + "license": "MIT", "dependencies": { "create-hash": "^1.1.2", "create-hmac": "^1.1.4", @@ -9542,6 +10082,7 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "license": "MIT", "engines": { "node": ">=8.6" }, @@ -9554,6 +10095,7 @@ "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz", "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", "dev": true, + "license": "MIT", "bin": { "pidtree": "bin/pidtree.js" }, @@ -9566,6 +10108,7 @@ "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -9581,9 +10124,9 @@ } }, "node_modules/possible-typed-array-names": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", - "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", "dev": true, "license": "MIT", "engines": { @@ -9601,9 +10144,9 @@ } }, "node_modules/prettier": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.4.2.tgz", - "integrity": "sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==", + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.3.tgz", + "integrity": "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==", "dev": true, "license": "MIT", "bin": { @@ -9621,6 +10164,7 @@ "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", "dev": true, + "license": "MIT", "dependencies": { "fast-diff": "^1.1.2" }, @@ -9629,35 +10173,30 @@ } }, "node_modules/prettier-plugin-solidity": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/prettier-plugin-solidity/-/prettier-plugin-solidity-1.4.1.tgz", - "integrity": "sha512-Mq8EtfacVZ/0+uDKTtHZGW3Aa7vEbX/BNx63hmVg6YTiTXSiuKP0amj0G6pGwjmLaOfymWh3QgXEZkjQbU8QRg==", + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/prettier-plugin-solidity/-/prettier-plugin-solidity-1.4.2.tgz", + "integrity": "sha512-VVD/4XlDjSzyPWWCPW8JEleFa8JNKFYac5kNlMjVXemQyQZKfpekPMhFZSePuXB6L+RixlFvWe20iacGjFYrLw==", "dev": true, "license": "MIT", "dependencies": { - "@solidity-parser/parser": "^0.18.0", - "semver": "^7.5.4" + "@solidity-parser/parser": "^0.19.0", + "semver": "^7.6.3" }, "engines": { - "node": ">=16" + "node": ">=18" }, "peerDependencies": { "prettier": ">=2.3.0" } }, - "node_modules/prettier-plugin-solidity/node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, + "license": "MIT", "engines": { - "node": ">=10" + "node": ">= 0.6.0" } }, "node_modules/propagate": { @@ -9683,31 +10222,23 @@ "dev": true, "license": "MIT" }, - "node_modules/pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, "node_modules/punycode": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.0.tgz", - "integrity": "sha512-Yxz2kRwT90aPiWEMHVYnEf4+rhwF1tBmmZ4KepCP+Wkium9JxtWnUm1nqGwpiAHr/tnTSeHqr3wb++jgSkXjhA==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", + "license": "BSD-3-Clause", "dependencies": { - "side-channel": "^1.0.4" + "side-channel": "^1.1.0" }, "engines": { "node": ">=0.6" @@ -9734,13 +10265,15 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/quick-lru": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -9749,15 +10282,17 @@ } }, "node_modules/rambda": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/rambda/-/rambda-7.4.0.tgz", - "integrity": "sha512-A9hihu7dUTLOUCM+I8E61V4kRXnN4DwYeK0DwCBydC1MqNI1PidyAtbtpsJlBBzK4icSctEcCQ1bGcLpBuETUQ==", - "dev": true + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/rambda/-/rambda-7.5.0.tgz", + "integrity": "sha512-y/M9weqWAH4iopRd7EHDEQQvpFPHj1AA3oHozE9tfITHUtTR7Z9PSlIRRG2l1GuW7sefC1cXFfIcF+cgnShdBA==", + "dev": true, + "license": "MIT" }, "node_modules/randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "license": "MIT", "dependencies": { "safe-buffer": "^5.1.0" } @@ -9766,6 +10301,7 @@ "version": "2.5.2", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "license": "MIT", "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", @@ -9792,22 +10328,34 @@ "rc": "cli.js" } }, + "node_modules/rc/node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/rdf-canonize": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/rdf-canonize/-/rdf-canonize-3.3.0.tgz", - "integrity": "sha512-gfSNkMua/VWC1eYbSkVaL/9LQhFeOh0QULwv7Or0f+po8pMgQ1blYQFe1r9Mv2GJZXw88Cz/drnAnB9UlNnHfQ==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/rdf-canonize/-/rdf-canonize-4.0.1.tgz", + "integrity": "sha512-B5ynHt4sasbUafzrvYI2GFARgeFcD8Sx9yXPbg7gEyT2EH76rlCv84kyO6tnxzVbxUN/uJDbK1S/MXh+DsnuTA==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "setimmediate": "^1.0.5" }, "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/readable-stream": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -9818,12 +10366,12 @@ } }, "node_modules/readdirp": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.2.tgz", - "integrity": "sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", "license": "MIT", "engines": { - "node": ">= 14.16.0" + "node": ">= 14.18.0" }, "funding": { "type": "individual", @@ -9847,6 +10395,7 @@ "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.3.tgz", "integrity": "sha512-8HrF5ZsXk5FAH9dgsx3BlUer73nIhuj+9OrQwEbLTPOBzGkL1lsFCR01am+v+0m2Cmbs1nP12hLDl5FA7EszKA==", "dev": true, + "license": "MIT", "dependencies": { "minimatch": "^3.0.5" }, @@ -9854,29 +10403,55 @@ "node": ">=6.0.0" } }, + "node_modules/recursive-readdir/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/recursive-readdir/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/reduce-flatten": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-2.0.0.tgz", "integrity": "sha512-EJ4UNY/U1t2P/2k6oqotuX2Cc3T6nxJwsM0N0asT7dhrtH1ltUxDn4NalSYmPE2rCkVpcf/X6R0wDwcFpzhd4w==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/reflect.getprototypeof": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.7.tgz", - "integrity": "sha512-bMvFGIUKlc/eSfXNX+aZ+EL95/EgZzuwA0OBPTbZZDEJw/0AkentjMuM1oiRfwHrshqk4RzdgiTg5CcDalXN5g==", + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", + "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", "define-properties": "^1.2.1", - "es-abstract": "^1.23.5", + "es-abstract": "^1.23.9", "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "which-builtin-type": "^1.1.4" + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.1", + "which-builtin-type": "^1.2.1" }, "engines": { "node": ">= 0.4" @@ -9886,15 +10461,17 @@ } }, "node_modules/regexp.prototype.flags": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.3.tgz", - "integrity": "sha512-vqlC04+RQoFalODCbCumG2xIOvapzVMHwsyIGM/SIE8fRhFFsXeH8/QQ+s0T0kDAhKc4k30s73/0ydkHQz6HlQ==", + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", + "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-errors": "^1.3.0", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", "set-function-name": "^2.0.2" }, "engines": { @@ -9905,9 +10482,9 @@ } }, "node_modules/registry-auth-token": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-5.0.3.tgz", - "integrity": "sha512-1bpc9IyC+e+CNFRaWyn77tk4xGG4PPUyfakSmA6F6cvUDjrm58dfyJ3II+9yb10EDkHoy1LaPSmHaWLOH3m6HA==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-5.1.0.tgz", + "integrity": "sha512-GdekYuwLXLxMuFTwAPg5UKGLW/UXzQrZvH/Zj791BQif5T05T0RsaLfHc9q3ZOKi7n+BoprPD9mJ0O0k4xzUlw==", "dev": true, "license": "MIT", "dependencies": { @@ -9947,6 +10524,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -9962,19 +10540,22 @@ } }, "node_modules/resolve": { - "version": "1.22.8", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", - "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "version": "1.22.10", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", + "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", "dev": true, "license": "MIT", "dependencies": { - "is-core-module": "^2.13.0", + "is-core-module": "^2.16.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -9983,13 +10564,15 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -10005,26 +10588,21 @@ } }, "node_modules/responselike": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", - "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-3.0.0.tgz", + "integrity": "sha512-40yHxbNcl2+rzXvZuVkrYohathsSJlMTXKryG5y8uciHv1+xDLHQpgjG64JUO9nrEq2jGLH6IZ8BcZyw3wrweg==", "dev": true, + "license": "MIT", "dependencies": { - "lowercase-keys": "^2.0.0" + "lowercase-keys": "^3.0.0" + }, + "engines": { + "node": ">=14.16" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/responselike/node_modules/lowercase-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/restore-cursor": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", @@ -10059,10 +10637,11 @@ } }, "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", "dev": true, + "license": "MIT", "engines": { "iojs": ">=1.0.0", "node": ">=0.10.0" @@ -10079,7 +10658,9 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", "dev": true, + "license": "ISC", "dependencies": { "glob": "^7.1.3" }, @@ -10090,10 +10671,58 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/rimraf/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/rimraf/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/ripemd160": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "dev": true, + "license": "MIT", "dependencies": { "hash-base": "^3.0.0", "inherits": "^2.0.1" @@ -10103,6 +10732,8 @@ "version": "2.2.7", "resolved": "https://registry.npmjs.org/rlp/-/rlp-2.2.7.tgz", "integrity": "sha512-d5gdPmgQ0Z+AklL2NVXr/IoSjNZFfTVvQWzL/AM2AOcSzYP2xjlb0AC8YyCLc41MSNf6P6QVtjgPdmVtzb+4lQ==", + "dev": true, + "license": "MPL-2.0", "dependencies": { "bn.js": "^5.2.0" }, @@ -10129,29 +10760,31 @@ "url": "https://feross.org/support" } ], + "license": "MIT", "dependencies": { "queue-microtask": "^1.2.2" } }, "node_modules/rxjs": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", - "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "version": "7.8.2", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", + "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", "license": "Apache-2.0", "dependencies": { "tslib": "^2.1.0" } }, "node_modules/safe-array-concat": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", - "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz", + "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", - "get-intrinsic": "^1.2.4", - "has-symbols": "^1.0.3", + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "has-symbols": "^1.1.0", "isarray": "^2.0.5" }, "engines": { @@ -10178,18 +10811,36 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" + }, + "node_modules/safe-push-apply": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", + "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/safe-regex-test": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", - "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.6", + "call-bound": "^1.0.2", "es-errors": "^1.3.0", - "is-regex": "^1.1.4" + "is-regex": "^1.2.1" }, "engines": { "node": ">= 0.4" @@ -10201,13 +10852,15 @@ "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" }, "node_modules/sc-istanbul": { "version": "0.4.6", "resolved": "https://registry.npmjs.org/sc-istanbul/-/sc-istanbul-0.4.6.tgz", "integrity": "sha512-qJFF/8tW/zJsbyfh/iT/ZM5QNHE3CXxtLJbZsL+CzdJLBsPD7SedJZoUA4d8iAcN2IoMp/Dx80shOOd2x96X/g==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "abbrev": "1.0.x", "async": "1.x", @@ -10233,21 +10886,20 @@ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", "dev": true, + "license": "MIT", "dependencies": { "sprintf-js": "~1.0.2" } }, - "node_modules/sc-istanbul/node_modules/esprima": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", - "integrity": "sha512-OarPfz0lFCiW4/AV2Oy1Rp9qu0iusTKqykwTspGCZtPxmF81JR4MmIebvF1F9+UOKth2ZubLQ4XGGaU+hSn99A==", + "node_modules/sc-istanbul/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=0.10.0" + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, "node_modules/sc-istanbul/node_modules/glob": { @@ -10256,6 +10908,7 @@ "integrity": "sha512-c9IPMazfRITpmAAKi22dK1VKxGDX9ehhqfABDriL/lzO92xcUKEJPQHrVA/2YHSNFB4iFlykVmWvwo48nr3OxA==", "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, + "license": "ISC", "dependencies": { "inflight": "^1.0.4", "inherits": "2", @@ -10272,6 +10925,7 @@ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", "integrity": "sha512-DyYHfIYwAJmjAjSSPKANxI8bFY9YtFrgkAfinBojQ8YJTOuOuav64tMUJv584SES4xl74PmuaevIyaLESHdTAA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -10281,6 +10935,7 @@ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", "dev": true, + "license": "MIT", "dependencies": { "argparse": "^1.0.7", "esprima": "^4.0.0" @@ -10294,6 +10949,7 @@ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", "dev": true, + "license": "BSD-2-Clause", "bin": { "esparse": "bin/esparse.js", "esvalidate": "bin/esvalidate.js" @@ -10302,29 +10958,32 @@ "node": ">=4" } }, - "node_modules/sc-istanbul/node_modules/mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "node_modules/sc-istanbul/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, + "license": "ISC", "dependencies": { - "minimist": "^1.2.6" + "brace-expansion": "^1.1.7" }, - "bin": { - "mkdirp": "bin/cmd.js" + "engines": { + "node": "*" } }, "node_modules/sc-istanbul/node_modules/resolve": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", "integrity": "sha512-9znBF0vBcaSN3W2j7wKvdERPwqTxSpCq+if5C0WoTCyV9n24rua28jeuQ2pL/HOf+yUe/Mef+H/5p60K0Id3bg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/sc-istanbul/node_modules/supports-color": { "version": "3.2.3", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", "integrity": "sha512-Jds2VIYDrlp5ui7t8abHN2bjAu4LV/q4N2KivFPpGH0lrka0BMq/33AmECUXlKPcHigkNaqfXRENFju+rlcy+A==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^1.0.0" }, @@ -10337,6 +10996,7 @@ "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "dev": true, + "license": "ISC", "dependencies": { "isexe": "^2.0.0" }, @@ -10354,34 +11014,50 @@ "node_modules/scrypt-js": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-3.0.1.tgz", - "integrity": "sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==" + "integrity": "sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==", + "license": "MIT" }, "node_modules/secp256k1": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.3.tgz", - "integrity": "sha512-NLZVf+ROMxwtEj3Xa562qgv2BK5e2WNmXPiOdVIPLgs6lyTzMvBq0aWTYMI5XCP9jZMVKOcqZLw/Wc4vDkuxhA==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.4.tgz", + "integrity": "sha512-6JfvwvjUOn8F/jUoBY2Q1v5WY5XS+rj8qSe0v8Y4ezH4InLgTEeOOPQsRll9OV429Pvo6BCHGavIyJfr3TAhsw==", + "dev": true, "hasInstallScript": true, + "license": "MIT", "dependencies": { - "elliptic": "^6.5.4", - "node-addon-api": "^2.0.0", + "elliptic": "^6.5.7", + "node-addon-api": "^5.0.0", "node-gyp-build": "^4.2.0" }, "engines": { - "node": ">=10.0.0" + "node": ">=18.0.0" } }, + "node_modules/secp256k1/node_modules/node-addon-api": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", + "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==", + "dev": true, + "license": "MIT" + }, "node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, "node_modules/serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "license": "BSD-3-Clause", "dependencies": { "randombytes": "^2.1.0" } @@ -10390,6 +11066,7 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, "license": "MIT", "dependencies": { "define-data-property": "^1.1.4", @@ -10419,20 +11096,40 @@ "node": ">= 0.4" } }, + "node_modules/set-proto": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", + "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/setimmediate": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==" + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", + "dev": true, + "license": "MIT" }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" }, "node_modules/sha.js": { "version": "2.4.11", "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dev": true, + "license": "(MIT AND BSD-3-Clause)", "dependencies": { "inherits": "^2.0.1", "safe-buffer": "^5.0.1" @@ -10460,6 +11157,7 @@ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, + "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" }, @@ -10472,6 +11170,7 @@ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -10481,6 +11180,7 @@ "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz", "integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "glob": "^7.0.0", "interpret": "^1.0.0", @@ -10493,59 +11193,177 @@ "node": ">=4" } }, - "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "node_modules/shelljs/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "node_modules/shelljs/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, "engines": { - "node": ">=14" + "node": "*" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "node_modules/shelljs/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, "engines": { - "node": ">=8" + "node": "*" } }, - "node_modules/slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", - "dev": true, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", "license": "MIT", "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" }, "engines": { - "node": ">=10" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/slice-ansi": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", + "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.0.0", + "is-fullwidth-code-point": "^4.0.0" + }, + "engines": { + "node": ">=12" }, "funding": { "url": "https://github.com/chalk/slice-ansi?sponsor=1" } }, + "node_modules/slice-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/smoldot": { "version": "2.0.26", "resolved": "https://registry.npmjs.org/smoldot/-/smoldot-2.0.26.tgz", @@ -10562,14 +11380,53 @@ "integrity": "sha512-MkY9KFFuhMeTkWU+4wIzBoEkGr1DXdMR98/zGB8S7efg9Wph9Z4d98RRu7c8pRpmRfrSPAYuMKkvauMCpWXStg==", "license": "MIT" }, + "node_modules/solc": { + "version": "0.8.26", + "resolved": "https://registry.npmjs.org/solc/-/solc-0.8.26.tgz", + "integrity": "sha512-yiPQNVf5rBFHwN6SIf3TUUvVAFKcQqmSUFeq+fb6pNRCo0ZCgpYOZDi3BVoezCPIAcKrVYd/qXlBLUP9wVrZ9g==", + "license": "MIT", + "dependencies": { + "command-exists": "^1.2.8", + "commander": "^8.1.0", + "follow-redirects": "^1.12.1", + "js-sha3": "0.8.0", + "memorystream": "^0.3.1", + "semver": "^5.5.0", + "tmp": "0.0.33" + }, + "bin": { + "solcjs": "solc.js" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/solc/node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "license": "MIT", + "engines": { + "node": ">= 12" + } + }, + "node_modules/solc/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "license": "ISC", + "bin": { + "semver": "bin/semver" + } + }, "node_modules/solhint": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/solhint/-/solhint-5.0.3.tgz", - "integrity": "sha512-OLCH6qm/mZTCpplTXzXTJGId1zrtNuDYP5c2e6snIv/hdRVxPfBBz/bAlL91bY/Accavkayp2Zp2BaDSrLVXTQ==", + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/solhint/-/solhint-5.0.5.tgz", + "integrity": "sha512-WrnG6T+/UduuzSWsSOAbfq1ywLUDwNea3Gd5hg6PS+pLUm8lz2ECNr0beX609clBxmDeZ3676AiA9nPDljmbJQ==", "dev": true, "license": "MIT", "dependencies": { - "@solidity-parser/parser": "^0.18.0", + "@solidity-parser/parser": "^0.19.0", "ajv": "^6.12.6", "antlr4": "^4.13.1-patch-1", "ast-parents": "^0.0.1", @@ -10610,14 +11467,14 @@ "prettier-plugin-solidity": "^1.0.0" } }, - "node_modules/solhint/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "node_modules/solhint/node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", "dev": true, "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" + "engines": { + "node": ">=14" } }, "node_modules/solhint/node_modules/glob": { @@ -10671,23 +11528,10 @@ "url": "https://github.com/prettier/prettier?sponsor=1" } }, - "node_modules/solhint/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/solidity-coverage": { - "version": "0.8.14", - "resolved": "https://registry.npmjs.org/solidity-coverage/-/solidity-coverage-0.8.14.tgz", - "integrity": "sha512-ItAAObe5GaEOp20kXC2BZRnph+9P7Rtoqg2mQc2SXGEHgSDF2wWd1Wxz3ntzQWXkbCtIIGdJT918HG00cObwbA==", + "version": "0.8.15", + "resolved": "https://registry.npmjs.org/solidity-coverage/-/solidity-coverage-0.8.15.tgz", + "integrity": "sha512-qH7290NKww4/t/qFvnSEePEzON0k025IGVlwc8wo8Q6p+h1Tt6fV2M0k3yfsps3TomZYTROsfPXjx7MSnwD5uA==", "dev": true, "license": "ISC", "dependencies": { @@ -10718,18 +11562,12 @@ "hardhat": "^2.11.0" } }, - "node_modules/solidity-coverage/node_modules/@solidity-parser/parser": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.19.0.tgz", - "integrity": "sha512-RV16k/qIxW/wWc+mLzV3ARyKUaMUTBy9tOLMzFhtNSKYeTAanQ3a5MudJKf/8arIFnA2L27SNjarQKmFg0w/jA==", - "dev": true, - "license": "MIT" - }, "node_modules/solidity-coverage/node_modules/ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, + "license": "MIT", "dependencies": { "color-convert": "^1.9.0" }, @@ -10742,6 +11580,7 @@ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -10756,6 +11595,7 @@ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, + "license": "MIT", "dependencies": { "color-name": "1.1.3" } @@ -10764,13 +11604,15 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/solidity-coverage/node_modules/escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.8.0" } @@ -10780,6 +11622,7 @@ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", "dev": true, + "license": "MIT", "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^4.0.0", @@ -10789,44 +11632,24 @@ "node": ">=6 <7 || >=8" } }, - "node_modules/solidity-coverage/node_modules/globby": { - "version": "10.0.2", - "resolved": "https://registry.npmjs.org/globby/-/globby-10.0.2.tgz", - "integrity": "sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg==", - "dev": true, - "dependencies": { - "@types/glob": "^7.1.1", - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.0.3", - "glob": "^7.1.3", - "ignore": "^5.1.1", - "merge2": "^1.2.3", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/solidity-coverage/node_modules/has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } }, - "node_modules/solidity-coverage/node_modules/semver": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", - "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "node_modules/solidity-coverage/node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", "dev": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" + "license": "MIT", + "optionalDependencies": { + "graceful-fs": "^4.1.6" } }, "node_modules/solidity-coverage/node_modules/supports-color": { @@ -10834,6 +11657,7 @@ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, + "license": "MIT", "dependencies": { "has-flag": "^3.0.0" }, @@ -10841,6 +11665,16 @@ "node": ">=4" } }, + "node_modules/solidity-coverage/node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4.0.0" + } + }, "node_modules/source-map": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", @@ -10858,6 +11692,7 @@ "version": "0.5.21", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "license": "MIT", "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -10867,6 +11702,7 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } @@ -10875,19 +11711,21 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true + "dev": true, + "license": "BSD-3-Clause" }, "node_modules/stable-hash": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/stable-hash/-/stable-hash-0.0.4.tgz", - "integrity": "sha512-LjdcbuBeLcdETCrPn9i8AYAZ1eCtu4ECAWtP7UleOiZ9LzVxRzzUZEoZ8zB24nhkQnDWyET0I+3sWokSDS3E7g==", + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/stable-hash/-/stable-hash-0.0.5.tgz", + "integrity": "sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==", "dev": true, "license": "MIT" }, "node_modules/stacktrace-parser": { - "version": "0.1.10", - "resolved": "https://registry.npmjs.org/stacktrace-parser/-/stacktrace-parser-0.1.10.tgz", - "integrity": "sha512-KJP1OCML99+8fhOHxwwzyWrlUuVX5GQ0ZpJTd1DFXhdkrvg1szxfHhawXUZ3g9TkXORQd4/WG68jMlQZ2p8wlg==", + "version": "0.1.11", + "resolved": "https://registry.npmjs.org/stacktrace-parser/-/stacktrace-parser-0.1.11.tgz", + "integrity": "sha512-WjlahMgHmCJpqzU8bIBy4qtsZdU9lRlcZE3Lvyej6t4tuOuv1vk57OW3MBrj6hXBFx/nNoC9MPMTcr5YA7NQbg==", + "license": "MIT", "dependencies": { "type-fest": "^0.7.1" }, @@ -10899,6 +11737,7 @@ "version": "0.7.1", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.7.1.tgz", "integrity": "sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==", + "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=8" } @@ -10907,6 +11746,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -10915,6 +11755,7 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "license": "MIT", "dependencies": { "safe-buffer": "~5.2.0" } @@ -10933,12 +11774,14 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/string-format/-/string-format-2.0.0.tgz", "integrity": "sha512-bbEs3scLeYNXLecRRuk6uJxdXUSj6le/8rNPHChIJTn2V79aXVTR1EH2OH5zLKKoz0V02fOUKZZcw01pLUShZA==", - "dev": true + "dev": true, + "license": "WTFPL OR MIT" }, "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==", + "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -10964,17 +11807,39 @@ "node": ">=8" } }, + "node_modules/string-width-cjs/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==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width/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==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/string.prototype.trim": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", - "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz", + "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-data-property": "^1.1.4", "define-properties": "^1.2.1", - "es-abstract": "^1.23.0", - "es-object-atoms": "^1.0.0" + "es-abstract": "^1.23.5", + "es-object-atoms": "^1.0.0", + "has-property-descriptors": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -10984,16 +11849,20 @@ } }, "node_modules/string.prototype.trimend": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", - "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz", + "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -11020,6 +11889,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" }, @@ -11068,6 +11938,8 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz", "integrity": "sha512-q8d4ue7JGEiVcypji1bALTos+0pWtyGlivAWyPuTkHzuTCJqrK9sWxYQZUq6Nq3cuyv3bm734IhHvHtGGURU6A==", + "dev": true, + "license": "MIT", "dependencies": { "is-hex-prefixed": "1.0.0" }, @@ -11077,19 +11949,22 @@ } }, "node_modules/strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", - "dev": true, + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "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==", + "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, @@ -11102,6 +11977,7 @@ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -11110,20 +11986,20 @@ } }, "node_modules/synckit": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.2.tgz", - "integrity": "sha512-vrozgXDQwYO72vHjUb/HnFbQx1exDjoKzqx23aXEg2a9VIg2TSFZ8FmeZpTjUCFMYw7mpX4BE2SFu8wI7asYsw==", + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.4.tgz", + "integrity": "sha512-Q/XQKRaJiLiFIBNN+mndW7S/RHxvwzuZS6ZwmRzUBqJBv/5QIKCEwkBC8GBf8EQJKYnaFs0wOZbKTXBPj8L9oQ==", "dev": true, "license": "MIT", "dependencies": { - "@pkgr/core": "^0.1.0", - "tslib": "^2.6.2" + "@pkgr/core": "^0.2.3", + "tslib": "^2.8.1" }, "engines": { "node": "^14.18.0 || >=16.0.0" }, "funding": { - "url": "https://opencollective.com/unts" + "url": "https://opencollective.com/synckit" } }, "node_modules/table": { @@ -11148,6 +12024,7 @@ "resolved": "https://registry.npmjs.org/table-layout/-/table-layout-1.0.2.tgz", "integrity": "sha512-qd/R7n5rQTRFi+Zf2sk5XVVd9UQl6ZkduPFC3S7WEGJAmetDTjY3qPN50eSKzwuzEyQKy5TN2TiZdkIjos2L6A==", "dev": true, + "license": "MIT", "dependencies": { "array-back": "^4.0.1", "deep-extend": "~0.6.0", @@ -11163,6 +12040,7 @@ "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.2.tgz", "integrity": "sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -11172,6 +12050,7 @@ "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -11193,6 +12072,16 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/table/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==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/table/node_modules/json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", @@ -11200,39 +12089,51 @@ "dev": true, "license": "MIT" }, - "node_modules/tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "node_modules/table/node_modules/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", "dev": true, "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, "engines": { - "node": ">=6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" } }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/tinyglobby": { - "version": "0.2.10", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.10.tgz", - "integrity": "sha512-Zc+8eJlFMvgatPZTl6A9L/yht8QqdmUNtURHaKZLmKBE12hNPSrqNkUp2cs3M/UKmNVVAMFQYSjYIVHDjW5zew==", + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.12.tgz", + "integrity": "sha512-qkf4trmKSIiMTs/E63cxH+ojC2unam7rJ0WrauAzpT3ECNTxGRMlaXxVbfxMUC/w0LaYk6jQ4y/nGR9uBO3tww==", "license": "MIT", "dependencies": { - "fdir": "^6.4.2", + "fdir": "^6.4.3", "picomatch": "^4.0.2" }, "engines": { "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" } }, "node_modules/tinyglobby/node_modules/fdir": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.2.tgz", - "integrity": "sha512-KnhMXsKSPZlAhp7+IjUkRZKPb4fUyccpDrdFXbi4QL1qkmFh9kVY09Yox+n4MaOb3lHZ1Tv829C3oaaXoMYPDQ==", + "version": "6.4.3", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.3.tgz", + "integrity": "sha512-PMXmW2y1hDDfTSRc9gaXIuCCRpuoz3Kaz8cUelp3smouvfT632ozg2vrT6lJsHKKOF59YLbOGfAWGUcKEfRMQw==", "license": "MIT", "peerDependencies": { "picomatch": "^3 || ^4" @@ -11259,6 +12160,7 @@ "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "license": "MIT", "dependencies": { "os-tmpdir": "~1.0.2" }, @@ -11270,6 +12172,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "license": "MIT", "dependencies": { "is-number": "^7.0.0" }, @@ -11281,6 +12184,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", "engines": { "node": ">=0.6" } @@ -11290,28 +12194,30 @@ "resolved": "https://registry.npmjs.org/treeify/-/treeify-1.1.0.tgz", "integrity": "sha512-1m4RA7xVAJrSGrrXGs0L3YTwyvBs2S8PbRHaLZAkFw7JR8oIFwYtysxlBZhYIa7xSyiYJKZ3iGrrk55cGA3i9A==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.6" } }, "node_modules/ts-api-utils": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz", - "integrity": "sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", + "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", "dev": true, "license": "MIT", "engines": { - "node": ">=16" + "node": ">=18.12" }, "peerDependencies": { - "typescript": ">=4.2.0" + "typescript": ">=4.8.4" } }, "node_modules/ts-command-line-args": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/ts-command-line-args/-/ts-command-line-args-2.3.1.tgz", - "integrity": "sha512-FR3y7pLl/fuUNSmnPhfLArGqRrpojQgIEEOVzYx9DhTmfIN7C9RWSfpkJEF4J+Gk7aVx5pak8I7vWZsaN4N84g==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/ts-command-line-args/-/ts-command-line-args-2.5.1.tgz", + "integrity": "sha512-H69ZwTw3rFHb5WYpQya40YAX2/w7Ut75uUECbgBIsLmM+BNuYnxsltfyyLMxy6sEeKxgijLTnQtLd0nKd6+IYw==", "dev": true, + "license": "ISC", "dependencies": { "chalk": "^4.1.0", "command-line-args": "^5.1.1", @@ -11327,6 +12233,7 @@ "resolved": "https://registry.npmjs.org/ts-essentials/-/ts-essentials-7.0.3.tgz", "integrity": "sha512-8+gr5+lqO3G84KdiTSMRLtuyJ+nTBVRKuCrK4lidMPdVeEp0uqC875uE5NMcaA7YYMN7XsNiFQuMvasF8HT/xQ==", "dev": true, + "license": "MIT", "peerDependencies": { "typescript": ">=3.7.0" } @@ -11335,6 +12242,7 @@ "version": "10.9.2", "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", + "license": "MIT", "dependencies": { "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", @@ -11373,6 +12281,15 @@ } } }, + "node_modules/ts-node/node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, "node_modules/tsconfig-paths": { "version": "3.15.0", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", @@ -11395,17 +12312,8 @@ "node_modules/tsort": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/tsort/-/tsort-0.0.1.tgz", - "integrity": "sha512-Tyrf5mxF8Ofs1tNoxA13lFeZ2Zrbd6cKbuH3V+MQ5sb6DtBj5FjrXVsRWT8YvNAQTqNoz66dz1WsbigI22aEnw==" - }, - "node_modules/tweetnacl": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", - "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==" - }, - "node_modules/tweetnacl-util": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/tweetnacl-util/-/tweetnacl-util-0.15.1.tgz", - "integrity": "sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw==" + "integrity": "sha512-Tyrf5mxF8Ofs1tNoxA13lFeZ2Zrbd6cKbuH3V+MQ5sb6DtBj5FjrXVsRWT8YvNAQTqNoz66dz1WsbigI22aEnw==", + "license": "MIT" }, "node_modules/type-check": { "version": "0.4.0", @@ -11434,6 +12342,7 @@ "version": "0.20.2", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=10" }, @@ -11446,6 +12355,7 @@ "resolved": "https://registry.npmjs.org/typechain/-/typechain-8.3.2.tgz", "integrity": "sha512-x/sQYr5w9K7yv3es7jo4KTX05CLxOf7TRWwoHlrjRh8H82G64g+k7VuWPJlgMo6qrjfCulOdfBjiaDtmhFYD/Q==", "dev": true, + "license": "MIT", "dependencies": { "@types/prettier": "^2.1.1", "debug": "^4.3.1", @@ -11465,11 +12375,23 @@ "typescript": ">=4.3.0" } }, + "node_modules/typechain/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, "node_modules/typechain/node_modules/fs-extra": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", "dev": true, + "license": "MIT", "dependencies": { "graceful-fs": "^4.1.2", "jsonfile": "^4.0.0", @@ -11483,7 +12405,9 @@ "version": "7.1.7", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, + "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -11499,6 +12423,42 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/typechain/node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "dev": true, + "license": "MIT", + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/typechain/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/typechain/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/typechain/node_modules/prettier": { "version": "2.8.8", "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", @@ -11515,33 +12475,43 @@ "url": "https://github.com/prettier/prettier?sponsor=1" } }, + "node_modules/typechain/node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4.0.0" + } + }, "node_modules/typed-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", - "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bound": "^1.0.3", "es-errors": "^1.3.0", - "is-typed-array": "^1.1.13" + "is-typed-array": "^1.1.14" }, "engines": { "node": ">= 0.4" } }, "node_modules/typed-array-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", - "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", + "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13" + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.14" }, "engines": { "node": ">= 0.4" @@ -11551,19 +12521,19 @@ } }, "node_modules/typed-array-byte-offset": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.3.tgz", - "integrity": "sha512-GsvTyUHTriq6o/bHcTd0vM7OQ9JEdlvluu9YISaA7+KzDzPaIzEeDFNkTfhdE3MYcNhNi0vq/LlegYgIs5yPAw==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", + "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", "dev": true, "license": "MIT", "dependencies": { "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", + "call-bind": "^1.0.8", "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13", - "reflect.getprototypeof": "^1.0.6" + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.15", + "reflect.getprototypeof": "^1.0.9" }, "engines": { "node": ">= 0.4" @@ -11594,9 +12564,9 @@ } }, "node_modules/typescript": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.2.tgz", - "integrity": "sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==", + "version": "5.8.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", + "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", @@ -11611,15 +12581,17 @@ "resolved": "https://registry.npmjs.org/typical/-/typical-4.0.0.tgz", "integrity": "sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/uglify-js": { - "version": "3.18.0", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.18.0.tgz", - "integrity": "sha512-SyVVbcNBCk0dzr9XL/R/ySrmYf0s372K6/hFklzgcp2lBFyXtw4I7BOdDjlLhE1aVqaI/SHWXWmYdlZxuyF38A==", + "version": "3.19.3", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", + "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", "dev": true, + "license": "BSD-2-Clause", "optional": true, "bin": { "uglifyjs": "bin/uglifyjs" @@ -11629,25 +12601,29 @@ } }, "node_modules/unbox-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", - "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", + "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", + "call-bound": "^1.0.3", "has-bigints": "^1.0.2", - "has-symbols": "^1.0.3", - "which-boxed-primitive": "^1.0.2" + "has-symbols": "^1.1.0", + "which-boxed-primitive": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/undici": { - "version": "5.28.4", - "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.4.tgz", - "integrity": "sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==", + "version": "5.29.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.29.0.tgz", + "integrity": "sha512-raqeBD6NQK4SkWhQzeYKd1KmIG6dllBOTt55Rmkt4HtI9mwdWtJljnrXjAFUBLTSN67HWrOIZ3EPF4kjUw80Bg==", + "license": "MIT", "dependencies": { "@fastify/busboy": "^2.0.0" }, @@ -11656,65 +12632,85 @@ } }, "node_modules/undici-types": { - "version": "6.19.8", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", - "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", "license": "MIT" }, "node_modules/universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "license": "MIT", "engines": { - "node": ">= 4.0.0" + "node": ">= 10.0.0" } }, "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", "engines": { "node": ">= 0.8" } }, + "node_modules/unrs-resolver": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.5.0.tgz", + "integrity": "sha512-6aia3Oy7SEe0MuUGQm2nsyob0L2+g57w178K5SE/3pvSGAIp28BB2O921fKx424Ahc/gQ6v0DXFbhcpyhGZdOA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/JounQin" + }, + "optionalDependencies": { + "@unrs/resolver-binding-darwin-arm64": "1.5.0", + "@unrs/resolver-binding-darwin-x64": "1.5.0", + "@unrs/resolver-binding-freebsd-x64": "1.5.0", + "@unrs/resolver-binding-linux-arm-gnueabihf": "1.5.0", + "@unrs/resolver-binding-linux-arm-musleabihf": "1.5.0", + "@unrs/resolver-binding-linux-arm64-gnu": "1.5.0", + "@unrs/resolver-binding-linux-arm64-musl": "1.5.0", + "@unrs/resolver-binding-linux-ppc64-gnu": "1.5.0", + "@unrs/resolver-binding-linux-riscv64-gnu": "1.5.0", + "@unrs/resolver-binding-linux-s390x-gnu": "1.5.0", + "@unrs/resolver-binding-linux-x64-gnu": "1.5.0", + "@unrs/resolver-binding-linux-x64-musl": "1.5.0", + "@unrs/resolver-binding-wasm32-wasi": "1.5.0", + "@unrs/resolver-binding-win32-arm64-msvc": "1.5.0", + "@unrs/resolver-binding-win32-ia32-msvc": "1.5.0", + "@unrs/resolver-binding-win32-x64-msvc": "1.5.0" + } + }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "punycode": "^2.1.0" } }, - "node_modules/utf-8-validate": { - "version": "5.0.9", - "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.9.tgz", - "integrity": "sha512-Yek7dAy0v3Kl0orwMlvi7TPtiCNrdfHNd7Gcc/pLq4BLXqfAmd0J7OWMizUQnTTJsyjKn02mU7anqwfmUP4J8Q==", - "hasInstallScript": true, - "optional": true, - "peer": true, - "dependencies": { - "node-gyp-build": "^4.3.0" - }, - "engines": { - "node": ">=6.14.2" - } - }, "node_modules/utf8": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/utf8/-/utf8-3.0.0.tgz", "integrity": "sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" }, "node_modules/uuid": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "license": "MIT", "bin": { "uuid": "dist/bin/uuid" } @@ -11722,25 +12718,89 @@ "node_modules/v8-compile-cache-lib": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", - "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==" + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "license": "MIT" + }, + "node_modules/viem": { + "version": "2.27.2", + "resolved": "https://registry.npmjs.org/viem/-/viem-2.27.2.tgz", + "integrity": "sha512-VwsB+RswcflbwBNPMvzTHuafDA51iT8v4SuIFcudTP2skmxcdodbgoOLP4dYELVnCzcedxoSJDOeext4V3zdnA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/wevm" + } + ], + "license": "MIT", + "dependencies": { + "@noble/curves": "1.8.1", + "@noble/hashes": "1.7.1", + "@scure/bip32": "1.6.2", + "@scure/bip39": "1.5.4", + "abitype": "1.0.8", + "isows": "1.0.6", + "ox": "0.6.9", + "ws": "8.18.1" + }, + "peerDependencies": { + "typescript": ">=5.0.4" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/viem/node_modules/@noble/curves": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.8.1.tgz", + "integrity": "sha512-warwspo+UYUPep0Q+vtdVB4Ugn8GGQj8iyB3gnRWsztmUHTI3S1nhdiWNsPUGL0vud7JlRRk1XEu7Lq1KGTnMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.7.1" + }, + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/viem/node_modules/@noble/hashes": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.7.1.tgz", + "integrity": "sha512-B8XBPsn4vT/KJAGqDzbwztd+6Yte3P4V7iafm24bxgDe/mlRuK6xmWPuCNrKt2vDafZ8MfJLlchDG/vYafQEjQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } }, "node_modules/web-streams-polyfill": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz", - "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", + "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", + "license": "MIT", "engines": { "node": ">= 8" } }, "node_modules/web3-utils": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.10.0.tgz", - "integrity": "sha512-kSaCM0uMcZTNUSmn5vMEhlo02RObGNRRCkdX0V9UTAU0+lrvn0HSaudyCo6CQzuXUsnuY2ERJGCGPfeWmv19Rg==", + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.10.4.tgz", + "integrity": "sha512-tsu8FiKJLk2PzhDl9fXbGUWTkkVXYhtTA+SmEFkKft+9BgwLxfCRpU96sWv7ICC8zixBNd3JURVoiR3dUXgP8A==", "dev": true, + "license": "LGPL-3.0", "dependencies": { + "@ethereumjs/util": "^8.1.0", "bn.js": "^5.2.1", "ethereum-bloom-filters": "^1.0.6", - "ethereumjs-util": "^7.1.0", + "ethereum-cryptography": "^2.1.2", "ethjs-unit": "0.1.6", "number-to-bn": "1.7.0", "randombytes": "^2.1.0", @@ -11750,61 +12810,168 @@ "node": ">=8.0.0" } }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "node_modules/web3-utils/node_modules/@ethereumjs/rlp": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@ethereumjs/rlp/-/rlp-4.0.1.tgz", + "integrity": "sha512-tqsQiBQDQdmPWE1xkkBq4rlSW5QZpLOUJ5RJh2/9fug+q9tnUhuZoVLk7s0scUIKTOzEtR72DFBXI4WiZcMpvw==", "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, + "license": "MPL-2.0", "bin": { - "node-which": "bin/node-which" + "rlp": "bin/rlp" }, "engines": { - "node": ">= 8" + "node": ">=14" } }, - "node_modules/which-boxed-primitive": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.0.tgz", - "integrity": "sha512-Ei7Miu/AXe2JJ4iNF5j/UphAgRoma4trE6PtisM09bPygb3egMH3YLW/befsWb1A1AxvNSFidOFTB18XtnIIng==", + "node_modules/web3-utils/node_modules/@ethereumjs/util": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/@ethereumjs/util/-/util-8.1.0.tgz", + "integrity": "sha512-zQ0IqbdX8FZ9aw11vP+dZkKDkS+kgIvQPHnSAXzP9pLu+Rfu3D3XEeLbicvoXJTYnhZiPmsZUxgdzXwNKxRPbA==", "dev": true, - "license": "MIT", + "license": "MPL-2.0", "dependencies": { - "is-bigint": "^1.1.0", - "is-boolean-object": "^1.2.0", - "is-number-object": "^1.1.0", - "is-string": "^1.1.0", - "is-symbol": "^1.1.0" + "@ethereumjs/rlp": "^4.0.1", + "ethereum-cryptography": "^2.0.0", + "micro-ftch": "^0.3.1" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=14" } }, - "node_modules/which-builtin-type": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.0.tgz", - "integrity": "sha512-I+qLGQ/vucCby4tf5HsLmGueEla4ZhwTBSqaooS+Y0BuxN4Cp+okmGuV+8mXZ84KDI9BA+oklo+RzKg0ONdSUA==", + "node_modules/web3-utils/node_modules/@noble/curves": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.4.2.tgz", + "integrity": "sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw==", "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.7", - "function.prototype.name": "^1.1.6", - "has-tostringtag": "^1.0.2", - "is-async-function": "^2.0.0", - "is-date-object": "^1.0.5", - "is-finalizationregistry": "^1.1.0", - "is-generator-function": "^1.0.10", - "is-regex": "^1.1.4", + "@noble/hashes": "1.4.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/web3-utils/node_modules/@noble/hashes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", + "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/web3-utils/node_modules/@scure/base": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.9.tgz", + "integrity": "sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/web3-utils/node_modules/@scure/bip32": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.4.0.tgz", + "integrity": "sha512-sVUpc0Vq3tXCkDGYVWGIZTRfnvu8LoTDaev7vbwh0omSvVORONr960MQWdKqJDCReIEmTj3PAr73O3aoxz7OPg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@noble/curves": "~1.4.0", + "@noble/hashes": "~1.4.0", + "@scure/base": "~1.1.6" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/web3-utils/node_modules/@scure/bip39": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.3.0.tgz", + "integrity": "sha512-disdg7gHuTDZtY+ZdkmLpPCk7fxZSu3gBiEGuoC1XYxv9cGx3Z6cpTggCgW6odSOOIXCiDjuGejW+aJKCY/pIQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@noble/hashes": "~1.4.0", + "@scure/base": "~1.1.6" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/web3-utils/node_modules/ethereum-cryptography": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.2.1.tgz", + "integrity": "sha512-r/W8lkHSiTLxUxW8Rf3u4HGB0xQweG2RyETjywylKZSzLWoWAijRz8WCuOtJ6wah+avllXBqZuk29HCCvhEIRg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@noble/curves": "1.4.2", + "@noble/hashes": "1.4.0", + "@scure/bip32": "1.4.0", + "@scure/bip39": "1.3.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", + "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-bigint": "^1.1.0", + "is-boolean-object": "^1.2.1", + "is-number-object": "^1.1.1", + "is-string": "^1.1.1", + "is-symbol": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", + "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", + "is-async-function": "^2.0.0", + "is-date-object": "^1.1.0", + "is-finalizationregistry": "^1.1.0", + "is-generator-function": "^1.0.10", + "is-regex": "^1.2.1", "is-weakref": "^1.0.2", "isarray": "^2.0.5", - "which-boxed-primitive": "^1.0.2", + "which-boxed-primitive": "^1.1.0", "which-collection": "^1.0.2", - "which-typed-array": "^1.1.15" + "which-typed-array": "^1.1.16" }, "engines": { "node": ">= 0.4" @@ -11833,16 +13000,18 @@ } }, "node_modules/which-typed-array": { - "version": "1.1.16", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.16.tgz", - "integrity": "sha512-g+N+GAWiRj66DngFwHvISJd+ITsyphZvD1vChfVg6cEdnzy53GzB3oy0fUNlvhz7H7+MiqhYr26qxQShCpKTTQ==", + "version": "1.1.19", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz", + "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==", "dev": true, "license": "MIT", "dependencies": { "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", "has-tostringtag": "^1.0.2" }, "engines": { @@ -11856,6 +13025,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", + "license": "MIT", "dependencies": { "string-width": "^4.0.0" }, @@ -11868,6 +13038,7 @@ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -11876,13 +13047,15 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/wordwrapjs": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/wordwrapjs/-/wordwrapjs-4.0.1.tgz", "integrity": "sha512-kKlNACbvHrkpIw6oPeYDSmdCTu2hdMHoyXLTcUKala++lx5Y+wjJ/e474Jqv5abnVmwxw08DiTuHmw69lJGksA==", "dev": true, + "license": "MIT", "dependencies": { "reduce-flatten": "^2.0.0", "typical": "^5.2.0" @@ -11896,19 +13069,22 @@ "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/workerpool": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", - "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==" + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.5.1.tgz", + "integrity": "sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==", + "license": "Apache-2.0" }, "node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -11943,12 +13119,13 @@ "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC" }, "node_modules/ws": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", - "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.1.tgz", + "integrity": "sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w==", "license": "MIT", "engines": { "node": ">=10.0.0" @@ -11970,6 +13147,7 @@ "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "license": "ISC", "engines": { "node": ">=10" } @@ -11978,12 +13156,13 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/yaml": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.1.tgz", - "integrity": "sha512-7r0XPzioN/Q9kXBro/XPnA6kznR73DHq+GXh5ON7ZozRO6aMjbmiBuKste2wslTFkC5d1dw0GooOCepZXJ2SAg==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.7.1.tgz", + "integrity": "sha512-10ULxpnOCQXxJvBgxsn9ptjq6uviG/htZKk9veJGhlqn3w/DxQ631zFF+nlQXLwmImeS5amR2dl2U8sg6U9jsQ==", "dev": true, "license": "ISC", "bin": { @@ -11997,6 +13176,7 @@ "version": "16.2.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "license": "MIT", "dependencies": { "cliui": "^7.0.2", "escalade": "^3.1.1", @@ -12011,9 +13191,10 @@ } }, "node_modules/yargs-parser": { - "version": "20.2.4", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "license": "ISC", "engines": { "node": ">=10" } @@ -12022,6 +13203,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", + "license": "MIT", "dependencies": { "camelcase": "^6.0.0", "decamelize": "^4.0.0", @@ -12032,18 +13214,11 @@ "node": ">=10" } }, - "node_modules/yargs-unparser/node_modules/is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", - "engines": { - "node": ">=8" - } - }, "node_modules/yn": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "license": "MIT", "engines": { "node": ">=6" } @@ -12052,6 +13227,7 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "license": "MIT", "engines": { "node": ">=10" }, @@ -12074,10 +13250,10 @@ "ethers": "~5.7.0" } }, - "node_modules/zksync-ethers/node_modules/ethers": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.7.2.tgz", - "integrity": "sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg==", + "node_modules/zksync-ethers/node_modules/@ethersproject/abi": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.7.0.tgz", + "integrity": "sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA==", "funding": [ { "type": "individual", @@ -12090,140 +13266,6 @@ ], "license": "MIT", "dependencies": { - "@ethersproject/abi": "5.7.0", - "@ethersproject/abstract-provider": "5.7.0", - "@ethersproject/abstract-signer": "5.7.0", - "@ethersproject/address": "5.7.0", - "@ethersproject/base64": "5.7.0", - "@ethersproject/basex": "5.7.0", - "@ethersproject/bignumber": "5.7.0", - "@ethersproject/bytes": "5.7.0", - "@ethersproject/constants": "5.7.0", - "@ethersproject/contracts": "5.7.0", - "@ethersproject/hash": "5.7.0", - "@ethersproject/hdnode": "5.7.0", - "@ethersproject/json-wallets": "5.7.0", - "@ethersproject/keccak256": "5.7.0", - "@ethersproject/logger": "5.7.0", - "@ethersproject/networks": "5.7.1", - "@ethersproject/pbkdf2": "5.7.0", - "@ethersproject/properties": "5.7.0", - "@ethersproject/providers": "5.7.2", - "@ethersproject/random": "5.7.0", - "@ethersproject/rlp": "5.7.0", - "@ethersproject/sha2": "5.7.0", - "@ethersproject/signing-key": "5.7.0", - "@ethersproject/solidity": "5.7.0", - "@ethersproject/strings": "5.7.0", - "@ethersproject/transactions": "5.7.0", - "@ethersproject/units": "5.7.0", - "@ethersproject/wallet": "5.7.0", - "@ethersproject/web": "5.7.1", - "@ethersproject/wordlists": "5.7.0" - } - } - }, - "dependencies": { - "@adraffy/ens-normalize": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.0.tgz", - "integrity": "sha512-nA9XHtlAkYfJxY7bce8DcN7eKxWWCWkU+1GR9d+U6MbNpfwQp8TI7vqOsBsMcHoT4mBu2kypKoSKnghEzOOq5Q==", - "dev": true - }, - "@babel/code-frame": { - "version": "7.26.2", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", - "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.25.9", - "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" - } - }, - "@babel/helper-validator-identifier": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", - "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", - "dev": true - }, - "@colors/colors": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", - "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", - "dev": true, - "optional": true - }, - "@cspotcode/source-map-support": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", - "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", - "requires": { - "@jridgewell/trace-mapping": "0.3.9" - } - }, - "@digitalbazaar/http-client": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@digitalbazaar/http-client/-/http-client-3.2.0.tgz", - "integrity": "sha512-NhYXcWE/JDE7AnJikNX7q0S6zNuUPA2NuIoRdUpmvHlarjmRqyr6hIO3Awu2FxlUzbdiI1uzuWrZyB9mD1tTvw==", - "dev": true, - "requires": { - "ky": "^0.30.0", - "ky-universal": "^0.10.1", - "undici": "^5.2.0" - } - }, - "@eslint-community/eslint-utils": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz", - "integrity": "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^3.4.3" - } - }, - "@eslint-community/regexpp": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", - "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", - "dev": true - }, - "@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", - "dev": true, - "requires": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "dependencies": { - "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true - } - } - }, - "@eslint/js": { - "version": "8.57.1", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", - "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", - "dev": true - }, - "@ethersproject/abi": { - "version": "5.7.0", - "resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.7.0.tgz", - "integrity": "sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA==", - "requires": { "@ethersproject/address": "^5.7.0", "@ethersproject/bignumber": "^5.7.0", "@ethersproject/bytes": "^5.7.0", @@ -12235,25 +13277,47 @@ "@ethersproject/strings": "^5.7.0" } }, - "@ethersproject/abstract-provider": { + "node_modules/zksync-ethers/node_modules/@ethersproject/abstract-provider": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.7.0.tgz", "integrity": "sha512-R41c9UkchKCpAqStMYUpdunjo3pkEvZC3FAwZn5S5MGbXoMQOHIdHItezTETxAO5bevtMApSyEhn9+CHcDsWBw==", - "requires": { - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "@ethersproject/networks": "^5.7.0", - "@ethersproject/properties": "^5.7.0", - "@ethersproject/transactions": "^5.7.0", - "@ethersproject/web": "^5.7.0" - } - }, - "@ethersproject/abstract-signer": { - "version": "5.7.0", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/networks": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/transactions": "^5.7.0", + "@ethersproject/web": "^5.7.0" + } + }, + "node_modules/zksync-ethers/node_modules/@ethersproject/abstract-signer": { + "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.7.0.tgz", "integrity": "sha512-a16V8bq1/Cz+TGCkE2OPMTOUDLS3grCpdjoJCYNnVBbdYEMSgKrU0+B90s8b6H+ByYTBZN7a3g76jdIJi7UfKQ==", - "requires": { + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { "@ethersproject/abstract-provider": "^5.7.0", "@ethersproject/bignumber": "^5.7.0", "@ethersproject/bytes": "^5.7.0", @@ -12261,11 +13325,22 @@ "@ethersproject/properties": "^5.7.0" } }, - "@ethersproject/address": { + "node_modules/zksync-ethers/node_modules/@ethersproject/address": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.7.0.tgz", "integrity": "sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA==", - "requires": { + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { "@ethersproject/bignumber": "^5.7.0", "@ethersproject/bytes": "^5.7.0", "@ethersproject/keccak256": "^5.7.0", @@ -12273,54 +13348,120 @@ "@ethersproject/rlp": "^5.7.0" } }, - "@ethersproject/base64": { + "node_modules/zksync-ethers/node_modules/@ethersproject/base64": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.7.0.tgz", "integrity": "sha512-Dr8tcHt2mEbsZr/mwTPIQAf3Ai0Bks/7gTw9dSqk1mQvhW3XvRlmDJr/4n+wg1JmCl16NZue17CDh8xb/vZ0sQ==", - "requires": { + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { "@ethersproject/bytes": "^5.7.0" } }, - "@ethersproject/basex": { + "node_modules/zksync-ethers/node_modules/@ethersproject/basex": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/basex/-/basex-5.7.0.tgz", "integrity": "sha512-ywlh43GwZLv2Voc2gQVTKBoVQ1mti3d8HK5aMxsfu/nRDnMmNqaSJ3r3n85HBByT8OpoY96SXM1FogC533T4zw==", - "requires": { + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { "@ethersproject/bytes": "^5.7.0", "@ethersproject/properties": "^5.7.0" } }, - "@ethersproject/bignumber": { + "node_modules/zksync-ethers/node_modules/@ethersproject/bignumber": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.7.0.tgz", "integrity": "sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw==", - "requires": { + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { "@ethersproject/bytes": "^5.7.0", "@ethersproject/logger": "^5.7.0", "bn.js": "^5.2.1" } }, - "@ethersproject/bytes": { + "node_modules/zksync-ethers/node_modules/@ethersproject/bytes": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.7.0.tgz", "integrity": "sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A==", - "requires": { + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { "@ethersproject/logger": "^5.7.0" } }, - "@ethersproject/constants": { + "node_modules/zksync-ethers/node_modules/@ethersproject/constants": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.7.0.tgz", "integrity": "sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA==", - "requires": { + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { "@ethersproject/bignumber": "^5.7.0" } }, - "@ethersproject/contracts": { + "node_modules/zksync-ethers/node_modules/@ethersproject/contracts": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/contracts/-/contracts-5.7.0.tgz", "integrity": "sha512-5GJbzEU3X+d33CdfPhcyS+z8MzsTrBGk/sc+G+59+tPa9yFkl6HQ9D6L0QMgNTA9q8dT0XKxxkyp883XsQvbbg==", - "requires": { + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { "@ethersproject/abi": "^5.7.0", "@ethersproject/abstract-provider": "^5.7.0", "@ethersproject/abstract-signer": "^5.7.0", @@ -12333,11 +13474,22 @@ "@ethersproject/transactions": "^5.7.0" } }, - "@ethersproject/hash": { + "node_modules/zksync-ethers/node_modules/@ethersproject/hash": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.7.0.tgz", "integrity": "sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g==", - "requires": { + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { "@ethersproject/abstract-signer": "^5.7.0", "@ethersproject/address": "^5.7.0", "@ethersproject/base64": "^5.7.0", @@ -12349,11 +13501,22 @@ "@ethersproject/strings": "^5.7.0" } }, - "@ethersproject/hdnode": { + "node_modules/zksync-ethers/node_modules/@ethersproject/hdnode": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/hdnode/-/hdnode-5.7.0.tgz", "integrity": "sha512-OmyYo9EENBPPf4ERhR7oj6uAtUAhYGqOnIS+jE5pTXvdKBS99ikzq1E7Iv0ZQZ5V36Lqx1qZLeak0Ra16qpeOg==", - "requires": { + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { "@ethersproject/abstract-signer": "^5.7.0", "@ethersproject/basex": "^5.7.0", "@ethersproject/bignumber": "^5.7.0", @@ -12368,11 +13531,22 @@ "@ethersproject/wordlists": "^5.7.0" } }, - "@ethersproject/json-wallets": { + "node_modules/zksync-ethers/node_modules/@ethersproject/json-wallets": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/json-wallets/-/json-wallets-5.7.0.tgz", "integrity": "sha512-8oee5Xgu6+RKgJTkvEMl2wDgSPSAQ9MB/3JYjFV9jlKvcYHUXZC+cQp0njgmxdHkYWn8s6/IqIZYm0YWCjO/0g==", - "requires": { + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { "@ethersproject/abstract-signer": "^5.7.0", "@ethersproject/address": "^5.7.0", "@ethersproject/bytes": "^5.7.0", @@ -12388,50 +13562,116 @@ "scrypt-js": "3.0.1" } }, - "@ethersproject/keccak256": { + "node_modules/zksync-ethers/node_modules/@ethersproject/keccak256": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.7.0.tgz", "integrity": "sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg==", - "requires": { + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { "@ethersproject/bytes": "^5.7.0", "js-sha3": "0.8.0" } }, - "@ethersproject/logger": { + "node_modules/zksync-ethers/node_modules/@ethersproject/logger": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.7.0.tgz", - "integrity": "sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig==" + "integrity": "sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT" }, - "@ethersproject/networks": { + "node_modules/zksync-ethers/node_modules/@ethersproject/networks": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.7.1.tgz", "integrity": "sha512-n/MufjFYv3yFcUyfhnXotyDlNdFb7onmkSy8aQERi2PjNcnWQ66xXxa3XlS8nCcA8aJKJjIIMNJTC7tu80GwpQ==", - "requires": { + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { "@ethersproject/logger": "^5.7.0" } }, - "@ethersproject/pbkdf2": { + "node_modules/zksync-ethers/node_modules/@ethersproject/pbkdf2": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/pbkdf2/-/pbkdf2-5.7.0.tgz", "integrity": "sha512-oR/dBRZR6GTyaofd86DehG72hY6NpAjhabkhxgr3X2FpJtJuodEl2auADWBZfhDHgVCbu3/H/Ocq2uC6dpNjjw==", - "requires": { + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { "@ethersproject/bytes": "^5.7.0", "@ethersproject/sha2": "^5.7.0" } }, - "@ethersproject/properties": { + "node_modules/zksync-ethers/node_modules/@ethersproject/properties": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.7.0.tgz", "integrity": "sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw==", - "requires": { + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { "@ethersproject/logger": "^5.7.0" } }, - "@ethersproject/providers": { + "node_modules/zksync-ethers/node_modules/@ethersproject/providers": { "version": "5.7.2", "resolved": "https://registry.npmjs.org/@ethersproject/providers/-/providers-5.7.2.tgz", "integrity": "sha512-g34EWZ1WWAVgr4aptGlVBF8mhl3VWjv+8hoAnzStu8Ah22VHBsuGzP17eb6xDVRzw895G4W7vvx60lFFur/1Rg==", - "requires": { + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { "@ethersproject/abstract-provider": "^5.7.0", "@ethersproject/abstract-signer": "^5.7.0", "@ethersproject/address": "^5.7.0", @@ -12452,49 +13692,85 @@ "@ethersproject/web": "^5.7.0", "bech32": "1.1.4", "ws": "7.4.6" - }, - "dependencies": { - "ws": { - "version": "7.4.6", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz", - "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==", - "requires": {} - } } }, - "@ethersproject/random": { + "node_modules/zksync-ethers/node_modules/@ethersproject/random": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/random/-/random-5.7.0.tgz", "integrity": "sha512-19WjScqRA8IIeWclFme75VMXSBvi4e6InrUNuaR4s5pTF2qNhcGdCUwdxUVGtDDqC00sDLCO93jPQoDUH4HVmQ==", - "requires": { + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { "@ethersproject/bytes": "^5.7.0", "@ethersproject/logger": "^5.7.0" } }, - "@ethersproject/rlp": { + "node_modules/zksync-ethers/node_modules/@ethersproject/rlp": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.7.0.tgz", "integrity": "sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w==", - "requires": { + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { "@ethersproject/bytes": "^5.7.0", "@ethersproject/logger": "^5.7.0" } }, - "@ethersproject/sha2": { + "node_modules/zksync-ethers/node_modules/@ethersproject/sha2": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/sha2/-/sha2-5.7.0.tgz", "integrity": "sha512-gKlH42riwb3KYp0reLsFTokByAKoJdgFCwI+CCiX/k+Jm2mbNs6oOaCjYQSlI1+XBVejwH2KrmCbMAT/GnRDQw==", - "requires": { - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/logger": "^5.7.0", - "hash.js": "1.1.7" + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "hash.js": "1.1.7" } }, - "@ethersproject/signing-key": { + "node_modules/zksync-ethers/node_modules/@ethersproject/signing-key": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.7.0.tgz", "integrity": "sha512-MZdy2nL3wO0u7gkB4nA/pEf8lu1TlFswPNmy8AiYkfKTdO6eXBJyUdmHO/ehm/htHw9K/qF8ujnTyUAD+Ry54Q==", - "requires": { + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { "@ethersproject/bytes": "^5.7.0", "@ethersproject/logger": "^5.7.0", "@ethersproject/properties": "^5.7.0", @@ -12503,11 +13779,22 @@ "hash.js": "1.1.7" } }, - "@ethersproject/solidity": { + "node_modules/zksync-ethers/node_modules/@ethersproject/solidity": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/solidity/-/solidity-5.7.0.tgz", "integrity": "sha512-HmabMd2Dt/raavyaGukF4XxizWKhKQ24DoLtdNbBmNKUOPqwjsKQSdV9GQtj9CBEea9DlzETlVER1gYeXXBGaA==", - "requires": { + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { "@ethersproject/bignumber": "^5.7.0", "@ethersproject/bytes": "^5.7.0", "@ethersproject/keccak256": "^5.7.0", @@ -12516,21 +13803,43 @@ "@ethersproject/strings": "^5.7.0" } }, - "@ethersproject/strings": { + "node_modules/zksync-ethers/node_modules/@ethersproject/strings": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.7.0.tgz", "integrity": "sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg==", - "requires": { + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { "@ethersproject/bytes": "^5.7.0", "@ethersproject/constants": "^5.7.0", "@ethersproject/logger": "^5.7.0" } }, - "@ethersproject/transactions": { + "node_modules/zksync-ethers/node_modules/@ethersproject/transactions": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.7.0.tgz", "integrity": "sha512-kmcNicCp1lp8qanMTC3RIikGgoJ80ztTyvtsFvCYpSCfkjhD0jZ2LOrnbcuxuToLIUYYf+4XwD1rP+B/erDIhQ==", - "requires": { + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { "@ethersproject/address": "^5.7.0", "@ethersproject/bignumber": "^5.7.0", "@ethersproject/bytes": "^5.7.0", @@ -12542,21 +13851,43 @@ "@ethersproject/signing-key": "^5.7.0" } }, - "@ethersproject/units": { + "node_modules/zksync-ethers/node_modules/@ethersproject/units": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/units/-/units-5.7.0.tgz", "integrity": "sha512-pD3xLMy3SJu9kG5xDGI7+xhTEmGXlEqXU4OfNapmfnxLVY4EMSSRp7j1k7eezutBPH7RBN/7QPnwR7hzNlEFeg==", - "requires": { + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { "@ethersproject/bignumber": "^5.7.0", "@ethersproject/constants": "^5.7.0", "@ethersproject/logger": "^5.7.0" } }, - "@ethersproject/wallet": { + "node_modules/zksync-ethers/node_modules/@ethersproject/wallet": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/wallet/-/wallet-5.7.0.tgz", "integrity": "sha512-MhmXlJXEJFBFVKrDLB4ZdDzxcBxQ3rLyCkhNqVu3CDYvR97E+8r01UgrI+TI99Le+aYm/in/0vp86guJuM7FCA==", - "requires": { + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { "@ethersproject/abstract-provider": "^5.7.0", "@ethersproject/abstract-signer": "^5.7.0", "@ethersproject/address": "^5.7.0", @@ -12574,11 +13905,22 @@ "@ethersproject/wordlists": "^5.7.0" } }, - "@ethersproject/web": { + "node_modules/zksync-ethers/node_modules/@ethersproject/web": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.7.1.tgz", "integrity": "sha512-Gueu8lSvyjBWL4cYsWsjh6MtMwM0+H4HvqFPZfB6dV8ctbP9zFAO73VG1cMWae0FLPCtz0peKPpZY8/ugJJX2w==", - "requires": { + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { "@ethersproject/base64": "^5.7.0", "@ethersproject/bytes": "^5.7.0", "@ethersproject/logger": "^5.7.0", @@ -12586,11 +13928,22 @@ "@ethersproject/strings": "^5.7.0" } }, - "@ethersproject/wordlists": { + "node_modules/zksync-ethers/node_modules/@ethersproject/wordlists": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/wordlists/-/wordlists-5.7.0.tgz", "integrity": "sha512-S2TFNJNfHWVHNE6cNDjbVlZ6MgE17MIxMbMg2zv3wn+3XSJGosL1m9ZVv3GXCf/2ymSsQ+hRI5IzoMJTG6aoVA==", - "requires": { + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { "@ethersproject/bytes": "^5.7.0", "@ethersproject/hash": "^5.7.0", "@ethersproject/logger": "^5.7.0", @@ -12598,7852 +13951,99 @@ "@ethersproject/strings": "^5.7.0" } }, - "@fastify/busboy": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.0.0.tgz", - "integrity": "sha512-JUFJad5lv7jxj926GPgymrWQxxjPYuJNiNjNMzqT+HiuP6Vl3dk5xzG+8sTX96np0ZAluvaMzPsjhHZ5rNuNQQ==" - }, - "@humanwhocodes/config-array": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", - "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", - "dev": true, - "requires": { - "@humanwhocodes/object-schema": "^2.0.3", - "debug": "^4.3.1", - "minimatch": "^3.0.5" - } - }, - "@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true - }, - "@humanwhocodes/object-schema": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", - "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", - "dev": true + "node_modules/zksync-ethers/node_modules/aes-js": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.0.0.tgz", + "integrity": "sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw==", + "license": "MIT" }, - "@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "dev": true, - "requires": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, + "node_modules/zksync-ethers/node_modules/elliptic": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", + "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", + "license": "MIT", "dependencies": { - "ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", - "dev": true - }, - "ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true - }, - "emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true - }, - "string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, - "requires": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - } - }, - "strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "requires": { - "ansi-regex": "^6.0.1" - } - }, - "wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "dev": true, - "requires": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - } - } + "bn.js": "^4.11.9", + "brorand": "^1.1.0", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" } }, - "@jridgewell/resolve-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", - "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==" - }, - "@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" - }, - "@jridgewell/trace-mapping": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", - "requires": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" - } + "node_modules/zksync-ethers/node_modules/elliptic/node_modules/bn.js": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", + "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", + "license": "MIT" }, - "@metamask/eth-sig-util": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@metamask/eth-sig-util/-/eth-sig-util-4.0.1.tgz", - "integrity": "sha512-tghyZKLHZjcdlDqCA3gNZmLeR0XvOE9U1qoQO9ohyAZT6Pya+H9vkBPcsyXytmYLNgVoin7CKCmweo/R43V+tQ==", - "requires": { - "ethereumjs-abi": "^0.6.8", - "ethereumjs-util": "^6.2.1", - "ethjs-util": "^0.1.6", - "tweetnacl": "^1.0.3", - "tweetnacl-util": "^0.15.1" - }, - "dependencies": { - "@types/bn.js": { - "version": "4.11.6", - "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz", - "integrity": "sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==", - "requires": { - "@types/node": "*" - } - }, - "bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" - }, - "ethereum-cryptography": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", - "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", - "requires": { - "@types/pbkdf2": "^3.0.0", - "@types/secp256k1": "^4.0.1", - "blakejs": "^1.1.0", - "browserify-aes": "^1.2.0", - "bs58check": "^2.1.2", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "hash.js": "^1.1.7", - "keccak": "^3.0.0", - "pbkdf2": "^3.0.17", - "randombytes": "^2.1.0", - "safe-buffer": "^5.1.2", - "scrypt-js": "^3.0.0", - "secp256k1": "^4.0.1", - "setimmediate": "^1.0.5" - } + "node_modules/zksync-ethers/node_modules/ethers": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.7.2.tgz", + "integrity": "sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" }, - "ethereumjs-util": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz", - "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==", - "requires": { - "@types/bn.js": "^4.11.3", - "bn.js": "^4.11.0", - "create-hash": "^1.1.2", - "elliptic": "^6.5.2", - "ethereum-cryptography": "^0.1.3", - "ethjs-util": "0.1.6", - "rlp": "^2.2.3" - } + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" } - } - }, - "@noble/curves": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.4.0.tgz", - "integrity": "sha512-p+4cb332SFCrReJkCYe8Xzm0OWi4Jji5jVdIZRL/PmacmDkFNw6MrrV+gGpiPxLHbV+zKFRywUWbaseT+tZRXg==", - "requires": { - "@noble/hashes": "1.4.0" - }, + ], + "license": "MIT", "dependencies": { - "@noble/hashes": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", - "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==" - } - } - }, - "@noble/hashes": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.1.2.tgz", - "integrity": "sha512-KYRCASVTv6aeUi1tsF8/vpyR7zpfs3FUzy2Jqm+MU+LmUKhQ0y2FpfwqkCcxSg2ua4GALJd8k2R76WxwZGbQpA==" - }, - "@noble/secp256k1": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/@noble/secp256k1/-/secp256k1-1.6.3.tgz", - "integrity": "sha512-T04e4iTurVy7I8Sw4+c5OSN9/RkPlo1uKxAomtxQNLq8j1uPAqnsqG1bqvY3Jv7c13gyr6dui0zmh/I3+f/JaQ==" - }, - "@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - } - }, - "@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true - }, - "@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "requires": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" + "@ethersproject/abi": "5.7.0", + "@ethersproject/abstract-provider": "5.7.0", + "@ethersproject/abstract-signer": "5.7.0", + "@ethersproject/address": "5.7.0", + "@ethersproject/base64": "5.7.0", + "@ethersproject/basex": "5.7.0", + "@ethersproject/bignumber": "5.7.0", + "@ethersproject/bytes": "5.7.0", + "@ethersproject/constants": "5.7.0", + "@ethersproject/contracts": "5.7.0", + "@ethersproject/hash": "5.7.0", + "@ethersproject/hdnode": "5.7.0", + "@ethersproject/json-wallets": "5.7.0", + "@ethersproject/keccak256": "5.7.0", + "@ethersproject/logger": "5.7.0", + "@ethersproject/networks": "5.7.1", + "@ethersproject/pbkdf2": "5.7.0", + "@ethersproject/properties": "5.7.0", + "@ethersproject/providers": "5.7.2", + "@ethersproject/random": "5.7.0", + "@ethersproject/rlp": "5.7.0", + "@ethersproject/sha2": "5.7.0", + "@ethersproject/signing-key": "5.7.0", + "@ethersproject/solidity": "5.7.0", + "@ethersproject/strings": "5.7.0", + "@ethersproject/transactions": "5.7.0", + "@ethersproject/units": "5.7.0", + "@ethersproject/wallet": "5.7.0", + "@ethersproject/web": "5.7.1", + "@ethersproject/wordlists": "5.7.0" } }, - "@nolyfill/is-core-module": { - "version": "1.0.39", - "resolved": "https://registry.npmjs.org/@nolyfill/is-core-module/-/is-core-module-1.0.39.tgz", - "integrity": "sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==", - "dev": true - }, - "@nomicfoundation/edr": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr/-/edr-0.6.5.tgz", - "integrity": "sha512-tAqMslLP+/2b2sZP4qe9AuGxG3OkQ5gGgHE4isUuq6dUVjwCRPFhAOhpdFl+OjY5P3yEv3hmq9HjUGRa2VNjng==", - "requires": { - "@nomicfoundation/edr-darwin-arm64": "0.6.5", - "@nomicfoundation/edr-darwin-x64": "0.6.5", - "@nomicfoundation/edr-linux-arm64-gnu": "0.6.5", - "@nomicfoundation/edr-linux-arm64-musl": "0.6.5", - "@nomicfoundation/edr-linux-x64-gnu": "0.6.5", - "@nomicfoundation/edr-linux-x64-musl": "0.6.5", - "@nomicfoundation/edr-win32-x64-msvc": "0.6.5" - } - }, - "@nomicfoundation/edr-darwin-arm64": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-darwin-arm64/-/edr-darwin-arm64-0.6.5.tgz", - "integrity": "sha512-A9zCCbbNxBpLgjS1kEJSpqxIvGGAX4cYbpDYCU2f3jVqOwaZ/NU761y1SvuCRVpOwhoCXqByN9b7HPpHi0L4hw==" - }, - "@nomicfoundation/edr-darwin-x64": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-darwin-x64/-/edr-darwin-x64-0.6.5.tgz", - "integrity": "sha512-x3zBY/v3R0modR5CzlL6qMfFMdgwd6oHrWpTkuuXnPFOX8SU31qq87/230f4szM+ukGK8Hi+mNq7Ro2VF4Fj+w==" - }, - "@nomicfoundation/edr-linux-arm64-gnu": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-arm64-gnu/-/edr-linux-arm64-gnu-0.6.5.tgz", - "integrity": "sha512-HGpB8f1h8ogqPHTyUpyPRKZxUk2lu061g97dOQ/W4CxevI0s/qiw5DB3U3smLvSnBHKOzYS1jkxlMeGN01ky7A==" - }, - "@nomicfoundation/edr-linux-arm64-musl": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-arm64-musl/-/edr-linux-arm64-musl-0.6.5.tgz", - "integrity": "sha512-ESvJM5Y9XC03fZg9KaQg3Hl+mbx7dsSkTIAndoJS7X2SyakpL9KZpOSYrDk135o8s9P9lYJdPOyiq+Sh+XoCbQ==" - }, - "@nomicfoundation/edr-linux-x64-gnu": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-x64-gnu/-/edr-linux-x64-gnu-0.6.5.tgz", - "integrity": "sha512-HCM1usyAR1Ew6RYf5AkMYGvHBy64cPA5NMbaeY72r0mpKaH3txiMyydcHibByOGdQ8iFLWpyUdpl1egotw+Tgg==" - }, - "@nomicfoundation/edr-linux-x64-musl": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-linux-x64-musl/-/edr-linux-x64-musl-0.6.5.tgz", - "integrity": "sha512-nB2uFRyczhAvWUH7NjCsIO6rHnQrof3xcCe6Mpmnzfl2PYcGyxN7iO4ZMmRcQS7R1Y670VH6+8ZBiRn8k43m7A==" - }, - "@nomicfoundation/edr-win32-x64-msvc": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/@nomicfoundation/edr-win32-x64-msvc/-/edr-win32-x64-msvc-0.6.5.tgz", - "integrity": "sha512-B9QD/4DSSCFtWicO8A3BrsnitO1FPv7axB62wq5Q+qeJ50yJlTmyeGY3cw62gWItdvy2mh3fRM6L1LpnHiB77A==" - }, - "@nomicfoundation/ethereumjs-common": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-common/-/ethereumjs-common-4.0.4.tgz", - "integrity": "sha512-9Rgb658lcWsjiicr5GzNCjI1llow/7r0k50dLL95OJ+6iZJcVbi15r3Y0xh2cIO+zgX0WIHcbzIu6FeQf9KPrg==", - "requires": { - "@nomicfoundation/ethereumjs-util": "9.0.4" - } - }, - "@nomicfoundation/ethereumjs-rlp": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-rlp/-/ethereumjs-rlp-5.0.4.tgz", - "integrity": "sha512-8H1S3s8F6QueOc/X92SdrA4RDenpiAEqMg5vJH99kcQaCy/a3Q6fgseo75mgWlbanGJXSlAPtnCeG9jvfTYXlw==" - }, - "@nomicfoundation/ethereumjs-tx": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-tx/-/ethereumjs-tx-5.0.4.tgz", - "integrity": "sha512-Xjv8wAKJGMrP1f0n2PeyfFCCojHd7iS3s/Ab7qzF1S64kxZ8Z22LCMynArYsVqiFx6rzYy548HNVEyI+AYN/kw==", - "requires": { - "@nomicfoundation/ethereumjs-common": "4.0.4", - "@nomicfoundation/ethereumjs-rlp": "5.0.4", - "@nomicfoundation/ethereumjs-util": "9.0.4", - "ethereum-cryptography": "0.1.3" - }, - "dependencies": { - "ethereum-cryptography": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", - "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", - "requires": { - "@types/pbkdf2": "^3.0.0", - "@types/secp256k1": "^4.0.1", - "blakejs": "^1.1.0", - "browserify-aes": "^1.2.0", - "bs58check": "^2.1.2", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "hash.js": "^1.1.7", - "keccak": "^3.0.0", - "pbkdf2": "^3.0.17", - "randombytes": "^2.1.0", - "safe-buffer": "^5.1.2", - "scrypt-js": "^3.0.0", - "secp256k1": "^4.0.1", - "setimmediate": "^1.0.5" - } - } - } - }, - "@nomicfoundation/ethereumjs-util": { - "version": "9.0.4", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-util/-/ethereumjs-util-9.0.4.tgz", - "integrity": "sha512-sLOzjnSrlx9Bb9EFNtHzK/FJFsfg2re6bsGqinFinH1gCqVfz9YYlXiMWwDM4C/L4ywuHFCYwfKTVr/QHQcU0Q==", - "requires": { - "@nomicfoundation/ethereumjs-rlp": "5.0.4", - "ethereum-cryptography": "0.1.3" + "node_modules/zksync-ethers/node_modules/ws": { + "version": "7.4.6", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz", + "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==", + "license": "MIT", + "engines": { + "node": ">=8.3.0" }, - "dependencies": { - "ethereum-cryptography": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", - "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", - "requires": { - "@types/pbkdf2": "^3.0.0", - "@types/secp256k1": "^4.0.1", - "blakejs": "^1.1.0", - "browserify-aes": "^1.2.0", - "bs58check": "^2.1.2", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "hash.js": "^1.1.7", - "keccak": "^3.0.0", - "pbkdf2": "^3.0.17", - "randombytes": "^2.1.0", - "safe-buffer": "^5.1.2", - "scrypt-js": "^3.0.0", - "secp256k1": "^4.0.1", - "setimmediate": "^1.0.5" - } - } - } - }, - "@nomicfoundation/hardhat-chai-matchers": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-chai-matchers/-/hardhat-chai-matchers-2.0.8.tgz", - "integrity": "sha512-Z5PiCXH4xhNLASROlSUOADfhfpfhYO6D7Hn9xp8PddmHey0jq704cr6kfU8TRrQ4PUZbpfsZadPj+pCfZdjPIg==", - "dev": true, - "requires": { - "@types/chai-as-promised": "^7.1.3", - "chai-as-promised": "^7.1.1", - "deep-eql": "^4.0.1", - "ordinal": "^1.0.3" - } - }, - "@nomicfoundation/hardhat-ethers": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-ethers/-/hardhat-ethers-3.0.8.tgz", - "integrity": "sha512-zhOZ4hdRORls31DTOqg+GmEZM0ujly8GGIuRY7t7szEk2zW/arY1qDug/py8AEktT00v5K+b6RvbVog+va51IA==", - "peer": true, - "requires": { - "debug": "^4.1.1", - "lodash.isequal": "^4.5.0" - } - }, - "@nomicfoundation/hardhat-network-helpers": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-network-helpers/-/hardhat-network-helpers-1.0.12.tgz", - "integrity": "sha512-xTNQNI/9xkHvjmCJnJOTyqDSl8uq1rKb2WOVmixQxFtRd7Oa3ecO8zM0cyC2YmOK+jHB9WPZ+F/ijkHg1CoORA==", - "dev": true, - "requires": { - "ethereumjs-util": "^7.1.4" - } - }, - "@nomicfoundation/solidity-analyzer": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer/-/solidity-analyzer-0.1.0.tgz", - "integrity": "sha512-xGWAiVCGOycvGiP/qrlf9f9eOn7fpNbyJygcB0P21a1MDuVPlKt0Srp7rvtBEutYQ48ouYnRXm33zlRnlTOPHg==", - "requires": { - "@nomicfoundation/solidity-analyzer-darwin-arm64": "0.1.0", - "@nomicfoundation/solidity-analyzer-darwin-x64": "0.1.0", - "@nomicfoundation/solidity-analyzer-freebsd-x64": "0.1.0", - "@nomicfoundation/solidity-analyzer-linux-arm64-gnu": "0.1.0", - "@nomicfoundation/solidity-analyzer-linux-arm64-musl": "0.1.0", - "@nomicfoundation/solidity-analyzer-linux-x64-gnu": "0.1.0", - "@nomicfoundation/solidity-analyzer-linux-x64-musl": "0.1.0", - "@nomicfoundation/solidity-analyzer-win32-arm64-msvc": "0.1.0", - "@nomicfoundation/solidity-analyzer-win32-ia32-msvc": "0.1.0", - "@nomicfoundation/solidity-analyzer-win32-x64-msvc": "0.1.0" - } - }, - "@nomicfoundation/solidity-analyzer-darwin-arm64": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-darwin-arm64/-/solidity-analyzer-darwin-arm64-0.1.0.tgz", - "integrity": "sha512-vEF3yKuuzfMHsZecHQcnkUrqm8mnTWfJeEVFHpg+cO+le96xQA4lAJYdUan8pXZohQxv1fSReQsn4QGNuBNuCw==", - "optional": true - }, - "@nomicfoundation/solidity-analyzer-darwin-x64": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-darwin-x64/-/solidity-analyzer-darwin-x64-0.1.0.tgz", - "integrity": "sha512-dlHeIg0pTL4dB1l9JDwbi/JG6dHQaU1xpDK+ugYO8eJ1kxx9Dh2isEUtA4d02cQAl22cjOHTvifAk96A+ItEHA==", - "optional": true - }, - "@nomicfoundation/solidity-analyzer-freebsd-x64": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-freebsd-x64/-/solidity-analyzer-freebsd-x64-0.1.0.tgz", - "integrity": "sha512-WFCZYMv86WowDA4GiJKnebMQRt3kCcFqHeIomW6NMyqiKqhK1kIZCxSLDYsxqlx396kKLPN1713Q1S8tu68GKg==", - "optional": true - }, - "@nomicfoundation/solidity-analyzer-linux-arm64-gnu": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-linux-arm64-gnu/-/solidity-analyzer-linux-arm64-gnu-0.1.0.tgz", - "integrity": "sha512-DTw6MNQWWlCgc71Pq7CEhEqkb7fZnS7oly13pujs4cMH1sR0JzNk90Mp1zpSCsCs4oKan2ClhMlLKtNat/XRKQ==", - "optional": true - }, - "@nomicfoundation/solidity-analyzer-linux-arm64-musl": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-linux-arm64-musl/-/solidity-analyzer-linux-arm64-musl-0.1.0.tgz", - "integrity": "sha512-wUpUnR/3GV5Da88MhrxXh/lhb9kxh9V3Jya2NpBEhKDIRCDmtXMSqPMXHZmOR9DfCwCvG6vLFPr/+YrPCnUN0w==", - "optional": true - }, - "@nomicfoundation/solidity-analyzer-linux-x64-gnu": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-linux-x64-gnu/-/solidity-analyzer-linux-x64-gnu-0.1.0.tgz", - "integrity": "sha512-lR0AxK1x/MeKQ/3Pt923kPvwigmGX3OxeU5qNtQ9pj9iucgk4PzhbS3ruUeSpYhUxG50jN4RkIGwUMoev5lguw==", - "optional": true - }, - "@nomicfoundation/solidity-analyzer-linux-x64-musl": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-linux-x64-musl/-/solidity-analyzer-linux-x64-musl-0.1.0.tgz", - "integrity": "sha512-A1he/8gy/JeBD3FKvmI6WUJrGrI5uWJNr5Xb9WdV+DK0F8msuOqpEByLlnTdLkXMwW7nSl3awvLezOs9xBHJEg==", - "optional": true - }, - "@nomicfoundation/solidity-analyzer-win32-arm64-msvc": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-win32-arm64-msvc/-/solidity-analyzer-win32-arm64-msvc-0.1.0.tgz", - "integrity": "sha512-7x5SXZ9R9H4SluJZZP8XPN+ju7Mx+XeUMWZw7ZAqkdhP5mK19I4vz3x0zIWygmfE8RT7uQ5xMap0/9NPsO+ykw==", - "optional": true - }, - "@nomicfoundation/solidity-analyzer-win32-ia32-msvc": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-win32-ia32-msvc/-/solidity-analyzer-win32-ia32-msvc-0.1.0.tgz", - "integrity": "sha512-m7w3xf+hnE774YRXu+2mGV7RiF3QJtUoiYU61FascCkQhX3QMQavh7saH/vzb2jN5D24nT/jwvaHYX/MAM9zUw==", - "optional": true - }, - "@nomicfoundation/solidity-analyzer-win32-x64-msvc": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-win32-x64-msvc/-/solidity-analyzer-win32-x64-msvc-0.1.0.tgz", - "integrity": "sha512-xCuybjY0sLJQnJhupiFAXaek2EqF0AP0eBjgzaalPXSNvCEN6ZYHvUzdA50ENDVeSYFXcUsYf3+FsD3XKaeptA==", - "optional": true - }, - "@nomiclabs/hardhat-solhint": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@nomiclabs/hardhat-solhint/-/hardhat-solhint-4.0.1.tgz", - "integrity": "sha512-ekfbbGfUwMZGr9aPAurPa7GVMX/6XqKemppVEez+mC36H7G5UyBsnrUKZMhMDVHG9S7+ke9sLuaibnWvpdSrQA==", - "dev": true, - "requires": { - "solhint": "^5.0.2" - } - }, - "@openzeppelin/contracts": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-5.1.0.tgz", - "integrity": "sha512-p1ULhl7BXzjjbha5aqst+QMLY+4/LCWADXOCsmLHRM77AqiPjnd9vvUN9sosUfhL9JGKpZ0TjEGxgvnizmWGSA==" - }, - "@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "dev": true, - "optional": true - }, - "@pkgr/core": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.1.tgz", - "integrity": "sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==", - "dev": true - }, - "@pnpm/config.env-replace": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@pnpm/config.env-replace/-/config.env-replace-1.1.0.tgz", - "integrity": "sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==", - "dev": true - }, - "@pnpm/network.ca-file": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@pnpm/network.ca-file/-/network.ca-file-1.0.2.tgz", - "integrity": "sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==", - "dev": true, - "requires": { - "graceful-fs": "4.2.10" - } - }, - "@pnpm/npm-conf": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/@pnpm/npm-conf/-/npm-conf-2.3.1.tgz", - "integrity": "sha512-c83qWb22rNRuB0UaVCI0uRPNRr8Z0FWnEIvT47jiHAmOIUHbBOg5XvV7pM5x+rKn9HRpjxquDbXYSXr3fAKFcw==", - "dev": true, - "requires": { - "@pnpm/config.env-replace": "^1.1.0", - "@pnpm/network.ca-file": "^1.0.1", - "config-chain": "^1.1.11" - } - }, - "@polkadot-api/json-rpc-provider": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/@polkadot-api/json-rpc-provider/-/json-rpc-provider-0.0.1.tgz", - "integrity": "sha512-/SMC/l7foRjpykLTUTacIH05H3mr9ip8b5xxfwXlVezXrNVLp3Cv0GX6uItkKd+ZjzVPf3PFrDF2B2/HLSNESA==", - "optional": true - }, - "@polkadot-api/json-rpc-provider-proxy": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@polkadot-api/json-rpc-provider-proxy/-/json-rpc-provider-proxy-0.1.0.tgz", - "integrity": "sha512-8GSFE5+EF73MCuLQm8tjrbCqlgclcHBSRaswvXziJ0ZW7iw3UEMsKkkKvELayWyBuOPa2T5i1nj6gFOeIsqvrg==", - "optional": true - }, - "@polkadot-api/metadata-builders": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@polkadot-api/metadata-builders/-/metadata-builders-0.3.2.tgz", - "integrity": "sha512-TKpfoT6vTb+513KDzMBTfCb/ORdgRnsS3TDFpOhAhZ08ikvK+hjHMt5plPiAX/OWkm1Wc9I3+K6W0hX5Ab7MVg==", - "optional": true, - "requires": { - "@polkadot-api/substrate-bindings": "0.6.0", - "@polkadot-api/utils": "0.1.0" - } - }, - "@polkadot-api/observable-client": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@polkadot-api/observable-client/-/observable-client-0.3.2.tgz", - "integrity": "sha512-HGgqWgEutVyOBXoGOPp4+IAq6CNdK/3MfQJmhCJb8YaJiaK4W6aRGrdQuQSTPHfERHCARt9BrOmEvTXAT257Ug==", - "optional": true, - "requires": { - "@polkadot-api/metadata-builders": "0.3.2", - "@polkadot-api/substrate-bindings": "0.6.0", - "@polkadot-api/utils": "0.1.0" - } - }, - "@polkadot-api/substrate-bindings": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@polkadot-api/substrate-bindings/-/substrate-bindings-0.6.0.tgz", - "integrity": "sha512-lGuhE74NA1/PqdN7fKFdE5C1gNYX357j1tWzdlPXI0kQ7h3kN0zfxNOpPUN7dIrPcOFZ6C0tRRVrBylXkI6xPw==", - "optional": true, - "requires": { - "@noble/hashes": "^1.3.1", - "@polkadot-api/utils": "0.1.0", - "@scure/base": "^1.1.1", - "scale-ts": "^1.6.0" + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" }, - "dependencies": { - "@noble/hashes": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.6.1.tgz", - "integrity": "sha512-pq5D8h10hHBjyqX+cfBm0i8JUXJ0UhczFc4r74zbuT9XgewFo2E3J1cOaGtdZynILNmQ685YWGzGE1Zv6io50w==", + "peerDependenciesMeta": { + "bufferutil": { "optional": true - } - } - }, - "@polkadot-api/substrate-client": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/@polkadot-api/substrate-client/-/substrate-client-0.1.4.tgz", - "integrity": "sha512-MljrPobN0ZWTpn++da9vOvt+Ex+NlqTlr/XT7zi9sqPtDJiQcYl+d29hFAgpaeTqbeQKZwz3WDE9xcEfLE8c5A==", - "optional": true, - "requires": { - "@polkadot-api/json-rpc-provider": "0.0.1", - "@polkadot-api/utils": "0.1.0" - } - }, - "@polkadot-api/utils": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@polkadot-api/utils/-/utils-0.1.0.tgz", - "integrity": "sha512-MXzWZeuGxKizPx2Xf/47wx9sr/uxKw39bVJUptTJdsaQn/TGq+z310mHzf1RCGvC1diHM8f593KrnDgc9oNbJA==", - "optional": true - }, - "@polkadot/api": { - "version": "15.0.2", - "resolved": "https://registry.npmjs.org/@polkadot/api/-/api-15.0.2.tgz", - "integrity": "sha512-CA8Pq2Gsz2MJvpkpIVNzaBs2eJGCr0sEodAb0vTOZW/ZlIDHcBWyWq3KXE+lBMWVzYBEC4Vz6MafNgq6Bsshlw==", - "requires": { - "@polkadot/api-augment": "15.0.2", - "@polkadot/api-base": "15.0.2", - "@polkadot/api-derive": "15.0.2", - "@polkadot/keyring": "^13.2.3", - "@polkadot/rpc-augment": "15.0.2", - "@polkadot/rpc-core": "15.0.2", - "@polkadot/rpc-provider": "15.0.2", - "@polkadot/types": "15.0.2", - "@polkadot/types-augment": "15.0.2", - "@polkadot/types-codec": "15.0.2", - "@polkadot/types-create": "15.0.2", - "@polkadot/types-known": "15.0.2", - "@polkadot/util": "^13.2.3", - "@polkadot/util-crypto": "^13.2.3", - "eventemitter3": "^5.0.1", - "rxjs": "^7.8.1", - "tslib": "^2.8.0" - } - }, - "@polkadot/api-augment": { - "version": "15.0.2", - "resolved": "https://registry.npmjs.org/@polkadot/api-augment/-/api-augment-15.0.2.tgz", - "integrity": "sha512-7qtfTihLKS7cT2kEsd8Y1+MJ+2n4Sl0y9BHuPhdNfKcDbGwCxIB7JzXNujww4Is4bF7w1lXcM2U0E/XwJi1BbQ==", - "requires": { - "@polkadot/api-base": "15.0.2", - "@polkadot/rpc-augment": "15.0.2", - "@polkadot/types": "15.0.2", - "@polkadot/types-augment": "15.0.2", - "@polkadot/types-codec": "15.0.2", - "@polkadot/util": "^13.2.3", - "tslib": "^2.8.0" - } - }, - "@polkadot/api-base": { - "version": "15.0.2", - "resolved": "https://registry.npmjs.org/@polkadot/api-base/-/api-base-15.0.2.tgz", - "integrity": "sha512-5++EjpuCxzmrL2JJj511RrPK+IovuIQa8DJhyOp62VDMXPkqS/O6Df5wjYzQh/ftT1ZysftXqJAUA/LSUsH+2g==", - "requires": { - "@polkadot/rpc-core": "15.0.2", - "@polkadot/types": "15.0.2", - "@polkadot/util": "^13.2.3", - "rxjs": "^7.8.1", - "tslib": "^2.8.0" - } - }, - "@polkadot/api-derive": { - "version": "15.0.2", - "resolved": "https://registry.npmjs.org/@polkadot/api-derive/-/api-derive-15.0.2.tgz", - "integrity": "sha512-nD8hXZxEv2/wuhjMmVP09lTAYd8inNgrLpLGUR+7hBQeVEQQTdNatkqMKpNIOk2MO46mtUK35NepvDBK9DWZzA==", - "requires": { - "@polkadot/api": "15.0.2", - "@polkadot/api-augment": "15.0.2", - "@polkadot/api-base": "15.0.2", - "@polkadot/rpc-core": "15.0.2", - "@polkadot/types": "15.0.2", - "@polkadot/types-codec": "15.0.2", - "@polkadot/util": "^13.2.3", - "@polkadot/util-crypto": "^13.2.3", - "rxjs": "^7.8.1", - "tslib": "^2.8.0" - } - }, - "@polkadot/keyring": { - "version": "13.2.3", - "resolved": "https://registry.npmjs.org/@polkadot/keyring/-/keyring-13.2.3.tgz", - "integrity": "sha512-pgTo6DXNXub0wGD+MnVHYhKxf80Jl+QMOCb818ioGdXz++Uw4mTueFAwtB+N7TGo0HafhChUiNJDxFdlDkcAng==", - "requires": { - "@polkadot/util": "13.2.3", - "@polkadot/util-crypto": "13.2.3", - "tslib": "^2.8.0" - } - }, - "@polkadot/networks": { - "version": "13.2.3", - "resolved": "https://registry.npmjs.org/@polkadot/networks/-/networks-13.2.3.tgz", - "integrity": "sha512-mG+zkXg/33AyPrkv2xBbAo3LBUwOwBn6qznBU/4jxiZPnVvCwMaxE7xHM22B5riItbNJ169FXv3wy0v6ZmkFbw==", - "requires": { - "@polkadot/util": "13.2.3", - "@substrate/ss58-registry": "^1.51.0", - "tslib": "^2.8.0" - } - }, - "@polkadot/rpc-augment": { - "version": "15.0.2", - "resolved": "https://registry.npmjs.org/@polkadot/rpc-augment/-/rpc-augment-15.0.2.tgz", - "integrity": "sha512-of88GdzsOs15HP+Gowh4G/iKKFkCNIeF0Wes8LiONfn+j2TmWt8blbyGhrIZZeApzbFUDFjnxUPGT40uWJcMpw==", - "requires": { - "@polkadot/rpc-core": "15.0.2", - "@polkadot/types": "15.0.2", - "@polkadot/types-codec": "15.0.2", - "@polkadot/util": "^13.2.3", - "tslib": "^2.8.0" - } - }, - "@polkadot/rpc-core": { - "version": "15.0.2", - "resolved": "https://registry.npmjs.org/@polkadot/rpc-core/-/rpc-core-15.0.2.tgz", - "integrity": "sha512-KOUnfXOAFCN0N23sEbS+FzXhX88JCvJst/nKzO9+q67NgYBEqgcaoG4tqt/VVedgkNi0kA7WAA3wyjt5UYMnrg==", - "requires": { - "@polkadot/rpc-augment": "15.0.2", - "@polkadot/rpc-provider": "15.0.2", - "@polkadot/types": "15.0.2", - "@polkadot/util": "^13.2.3", - "rxjs": "^7.8.1", - "tslib": "^2.8.0" - } - }, - "@polkadot/rpc-provider": { - "version": "15.0.2", - "resolved": "https://registry.npmjs.org/@polkadot/rpc-provider/-/rpc-provider-15.0.2.tgz", - "integrity": "sha512-BwLP8gNskzqtQ2kMk+EX6WK4d9TU0XJ/nJg0TKC2dX5sSTpTF2JQIYp1wuOik4rKNXIU/1hKaDSSylMJj7AHeQ==", - "requires": { - "@polkadot/keyring": "^13.2.3", - "@polkadot/types": "15.0.2", - "@polkadot/types-support": "15.0.2", - "@polkadot/util": "^13.2.3", - "@polkadot/util-crypto": "^13.2.3", - "@polkadot/x-fetch": "^13.2.3", - "@polkadot/x-global": "^13.2.3", - "@polkadot/x-ws": "^13.2.3", - "@substrate/connect": "0.8.11", - "eventemitter3": "^5.0.1", - "mock-socket": "^9.3.1", - "nock": "^13.5.5", - "tslib": "^2.8.0" - } - }, - "@polkadot/types": { - "version": "15.0.2", - "resolved": "https://registry.npmjs.org/@polkadot/types/-/types-15.0.2.tgz", - "integrity": "sha512-6gZBnuXU58hQAXWI2daED2OaQwFMxbQdkE8HVGMovMobEf0PxPfIqf+GdnVmWbe09EU9mv2gCWBcdnvHSRBlQg==", - "requires": { - "@polkadot/keyring": "^13.2.3", - "@polkadot/types-augment": "15.0.2", - "@polkadot/types-codec": "15.0.2", - "@polkadot/types-create": "15.0.2", - "@polkadot/util": "^13.2.3", - "@polkadot/util-crypto": "^13.2.3", - "rxjs": "^7.8.1", - "tslib": "^2.8.0" - } - }, - "@polkadot/types-augment": { - "version": "15.0.2", - "resolved": "https://registry.npmjs.org/@polkadot/types-augment/-/types-augment-15.0.2.tgz", - "integrity": "sha512-UiFJVEYML30+V9GdFAHPbA3s4MVQTL1CevsZMnX0+ApvlgEHJMZnVFfYF7jL2bl9BcUYM/zoxEAhj2MpqFFfxw==", - "requires": { - "@polkadot/types": "15.0.2", - "@polkadot/types-codec": "15.0.2", - "@polkadot/util": "^13.2.3", - "tslib": "^2.8.0" - } - }, - "@polkadot/types-codec": { - "version": "15.0.2", - "resolved": "https://registry.npmjs.org/@polkadot/types-codec/-/types-codec-15.0.2.tgz", - "integrity": "sha512-44Q40p1rl0t7Bl1QUamewqXNVPway9xgqByyifv6ODSGhtt+lFoarb3U4JzqRUuuK0PP57ePB0L8q81Totxeew==", - "requires": { - "@polkadot/util": "^13.2.3", - "@polkadot/x-bigint": "^13.2.3", - "tslib": "^2.8.0" - } - }, - "@polkadot/types-create": { - "version": "15.0.2", - "resolved": "https://registry.npmjs.org/@polkadot/types-create/-/types-create-15.0.2.tgz", - "integrity": "sha512-YhpcqbH3oI87PkgrV6Fez9jWDqFIep0KcS1YWQcwc9gsBNnuour80t2AAK41/tqAYwOZi6tpJwIevnEhVkxFYA==", - "requires": { - "@polkadot/types-codec": "15.0.2", - "@polkadot/util": "^13.2.3", - "tslib": "^2.8.0" - } - }, - "@polkadot/types-known": { - "version": "15.0.2", - "resolved": "https://registry.npmjs.org/@polkadot/types-known/-/types-known-15.0.2.tgz", - "integrity": "sha512-SyBo4xBoesHYiEfdW/nOgaftKgM7+puBWqQXq1Euz0MM5LDLjxBw22Srgk9ulGM6l9MsekIwCyX8geJ6/6J3Cg==", - "requires": { - "@polkadot/networks": "^13.2.3", - "@polkadot/types": "15.0.2", - "@polkadot/types-codec": "15.0.2", - "@polkadot/types-create": "15.0.2", - "@polkadot/util": "^13.2.3", - "tslib": "^2.8.0" - } - }, - "@polkadot/types-support": { - "version": "15.0.2", - "resolved": "https://registry.npmjs.org/@polkadot/types-support/-/types-support-15.0.2.tgz", - "integrity": "sha512-I7Im/4K2/XDZ1LfeQeeNyvIkfvozIPQs8K1/nsICDOmBbvIsjxSeKWHOcFDMJ8AlPEer6bqNQavOyZA/pg9R/Q==", - "requires": { - "@polkadot/util": "^13.2.3", - "tslib": "^2.8.0" - } - }, - "@polkadot/util": { - "version": "13.2.3", - "resolved": "https://registry.npmjs.org/@polkadot/util/-/util-13.2.3.tgz", - "integrity": "sha512-pioNnsig3qHXrfOKMe4Yqos8B8N3/EZUpS+WfTpWnn1VjYban/0GrTXeavPlAwggnY27b8fS6rBzQBhnVYDw8g==", - "requires": { - "@polkadot/x-bigint": "13.2.3", - "@polkadot/x-global": "13.2.3", - "@polkadot/x-textdecoder": "13.2.3", - "@polkadot/x-textencoder": "13.2.3", - "@types/bn.js": "^5.1.6", - "bn.js": "^5.2.1", - "tslib": "^2.8.0" - } - }, - "@polkadot/util-crypto": { - "version": "13.2.3", - "resolved": "https://registry.npmjs.org/@polkadot/util-crypto/-/util-crypto-13.2.3.tgz", - "integrity": "sha512-5sbggmLbn5eiuVMyPROPlT5roHRqdKHOfSpioNbGvGIZ1qIWVoC1RfsK0NWJOVGDzy6DpQe0KYT/kgcU5Xsrzw==", - "requires": { - "@noble/curves": "^1.3.0", - "@noble/hashes": "^1.3.3", - "@polkadot/networks": "13.2.3", - "@polkadot/util": "13.2.3", - "@polkadot/wasm-crypto": "^7.4.1", - "@polkadot/wasm-util": "^7.4.1", - "@polkadot/x-bigint": "13.2.3", - "@polkadot/x-randomvalues": "13.2.3", - "@scure/base": "^1.1.7", - "tslib": "^2.8.0" - }, - "dependencies": { - "@noble/hashes": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", - "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==" - }, - "@scure/base": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.2.1.tgz", - "integrity": "sha512-DGmGtC8Tt63J5GfHgfl5CuAXh96VF/LD8K9Hr/Gv0J2lAoRGlPOMpqMpMbCTOoOJMZCk2Xt+DskdDyn6dEFdzQ==" - } - } - }, - "@polkadot/wasm-bridge": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/@polkadot/wasm-bridge/-/wasm-bridge-7.4.1.tgz", - "integrity": "sha512-tdkJaV453tezBxhF39r4oeG0A39sPKGDJmN81LYLf+Fihb7astzwju+u75BRmDrHZjZIv00un3razJEWCxze6g==", - "requires": { - "@polkadot/wasm-util": "7.4.1", - "tslib": "^2.7.0" - } - }, - "@polkadot/wasm-crypto": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/@polkadot/wasm-crypto/-/wasm-crypto-7.4.1.tgz", - "integrity": "sha512-kHN/kF7hYxm1y0WeFLWeWir6oTzvcFmR4N8fJJokR+ajYbdmrafPN+6iLgQVbhZnDdxyv9jWDuRRsDnBx8tPMQ==", - "requires": { - "@polkadot/wasm-bridge": "7.4.1", - "@polkadot/wasm-crypto-asmjs": "7.4.1", - "@polkadot/wasm-crypto-init": "7.4.1", - "@polkadot/wasm-crypto-wasm": "7.4.1", - "@polkadot/wasm-util": "7.4.1", - "tslib": "^2.7.0" - } - }, - "@polkadot/wasm-crypto-asmjs": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/@polkadot/wasm-crypto-asmjs/-/wasm-crypto-asmjs-7.4.1.tgz", - "integrity": "sha512-pwU8QXhUW7IberyHJIQr37IhbB6DPkCG5FhozCiNTq4vFBsFPjm9q8aZh7oX1QHQaiAZa2m2/VjIVE+FHGbvHQ==", - "requires": { - "tslib": "^2.7.0" - } - }, - "@polkadot/wasm-crypto-init": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/@polkadot/wasm-crypto-init/-/wasm-crypto-init-7.4.1.tgz", - "integrity": "sha512-AVka33+f7MvXEEIGq5U0dhaA2SaXMXnxVCQyhJTaCnJ5bRDj0Xlm3ijwDEQUiaDql7EikbkkRtmlvs95eSUWYQ==", - "requires": { - "@polkadot/wasm-bridge": "7.4.1", - "@polkadot/wasm-crypto-asmjs": "7.4.1", - "@polkadot/wasm-crypto-wasm": "7.4.1", - "@polkadot/wasm-util": "7.4.1", - "tslib": "^2.7.0" - } - }, - "@polkadot/wasm-crypto-wasm": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/@polkadot/wasm-crypto-wasm/-/wasm-crypto-wasm-7.4.1.tgz", - "integrity": "sha512-PE1OAoupFR0ZOV2O8tr7D1FEUAwaggzxtfs3Aa5gr+yxlSOaWUKeqsOYe1KdrcjmZVV3iINEAXxgrbzCmiuONg==", - "requires": { - "@polkadot/wasm-util": "7.4.1", - "tslib": "^2.7.0" - } - }, - "@polkadot/wasm-util": { - "version": "7.4.1", - "resolved": "https://registry.npmjs.org/@polkadot/wasm-util/-/wasm-util-7.4.1.tgz", - "integrity": "sha512-RAcxNFf3zzpkr+LX/ItAsvj+QyM56TomJ0xjUMo4wKkHjwsxkz4dWJtx5knIgQz/OthqSDMR59VNEycQeNuXzA==", - "requires": { - "tslib": "^2.7.0" - } - }, - "@polkadot/x-bigint": { - "version": "13.2.3", - "resolved": "https://registry.npmjs.org/@polkadot/x-bigint/-/x-bigint-13.2.3.tgz", - "integrity": "sha512-VKgEAh0LsxTd/Hg517Tt5ZU4CySjBwMpaojbkjgv3fOdg1cN7t4eFEUxpyj7mlO0cp22SzDh7nmy4TO98qhLQA==", - "requires": { - "@polkadot/x-global": "13.2.3", - "tslib": "^2.8.0" - } - }, - "@polkadot/x-fetch": { - "version": "13.2.3", - "resolved": "https://registry.npmjs.org/@polkadot/x-fetch/-/x-fetch-13.2.3.tgz", - "integrity": "sha512-7Nmk+8ieEGzz43nc1rX6nH3rQo6rhGmAaIXJWnXY9gOHY0k1me1bJYbP+xDdh8vcLh8eY3D1sESUwG6QYZW2lg==", - "requires": { - "@polkadot/x-global": "13.2.3", - "node-fetch": "^3.3.2", - "tslib": "^2.8.0" - } - }, - "@polkadot/x-global": { - "version": "13.2.3", - "resolved": "https://registry.npmjs.org/@polkadot/x-global/-/x-global-13.2.3.tgz", - "integrity": "sha512-7MYQIAEwBkRcNrgqac5PbB0kNPlI6ISJEy6/Nb+crj8BFjQ8rf11PF49fq0QsvDeuYM1aNLigrvYZNptQs4lbw==", - "requires": { - "tslib": "^2.8.0" - } - }, - "@polkadot/x-randomvalues": { - "version": "13.2.3", - "resolved": "https://registry.npmjs.org/@polkadot/x-randomvalues/-/x-randomvalues-13.2.3.tgz", - "integrity": "sha512-Zf0GTfLmVk+VzPUmcQSpXjjmFzMTjPhXoLuIoE7xIu73T+vQ+TX9j7DvorN6bIRsnZ9l1SyTZsSf/NTjNZKIZg==", - "requires": { - "@polkadot/x-global": "13.2.3", - "tslib": "^2.8.0" - } - }, - "@polkadot/x-textdecoder": { - "version": "13.2.3", - "resolved": "https://registry.npmjs.org/@polkadot/x-textdecoder/-/x-textdecoder-13.2.3.tgz", - "integrity": "sha512-i8hRXPtGknmdm3FYv6/94I52VXHJZa5sgYNw1+Hqb4Jqmq4awUjea35CKXd/+aw70Qn8Ngg31l2GoiH494fa+Q==", - "requires": { - "@polkadot/x-global": "13.2.3", - "tslib": "^2.8.0" - } - }, - "@polkadot/x-textencoder": { - "version": "13.2.3", - "resolved": "https://registry.npmjs.org/@polkadot/x-textencoder/-/x-textencoder-13.2.3.tgz", - "integrity": "sha512-wJI3Bb/dC4zyBXJFm5+ZhyBXWoI5wvP8k8qX0/ZC0PQsgSAqs7LVhiofk4Wd94n0P41W5re58LrGXLyziSAshw==", - "requires": { - "@polkadot/x-global": "13.2.3", - "tslib": "^2.8.0" - } - }, - "@polkadot/x-ws": { - "version": "13.2.3", - "resolved": "https://registry.npmjs.org/@polkadot/x-ws/-/x-ws-13.2.3.tgz", - "integrity": "sha512-Y6MTAWgcnrnx/LkBx65X3ZyoJH5EFj3tXtflRoKg1+PLHSLuNBV7Wi5mLcE70z4e5c+4hgBbLq+8SqCqzFtSPw==", - "requires": { - "@polkadot/x-global": "13.2.3", - "tslib": "^2.8.0", - "ws": "^8.18.0" - } - }, - "@prb/math": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@prb/math/-/math-4.1.0.tgz", - "integrity": "sha512-ef5Xrlh3BeX4xT5/Wi810dpEPq2bYPndRxgFIaKSU1F/Op/s8af03kyom+mfU7gEpvfIZ46xu8W0duiHplbBMg==" - }, - "@prettier/sync": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@prettier/sync/-/sync-0.3.0.tgz", - "integrity": "sha512-3dcmCyAxIcxy036h1I7MQU/uEEBq8oLwf1CE3xeze+MPlgkdlb/+w6rGR/1dhp6Hqi17fRS6nvwnOzkESxEkOw==", - "dev": true, - "requires": {} - }, - "@rtsao/scc": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", - "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==", - "dev": true - }, - "@scure/base": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.6.tgz", - "integrity": "sha512-ok9AWwhcgYuGG3Zfhyqg+zwl+Wn5uE+dwC0NV/2qQkx4dABbb/bx96vWu8NSj+BNjjSjno+JRYRjle1jV08k3g==" - }, - "@scure/bip32": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.1.0.tgz", - "integrity": "sha512-ftTW3kKX54YXLCxH6BB7oEEoJfoE2pIgw7MINKAs5PsS6nqKPuKk1haTF/EuHmYqG330t5GSrdmtRuHaY1a62Q==", - "requires": { - "@noble/hashes": "~1.1.1", - "@noble/secp256k1": "~1.6.0", - "@scure/base": "~1.1.0" - } - }, - "@scure/bip39": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.1.0.tgz", - "integrity": "sha512-pwrPOS16VeTKg98dYXQyIjJEcWfz7/1YJIwxUEPFfQPtc86Ym/1sVgQ2RLoD43AazMk2l/unK4ITySSpW2+82w==", - "requires": { - "@noble/hashes": "~1.1.1", - "@scure/base": "~1.1.0" - } - }, - "@sentry/core": { - "version": "5.30.0", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-5.30.0.tgz", - "integrity": "sha512-TmfrII8w1PQZSZgPpUESqjB+jC6MvZJZdLtE/0hZ+SrnKhW3x5WlYLvTXZpcWePYBku7rl2wn1RZu6uT0qCTeg==", - "requires": { - "@sentry/hub": "5.30.0", - "@sentry/minimal": "5.30.0", - "@sentry/types": "5.30.0", - "@sentry/utils": "5.30.0", - "tslib": "^1.9.3" - }, - "dependencies": { - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - } - } - }, - "@sentry/hub": { - "version": "5.30.0", - "resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-5.30.0.tgz", - "integrity": "sha512-2tYrGnzb1gKz2EkMDQcfLrDTvmGcQPuWxLnJKXJvYTQDGLlEvi2tWz1VIHjunmOvJrB5aIQLhm+dcMRwFZDCqQ==", - "requires": { - "@sentry/types": "5.30.0", - "@sentry/utils": "5.30.0", - "tslib": "^1.9.3" - }, - "dependencies": { - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - } - } - }, - "@sentry/minimal": { - "version": "5.30.0", - "resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-5.30.0.tgz", - "integrity": "sha512-BwWb/owZKtkDX+Sc4zCSTNcvZUq7YcH3uAVlmh/gtR9rmUvbzAA3ewLuB3myi4wWRAMEtny6+J/FN/x+2wn9Xw==", - "requires": { - "@sentry/hub": "5.30.0", - "@sentry/types": "5.30.0", - "tslib": "^1.9.3" - }, - "dependencies": { - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - } - } - }, - "@sentry/node": { - "version": "5.30.0", - "resolved": "https://registry.npmjs.org/@sentry/node/-/node-5.30.0.tgz", - "integrity": "sha512-Br5oyVBF0fZo6ZS9bxbJZG4ApAjRqAnqFFurMVJJdunNb80brh7a5Qva2kjhm+U6r9NJAB5OmDyPkA1Qnt+QVg==", - "requires": { - "@sentry/core": "5.30.0", - "@sentry/hub": "5.30.0", - "@sentry/tracing": "5.30.0", - "@sentry/types": "5.30.0", - "@sentry/utils": "5.30.0", - "cookie": "^0.4.1", - "https-proxy-agent": "^5.0.0", - "lru_map": "^0.3.3", - "tslib": "^1.9.3" - }, - "dependencies": { - "cookie": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", - "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==" - }, - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - } - } - }, - "@sentry/tracing": { - "version": "5.30.0", - "resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-5.30.0.tgz", - "integrity": "sha512-dUFowCr0AIMwiLD7Fs314Mdzcug+gBVo/+NCMyDw8tFxJkwWAKl7Qa2OZxLQ0ZHjakcj1hNKfCQJ9rhyfOl4Aw==", - "requires": { - "@sentry/hub": "5.30.0", - "@sentry/minimal": "5.30.0", - "@sentry/types": "5.30.0", - "@sentry/utils": "5.30.0", - "tslib": "^1.9.3" - }, - "dependencies": { - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - } - } - }, - "@sentry/types": { - "version": "5.30.0", - "resolved": "https://registry.npmjs.org/@sentry/types/-/types-5.30.0.tgz", - "integrity": "sha512-R8xOqlSTZ+htqrfteCWU5Nk0CDN5ApUTvrlvBuiH1DyP6czDZ4ktbZB0hAgBlVcK0U+qpD3ag3Tqqpa5Q67rPw==" - }, - "@sentry/utils": { - "version": "5.30.0", - "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-5.30.0.tgz", - "integrity": "sha512-zaYmoH0NWWtvnJjC9/CBseXMtKHm/tm40sz3YfJRxeQjyzRqNQPgivpd9R/oDJCYj999mzdW382p/qi2ypjLww==", - "requires": { - "@sentry/types": "5.30.0", - "tslib": "^1.9.3" - }, - "dependencies": { - "tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" - } - } - }, - "@sindresorhus/is": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", - "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", - "dev": true - }, - "@solidity-parser/parser": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.18.0.tgz", - "integrity": "sha512-yfORGUIPgLck41qyN7nbwJRAx17/jAIXCTanHOJZhB6PJ1iAk/84b/xlsVKFSyNyLXIj0dhppoE0+CRws7wlzA==", - "dev": true - }, - "@substrate/connect": { - "version": "0.8.11", - "resolved": "https://registry.npmjs.org/@substrate/connect/-/connect-0.8.11.tgz", - "integrity": "sha512-ofLs1PAO9AtDdPbdyTYj217Pe+lBfTLltdHDs3ds8no0BseoLeAGxpz1mHfi7zB4IxI3YyAiLjH6U8cw4pj4Nw==", - "optional": true, - "requires": { - "@substrate/connect-extension-protocol": "^2.0.0", - "@substrate/connect-known-chains": "^1.1.5", - "@substrate/light-client-extension-helpers": "^1.0.0", - "smoldot": "2.0.26" - } - }, - "@substrate/connect-extension-protocol": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@substrate/connect-extension-protocol/-/connect-extension-protocol-2.2.1.tgz", - "integrity": "sha512-GoafTgm/Jey9E4Xlj4Z5ZBt/H4drH2CNq8VrAro80rtoznrXnFDNVivLQzZN0Xaj2g8YXSn9pC9Oc9IovYZJXw==", - "optional": true - }, - "@substrate/connect-known-chains": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/@substrate/connect-known-chains/-/connect-known-chains-1.8.1.tgz", - "integrity": "sha512-WkqXvuLWL1g136nxAoGkclybsVpo8claHeBl/8iA99ECAk4pWLtoCh8PoYrFEE1HfY4rk+A0krPybDlcDa/G4g==", - "optional": true - }, - "@substrate/light-client-extension-helpers": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@substrate/light-client-extension-helpers/-/light-client-extension-helpers-1.0.0.tgz", - "integrity": "sha512-TdKlni1mBBZptOaeVrKnusMg/UBpWUORNDv5fdCaJklP4RJiFOzBCrzC+CyVI5kQzsXBisZ+2pXm+rIjS38kHg==", - "optional": true, - "requires": { - "@polkadot-api/json-rpc-provider": "^0.0.1", - "@polkadot-api/json-rpc-provider-proxy": "^0.1.0", - "@polkadot-api/observable-client": "^0.3.0", - "@polkadot-api/substrate-client": "^0.1.2", - "@substrate/connect-extension-protocol": "^2.0.0", - "@substrate/connect-known-chains": "^1.1.5", - "rxjs": "^7.8.1" - } - }, - "@substrate/ss58-registry": { - "version": "1.51.0", - "resolved": "https://registry.npmjs.org/@substrate/ss58-registry/-/ss58-registry-1.51.0.tgz", - "integrity": "sha512-TWDurLiPxndFgKjVavCniytBIw+t4ViOi7TYp9h/D0NMmkEc9klFTo+827eyEJ0lELpqO207Ey7uGxUa+BS1jQ==" - }, - "@szmarczak/http-timer": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-5.0.1.tgz", - "integrity": "sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==", - "dev": true, - "requires": { - "defer-to-connect": "^2.0.1" - } - }, - "@tsconfig/node10": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", - "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==" - }, - "@tsconfig/node12": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", - "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==" - }, - "@tsconfig/node14": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", - "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==" - }, - "@tsconfig/node16": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.3.tgz", - "integrity": "sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==" - }, - "@typechain/ethers-v6": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/@typechain/ethers-v6/-/ethers-v6-0.5.1.tgz", - "integrity": "sha512-F+GklO8jBWlsaVV+9oHaPh5NJdd6rAKN4tklGfInX1Q7h0xPgVLP39Jl3eCulPB5qexI71ZFHwbljx4ZXNfouA==", - "dev": true, - "requires": { - "lodash": "^4.17.15", - "ts-essentials": "^7.0.1" - } - }, - "@typechain/hardhat": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/@typechain/hardhat/-/hardhat-9.1.0.tgz", - "integrity": "sha512-mtaUlzLlkqTlfPwB3FORdejqBskSnh+Jl8AIJGjXNAQfRQ4ofHADPl1+oU7Z3pAJzmZbUXII8MhOLQltcHgKnA==", - "dev": true, - "requires": { - "fs-extra": "^9.1.0" - }, - "dependencies": { - "fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dev": true, - "requires": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - } - }, - "universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "dev": true - } - } - }, - "@types/bn.js": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.6.tgz", - "integrity": "sha512-Xh8vSwUeMKeYYrj3cX4lGQgFSF/N03r+tv4AiLl1SucqV+uTQpxRcnM8AkXKHwYP9ZPXOYXRr2KPXpVlIvqh9w==", - "requires": { - "@types/node": "*" - } - }, - "@types/cacheable-request": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", - "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", - "dev": true, - "requires": { - "@types/http-cache-semantics": "*", - "@types/keyv": "^3.1.4", - "@types/node": "*", - "@types/responselike": "^1.0.0" - } - }, - "@types/chai": { - "version": "4.3.20", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.20.tgz", - "integrity": "sha512-/pC9HAB5I/xMlc5FP77qjCnI16ChlJfW0tGa0IUcFn38VJrTV6DeZ60NU5KZBtaOZqjdpwTWohz5HU1RrhiYxQ==", - "dev": true - }, - "@types/chai-as-promised": { - "version": "7.1.5", - "resolved": "https://registry.npmjs.org/@types/chai-as-promised/-/chai-as-promised-7.1.5.tgz", - "integrity": "sha512-jStwss93SITGBwt/niYrkf2C+/1KTeZCZl1LaeezTlqppAKeoQC7jxyqYuP72sxBGKCIbw7oHgbYssIRzT5FCQ==", - "dev": true, - "requires": { - "@types/chai": "*" - } - }, - "@types/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==", - "dev": true, - "requires": { - "@types/minimatch": "*", - "@types/node": "*" - } - }, - "@types/http-cache-semantics": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.3.tgz", - "integrity": "sha512-V46MYLFp08Wf2mmaBhvgjStM3tPa+2GAdy/iqoX+noX1//zje2x4XmrIU0cAwyClATsTmahbtoQ2EwP7I5WSiA==", - "dev": true - }, - "@types/json5": { - "version": "0.0.29", - "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", - "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", - "dev": true - }, - "@types/keyv": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", - "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/@types/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw==" - }, - "@types/minimatch": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", - "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==", - "dev": true - }, - "@types/mocha": { - "version": "10.0.10", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.10.tgz", - "integrity": "sha512-xPyYSz1cMPnJQhl0CLMH68j3gprKZaTjG3s5Vi+fDgx+uhG9NOXwbVt52eFS8ECyXhyKcjDLCBEqBExKuiZb7Q==", - "dev": true - }, - "@types/node": { - "version": "22.10.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz", - "integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==", - "requires": { - "undici-types": "~6.20.0" - }, - "dependencies": { - "undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==" - } - } - }, - "@types/pbkdf2": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@types/pbkdf2/-/pbkdf2-3.1.0.tgz", - "integrity": "sha512-Cf63Rv7jCQ0LaL8tNXmEyqTHuIJxRdlS5vMh1mj5voN4+QFhVZnlZruezqpWYDiJ8UTzhP0VmeLXCmBk66YrMQ==", - "requires": { - "@types/node": "*" - } - }, - "@types/prettier": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.2.tgz", - "integrity": "sha512-KufADq8uQqo1pYKVIYzfKbJfBAc0sOeXqGbFaSpv8MRmC/zXgowNZmFcbngndGk922QDmOASEXUZCaY48gs4cg==", - "dev": true - }, - "@types/qs": { - "version": "6.9.7", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", - "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==" - }, - "@types/responselike": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.2.tgz", - "integrity": "sha512-/4YQT5Kp6HxUDb4yhRkm0bJ7TbjvTddqX7PZ5hz6qV3pxSo72f/6YPRo+Mu2DU307tm9IioO69l7uAwn5XNcFA==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "@types/secp256k1": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@types/secp256k1/-/secp256k1-4.0.3.tgz", - "integrity": "sha512-Da66lEIFeIz9ltsdMZcpQvmrmmoqrfju8pm1BH8WbYjZSwUgCwXLb9C+9XYogwBITnbsSaMdVPb2ekf7TV+03w==", - "requires": { - "@types/node": "*" - } - }, - "@typescript-eslint/eslint-plugin": { - "version": "8.18.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.18.1.tgz", - "integrity": "sha512-Ncvsq5CT3Gvh+uJG0Lwlho6suwDfUXH0HztslDf5I+F2wAFAZMRwYLEorumpKLzmO2suAXZ/td1tBg4NZIi9CQ==", - "dev": true, - "requires": { - "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.18.1", - "@typescript-eslint/type-utils": "8.18.1", - "@typescript-eslint/utils": "8.18.1", - "@typescript-eslint/visitor-keys": "8.18.1", - "graphemer": "^1.4.0", - "ignore": "^5.3.1", - "natural-compare": "^1.4.0", - "ts-api-utils": "^1.3.0" - } - }, - "@typescript-eslint/parser": { - "version": "8.18.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.18.1.tgz", - "integrity": "sha512-rBnTWHCdbYM2lh7hjyXqxk70wvon3p2FyaniZuey5TrcGBpfhVp0OxOa6gxr9Q9YhZFKyfbEnxc24ZnVbbUkCA==", - "dev": true, - "requires": { - "@typescript-eslint/scope-manager": "8.18.1", - "@typescript-eslint/types": "8.18.1", - "@typescript-eslint/typescript-estree": "8.18.1", - "@typescript-eslint/visitor-keys": "8.18.1", - "debug": "^4.3.4" - } - }, - "@typescript-eslint/scope-manager": { - "version": "8.18.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.18.1.tgz", - "integrity": "sha512-HxfHo2b090M5s2+/9Z3gkBhI6xBH8OJCFjH9MhQ+nnoZqxU3wNxkLT+VWXWSFWc3UF3Z+CfPAyqdCTdoXtDPCQ==", - "dev": true, - "requires": { - "@typescript-eslint/types": "8.18.1", - "@typescript-eslint/visitor-keys": "8.18.1" - } - }, - "@typescript-eslint/type-utils": { - "version": "8.18.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.18.1.tgz", - "integrity": "sha512-jAhTdK/Qx2NJPNOTxXpMwlOiSymtR2j283TtPqXkKBdH8OAMmhiUfP0kJjc/qSE51Xrq02Gj9NY7MwK+UxVwHQ==", - "dev": true, - "requires": { - "@typescript-eslint/typescript-estree": "8.18.1", - "@typescript-eslint/utils": "8.18.1", - "debug": "^4.3.4", - "ts-api-utils": "^1.3.0" - } - }, - "@typescript-eslint/types": { - "version": "8.18.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.18.1.tgz", - "integrity": "sha512-7uoAUsCj66qdNQNpH2G8MyTFlgerum8ubf21s3TSM3XmKXuIn+H2Sifh/ES2nPOPiYSRJWAk0fDkW0APBWcpfw==", - "dev": true - }, - "@typescript-eslint/typescript-estree": { - "version": "8.18.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.18.1.tgz", - "integrity": "sha512-z8U21WI5txzl2XYOW7i9hJhxoKKNG1kcU4RzyNvKrdZDmbjkmLBo8bgeiOJmA06kizLI76/CCBAAGlTlEeUfyg==", - "dev": true, - "requires": { - "@typescript-eslint/types": "8.18.1", - "@typescript-eslint/visitor-keys": "8.18.1", - "debug": "^4.3.4", - "fast-glob": "^3.3.2", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^1.3.0" - }, - "dependencies": { - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - }, - "semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true - } - } - }, - "@typescript-eslint/utils": { - "version": "8.18.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.18.1.tgz", - "integrity": "sha512-8vikiIj2ebrC4WRdcAdDcmnu9Q/MXXwg+STf40BVfT8exDqBCUPdypvzcUPxEqRGKg9ALagZ0UWcYCtn+4W2iQ==", - "dev": true, - "requires": { - "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.18.1", - "@typescript-eslint/types": "8.18.1", - "@typescript-eslint/typescript-estree": "8.18.1" - } - }, - "@typescript-eslint/visitor-keys": { - "version": "8.18.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.18.1.tgz", - "integrity": "sha512-Vj0WLm5/ZsD013YeUKn+K0y8p1M0jPpxOkKdbD1wB0ns53a5piVY02zjf072TblEweAbcYiFiPoSMF3kp+VhhQ==", - "dev": true, - "requires": { - "@typescript-eslint/types": "8.18.1", - "eslint-visitor-keys": "^4.2.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", - "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", - "dev": true - } - } - }, - "@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", - "dev": true - }, - "abbrev": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz", - "integrity": "sha512-LEyx4aLEC3x6T0UguF6YILf+ntvmOaWsVfENmIW0E9H09vKlLDGelMjjSm0jkDHALj8A8quZ/HapKNigzwge+Q==", - "dev": true - }, - "abort-controller": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", - "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", - "dev": true, - "requires": { - "event-target-shim": "^5.0.0" - } - }, - "acorn": { - "version": "8.14.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", - "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==" - }, - "acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "requires": {} - }, - "acorn-walk": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==" - }, - "adm-zip": { - "version": "0.4.16", - "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.16.tgz", - "integrity": "sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg==" - }, - "aes-js": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.0.0.tgz", - "integrity": "sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw==" - }, - "agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "requires": { - "debug": "4" - } - }, - "aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "requires": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - } - }, - "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "amdefine": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", - "integrity": "sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg==", - "dev": true, - "optional": true - }, - "ansi-align": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", - "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", - "requires": { - "string-width": "^4.1.0" - } - }, - "ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==" - }, - "ansi-escapes": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.0.0.tgz", - "integrity": "sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==", - "dev": true, - "requires": { - "environment": "^1.0.0" - } - }, - "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" - } - }, - "antlr4": { - "version": "4.13.2", - "resolved": "https://registry.npmjs.org/antlr4/-/antlr4-4.13.2.tgz", - "integrity": "sha512-QiVbZhyy4xAZ17UPEuG3YTOt8ZaoeOR1CvEAqrEsDBsOqINslaB147i9xqljZqoyf5S+EUlGStaj+t22LT9MOg==", - "dev": true - }, - "anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - } - }, - "arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==" - }, - "argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" - }, - "array-back": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", - "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", - "dev": true - }, - "array-buffer-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", - "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", - "dev": true, - "requires": { - "call-bind": "^1.0.5", - "is-array-buffer": "^3.0.4" - } - }, - "array-includes": { - "version": "3.1.8", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", - "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", - "dev": true, - "requires": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-object-atoms": "^1.0.0", - "get-intrinsic": "^1.2.4", - "is-string": "^1.0.7" - } - }, - "array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true - }, - "array.prototype.findlastindex": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", - "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", - "dev": true, - "requires": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "es-shim-unscopables": "^1.0.2" - } - }, - "array.prototype.flat": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", - "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" - } - }, - "array.prototype.flatmap": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", - "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0" - } - }, - "arraybuffer.prototype.slice": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", - "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", - "dev": true, - "requires": { - "array-buffer-byte-length": "^1.0.1", - "call-bind": "^1.0.5", - "define-properties": "^1.2.1", - "es-abstract": "^1.22.3", - "es-errors": "^1.2.1", - "get-intrinsic": "^1.2.3", - "is-array-buffer": "^3.0.4", - "is-shared-array-buffer": "^1.0.2" - } - }, - "assertion-error": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", - "dev": true - }, - "assertion-tools": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/assertion-tools/-/assertion-tools-2.2.1.tgz", - "integrity": "sha512-JlA1S16Ox93PnYb45HvxNcax/Ii4gqTO8HLGa/ykj/ddp8EEHlokn6inJR2yMiz173WSFkCc0ciLJzGeaYBANw==", - "dev": true, - "requires": { - "ethers": "^5.7.2", - "jsonld": "^8.1.0", - "merkletreejs": "^0.3.2" - }, - "dependencies": { - "ethers": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.7.2.tgz", - "integrity": "sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg==", - "dev": true, - "requires": { - "@ethersproject/abi": "5.7.0", - "@ethersproject/abstract-provider": "5.7.0", - "@ethersproject/abstract-signer": "5.7.0", - "@ethersproject/address": "5.7.0", - "@ethersproject/base64": "5.7.0", - "@ethersproject/basex": "5.7.0", - "@ethersproject/bignumber": "5.7.0", - "@ethersproject/bytes": "5.7.0", - "@ethersproject/constants": "5.7.0", - "@ethersproject/contracts": "5.7.0", - "@ethersproject/hash": "5.7.0", - "@ethersproject/hdnode": "5.7.0", - "@ethersproject/json-wallets": "5.7.0", - "@ethersproject/keccak256": "5.7.0", - "@ethersproject/logger": "5.7.0", - "@ethersproject/networks": "5.7.1", - "@ethersproject/pbkdf2": "5.7.0", - "@ethersproject/properties": "5.7.0", - "@ethersproject/providers": "5.7.2", - "@ethersproject/random": "5.7.0", - "@ethersproject/rlp": "5.7.0", - "@ethersproject/sha2": "5.7.0", - "@ethersproject/signing-key": "5.7.0", - "@ethersproject/solidity": "5.7.0", - "@ethersproject/strings": "5.7.0", - "@ethersproject/transactions": "5.7.0", - "@ethersproject/units": "5.7.0", - "@ethersproject/wallet": "5.7.0", - "@ethersproject/web": "5.7.1", - "@ethersproject/wordlists": "5.7.0" - } - } - } - }, - "ast-parents": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/ast-parents/-/ast-parents-0.0.1.tgz", - "integrity": "sha512-XHusKxKz3zoYk1ic8Un640joHbFMhbqneyoZfoKnEGtf2ey9Uh/IdpcQplODdO/kENaMIWsD0nJm4+wX3UNLHA==", - "dev": true - }, - "astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true - }, - "async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha512-nSVgobk4rv61R9PUSDtYt7mPVB2olxNR5RWJcAsH676/ef11bUZwvu7+RGYrYauVdDPcO519v68wRhXQtxsV9w==", - "dev": true - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" - }, - "at-least-node": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", - "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", - "dev": true - }, - "available-typed-arrays": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", - "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", - "dev": true, - "requires": { - "possible-typed-array-names": "^1.0.0" - } - }, - "axios": { - "version": "0.21.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", - "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", - "requires": { - "follow-redirects": "^1.14.0" - } - }, - "balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, - "base-x": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.9.tgz", - "integrity": "sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==", - "requires": { - "safe-buffer": "^5.0.1" - } - }, - "bech32": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz", - "integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==" - }, - "bignumber.js": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.0.tgz", - "integrity": "sha512-4LwHK4nfDOraBCtst+wOWIHbu1vhvAPJK8g8nROd4iuc3PSEjWif/qwbkh8jwCJz6yDBvtU4KPynETgrfh7y3A==", - "dev": true - }, - "binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==" - }, - "blakejs": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/blakejs/-/blakejs-1.2.1.tgz", - "integrity": "sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ==" - }, - "bn.js": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", - "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==" - }, - "boxen": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz", - "integrity": "sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==", - "requires": { - "ansi-align": "^3.0.0", - "camelcase": "^6.2.0", - "chalk": "^4.1.0", - "cli-boxes": "^2.2.1", - "string-width": "^4.2.2", - "type-fest": "^0.20.2", - "widest-line": "^3.1.0", - "wrap-ansi": "^7.0.0" - } - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "requires": { - "fill-range": "^7.1.1" - } - }, - "brorand": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==" - }, - "brotli-wasm": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brotli-wasm/-/brotli-wasm-2.0.1.tgz", - "integrity": "sha512-+3USgYsC7bzb5yU0/p2HnnynZl0ak0E6uoIm4UW4Aby/8s8HFCq6NCfrrf1E9c3O8OCSzq3oYO1tUVqIi61Nww==", - "dev": true - }, - "browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==" - }, - "browserify-aes": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", - "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", - "requires": { - "buffer-xor": "^1.0.3", - "cipher-base": "^1.0.0", - "create-hash": "^1.1.0", - "evp_bytestokey": "^1.0.3", - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "bs58": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", - "integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==", - "requires": { - "base-x": "^3.0.2" - } - }, - "bs58check": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/bs58check/-/bs58check-2.1.2.tgz", - "integrity": "sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==", - "requires": { - "bs58": "^4.0.0", - "create-hash": "^1.1.0", - "safe-buffer": "^5.1.2" - } - }, - "buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" - }, - "buffer-reverse": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/buffer-reverse/-/buffer-reverse-1.0.1.tgz", - "integrity": "sha512-M87YIUBsZ6N924W57vDwT/aOu8hw7ZgdByz6ijksLjmHJELBASmYTTlNHRgjE+pTsT9oJXGaDSgqqwfdHotDUg==", - "dev": true - }, - "buffer-xor": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", - "integrity": "sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==" - }, - "bufferutil": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.6.tgz", - "integrity": "sha512-jduaYOYtnio4aIAyc6UbvPCVcgq7nYpVnucyxr6eCYg/Woad9Hf/oxxBRDnGGjPfjUm6j5O/uBWhIu4iLebFaw==", - "optional": true, - "peer": true, - "requires": { - "node-gyp-build": "^4.3.0" - } - }, - "bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==" - }, - "cacheable-lookup": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-6.1.0.tgz", - "integrity": "sha512-KJ/Dmo1lDDhmW2XDPMo+9oiy/CeqosPguPCrgcVzKyZrL6pM1gU2GmPY/xo6OQPTUaA/c0kwHuywB4E6nmT9ww==", - "dev": true - }, - "cacheable-request": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.4.tgz", - "integrity": "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==", - "dev": true, - "requires": { - "clone-response": "^1.0.2", - "get-stream": "^5.1.0", - "http-cache-semantics": "^4.0.0", - "keyv": "^4.0.0", - "lowercase-keys": "^2.0.0", - "normalize-url": "^6.0.1", - "responselike": "^2.0.0" - }, - "dependencies": { - "get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, - "requires": { - "pump": "^3.0.0" - } - }, - "lowercase-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", - "dev": true - } - } - }, - "call-bind": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", - "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", - "requires": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.1" - } - }, - "callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true - }, - "camelcase": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.1.tgz", - "integrity": "sha512-tVI4q5jjFV5CavAU8DXfza/TJcZutVKo/5Foskmsqcm0MsL91moHvwiGNnqaa2o6PF/7yT5ikDRcVcl8Rj6LCA==" - }, - "canonicalize": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/canonicalize/-/canonicalize-1.0.8.tgz", - "integrity": "sha512-0CNTVCLZggSh7bc5VkX5WWPWO+cyZbNd07IHIsSXLia/eAq+r836hgk+8BKoEh7949Mda87VUOitx5OddVj64A==", - "dev": true - }, - "chai": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.5.0.tgz", - "integrity": "sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw==", - "dev": true, - "requires": { - "assertion-error": "^1.1.0", - "check-error": "^1.0.3", - "deep-eql": "^4.1.3", - "get-func-name": "^2.0.2", - "loupe": "^2.3.6", - "pathval": "^1.1.1", - "type-detect": "^4.1.0" - } - }, - "chai-as-promised": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-7.1.1.tgz", - "integrity": "sha512-azL6xMoi+uxu6z4rhWQ1jbdUhOMhis2PvscD/xjLqNMkv3BPPp2JyyuTHOrf9BOosGpNQ11v6BKv/g57RXbiaA==", - "dev": true, - "requires": { - "check-error": "^1.0.2" - } - }, - "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" - } - }, - "charenc": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", - "integrity": "sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==", - "dev": true - }, - "check-error": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.3.tgz", - "integrity": "sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==", - "dev": true, - "requires": { - "get-func-name": "^2.0.2" - } - }, - "chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "requires": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "fsevents": "~2.3.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "dependencies": { - "readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "requires": { - "picomatch": "^2.2.1" - } - } - } - }, - "ci-info": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", - "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==" - }, - "cipher-base": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", - "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", - "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==" - }, - "cli-boxes": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", - "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==" - }, - "cli-cursor": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", - "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", - "dev": true, - "requires": { - "restore-cursor": "^5.0.0" - } - }, - "cli-table3": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.5.tgz", - "integrity": "sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==", - "dev": true, - "requires": { - "@colors/colors": "1.5.0", - "string-width": "^4.2.0" - } - }, - "cli-truncate": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz", - "integrity": "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==", - "dev": true, - "requires": { - "slice-ansi": "^5.0.0", - "string-width": "^7.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", - "dev": true - }, - "ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true - }, - "emoji-regex": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", - "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", - "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", - "dev": true - }, - "slice-ansi": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", - "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", - "dev": true, - "requires": { - "ansi-styles": "^6.0.0", - "is-fullwidth-code-point": "^4.0.0" - } - }, - "string-width": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", - "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", - "dev": true, - "requires": { - "emoji-regex": "^10.3.0", - "get-east-asian-width": "^1.0.0", - "strip-ansi": "^7.1.0" - } - }, - "strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "requires": { - "ansi-regex": "^6.0.1" - } - } - } - }, - "cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" - } - }, - "clone-response": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", - "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", - "dev": true, - "requires": { - "mimic-response": "^1.0.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==" - }, - "colorette": { - "version": "2.0.20", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", - "dev": true - }, - "combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "requires": { - "delayed-stream": "~1.0.0" - } - }, - "command-exists": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.9.tgz", - "integrity": "sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==" - }, - "command-line-args": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.2.1.tgz", - "integrity": "sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg==", - "dev": true, - "requires": { - "array-back": "^3.1.0", - "find-replace": "^3.0.0", - "lodash.camelcase": "^4.3.0", - "typical": "^4.0.0" - } - }, - "command-line-usage": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/command-line-usage/-/command-line-usage-6.1.3.tgz", - "integrity": "sha512-sH5ZSPr+7UStsloltmDh7Ce5fb8XPlHyoPzTpyyMuYCtervL65+ubVZ6Q61cFtFl62UyJlc8/JwERRbAFPUqgw==", - "dev": true, - "requires": { - "array-back": "^4.0.2", - "chalk": "^2.4.2", - "table-layout": "^1.0.2", - "typical": "^5.2.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "array-back": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.2.tgz", - "integrity": "sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg==", - "dev": true - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "typical": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", - "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", - "dev": true - } - } - }, - "commander": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", - "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" - }, - "config-chain": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", - "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", - "dev": true, - "requires": { - "ini": "^1.3.4", - "proto-list": "~1.2.1" - } - }, - "cosmiconfig": { - "version": "8.3.6", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", - "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", - "dev": true, - "requires": { - "import-fresh": "^3.3.0", - "js-yaml": "^4.1.0", - "parse-json": "^5.2.0", - "path-type": "^4.0.0" - } - }, - "create-hash": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", - "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", - "requires": { - "cipher-base": "^1.0.1", - "inherits": "^2.0.1", - "md5.js": "^1.3.4", - "ripemd160": "^2.0.1", - "sha.js": "^2.4.0" - } - }, - "create-hmac": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", - "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", - "requires": { - "cipher-base": "^1.0.3", - "create-hash": "^1.1.0", - "inherits": "^2.0.1", - "ripemd160": "^2.0.0", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - } - }, - "create-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==" - }, - "cross-env": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", - "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.1" - } - }, - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "crypt": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", - "integrity": "sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==", - "dev": true - }, - "crypto-js": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.2.0.tgz", - "integrity": "sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==", - "dev": true - }, - "data-uri-to-buffer": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.0.tgz", - "integrity": "sha512-Vr3mLBA8qWmcuschSLAOogKgQ/Jwxulv3RNE4FXnYWRGujzrRWQI4m12fQqRkwX06C0KanhLr4hK+GydchZsaA==" - }, - "data-view-buffer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", - "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", - "dev": true, - "requires": { - "call-bind": "^1.0.6", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" - } - }, - "data-view-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", - "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", - "dev": true, - "requires": { - "call-bind": "^1.0.7", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" - } - }, - "data-view-byte-offset": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", - "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", - "dev": true, - "requires": { - "call-bind": "^1.0.6", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" - } - }, - "death": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/death/-/death-1.1.0.tgz", - "integrity": "sha512-vsV6S4KVHvTGxbEcij7hkWRv0It+sGGWVOM67dQde/o5Xjnr+KmLjxWJii2uEObIrt1CcM9w0Yaovx+iOlIL+w==", - "dev": true - }, - "debug": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", - "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", - "requires": { - "ms": "^2.1.3" - } - }, - "decamelize": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==" - }, - "decompress-response": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", - "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", - "dev": true, - "requires": { - "mimic-response": "^3.1.0" - }, - "dependencies": { - "mimic-response": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", - "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", - "dev": true - } - } - }, - "deep-eql": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", - "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==", - "dev": true, - "requires": { - "type-detect": "^4.0.0" - } - }, - "deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "dev": true - }, - "deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "defer-to-connect": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", - "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", - "dev": true - }, - "define-data-property": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "requires": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" - } - }, - "define-properties": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", - "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", - "dev": true, - "requires": { - "define-data-property": "^1.0.1", - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - } - }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" - }, - "delete-empty": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/delete-empty/-/delete-empty-3.0.0.tgz", - "integrity": "sha512-ZUyiwo76W+DYnKsL3Kim6M/UOavPdBJgDYWOmuQhYaZvJH0AXAHbUNyEDtRbBra8wqqr686+63/0azfEk1ebUQ==", - "dev": true, - "requires": { - "ansi-colors": "^4.1.0", - "minimist": "^1.2.0", - "path-starts-with": "^2.0.0", - "rimraf": "^2.6.2" - }, - "dependencies": { - "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - } - } - }, - "depd": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", - "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" - }, - "diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==" - }, - "difflib": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/difflib/-/difflib-0.2.4.tgz", - "integrity": "sha512-9YVwmMb0wQHQNr5J9m6BSj6fk4pfGITGQOOs+D9Fl+INODWFOfvhIU1hNv6GgR1RBoC/9NJcwu77zShxV0kT7w==", - "dev": true, - "requires": { - "heap": ">= 0.2.0" - } - }, - "dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "requires": { - "path-type": "^4.0.0" - } - }, - "doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - }, - "dotenv": { - "version": "16.4.7", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz", - "integrity": "sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==" - }, - "eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true - }, - "elliptic": { - "version": "6.5.4", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", - "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", - "requires": { - "bn.js": "^4.11.9", - "brorand": "^1.1.0", - "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.1", - "inherits": "^2.0.4", - "minimalistic-assert": "^1.0.1", - "minimalistic-crypto-utils": "^1.0.1" - }, - "dependencies": { - "bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - } - } - }, - "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==" - }, - "encode-utf8": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/encode-utf8/-/encode-utf8-1.0.3.tgz", - "integrity": "sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw==" - }, - "end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "requires": { - "once": "^1.4.0" - } - }, - "enhanced-resolve": { - "version": "5.17.1", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", - "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - } - }, - "enquirer": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", - "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", - "requires": { - "ansi-colors": "^4.1.1" - } - }, - "env-paths": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", - "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==" - }, - "environment": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", - "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", - "dev": true - }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "requires": { - "is-arrayish": "^0.2.1" - } - }, - "es-abstract": { - "version": "1.23.5", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.5.tgz", - "integrity": "sha512-vlmniQ0WNPwXqA0BnmwV3Ng7HxiGlh6r5U6JcTMNx8OilcAGqVJBHJcPjqOMaczU9fRuRK5Px2BdVyPRnKMMVQ==", - "dev": true, - "requires": { - "array-buffer-byte-length": "^1.0.1", - "arraybuffer.prototype.slice": "^1.0.3", - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", - "data-view-buffer": "^1.0.1", - "data-view-byte-length": "^1.0.1", - "data-view-byte-offset": "^1.0.0", - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "es-set-tostringtag": "^2.0.3", - "es-to-primitive": "^1.2.1", - "function.prototype.name": "^1.1.6", - "get-intrinsic": "^1.2.4", - "get-symbol-description": "^1.0.2", - "globalthis": "^1.0.4", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2", - "has-proto": "^1.0.3", - "has-symbols": "^1.0.3", - "hasown": "^2.0.2", - "internal-slot": "^1.0.7", - "is-array-buffer": "^3.0.4", - "is-callable": "^1.2.7", - "is-data-view": "^1.0.1", - "is-negative-zero": "^2.0.3", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.3", - "is-string": "^1.0.7", - "is-typed-array": "^1.1.13", - "is-weakref": "^1.0.2", - "object-inspect": "^1.13.3", - "object-keys": "^1.1.1", - "object.assign": "^4.1.5", - "regexp.prototype.flags": "^1.5.3", - "safe-array-concat": "^1.1.2", - "safe-regex-test": "^1.0.3", - "string.prototype.trim": "^1.2.9", - "string.prototype.trimend": "^1.0.8", - "string.prototype.trimstart": "^1.0.8", - "typed-array-buffer": "^1.0.2", - "typed-array-byte-length": "^1.0.1", - "typed-array-byte-offset": "^1.0.2", - "typed-array-length": "^1.0.6", - "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.15" - } - }, - "es-define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", - "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", - "requires": { - "get-intrinsic": "^1.2.4" - } - }, - "es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==" - }, - "es-object-atoms": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", - "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", - "dev": true, - "requires": { - "es-errors": "^1.3.0" - } - }, - "es-set-tostringtag": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", - "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", - "dev": true, - "requires": { - "get-intrinsic": "^1.2.4", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.1" - } - }, - "es-shim-unscopables": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", - "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", - "dev": true, - "requires": { - "hasown": "^2.0.0" - } - }, - "es-to-primitive": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz", - "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==", - "dev": true, - "requires": { - "is-callable": "^1.2.7", - "is-date-object": "^1.0.5", - "is-symbol": "^1.0.4" - } - }, - "escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==" - }, - "escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==" - }, - "escodegen": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.8.1.tgz", - "integrity": "sha512-yhi5S+mNTOuRvyW4gWlg5W1byMaQGWWSYHXsuFZ7GBo7tpyOwi2EdzMP/QWxh9hwkD2m+wDVHJsxhRIj+v/b/A==", - "dev": true, - "requires": { - "esprima": "^2.7.1", - "estraverse": "^1.9.1", - "esutils": "^2.0.2", - "optionator": "^0.8.1", - "source-map": "~0.2.0" - }, - "dependencies": { - "esprima": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", - "integrity": "sha512-OarPfz0lFCiW4/AV2Oy1Rp9qu0iusTKqykwTspGCZtPxmF81JR4MmIebvF1F9+UOKth2ZubLQ4XGGaU+hSn99A==", - "dev": true - }, - "estraverse": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", - "integrity": "sha512-25w1fMXQrGdoquWnScXZGckOv+Wes+JDnuN/+7ex3SauFRS72r2lFDec0EKPt2YD1wUJ/IrfEex+9yp4hfSOJA==", - "dev": true - }, - "levn": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", - "integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==", - "dev": true, - "requires": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" - } - }, - "optionator": { - "version": "0.8.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", - "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", - "dev": true, - "requires": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.6", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "word-wrap": "~1.2.3" - } - }, - "prelude-ls": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", - "integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==", - "dev": true - }, - "type-check": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", - "integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==", - "dev": true, - "requires": { - "prelude-ls": "~1.1.2" - } - } - } - }, - "eslint": { - "version": "8.57.1", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", - "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", - "dev": true, - "requires": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.1", - "@humanwhocodes/config-array": "^0.13.0", - "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" - }, - "dependencies": { - "glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "requires": { - "is-glob": "^4.0.3" - } - } - } - }, - "eslint-config-prettier": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", - "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", - "dev": true, - "requires": {} - }, - "eslint-import-resolver-node": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", - "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", - "dev": true, - "requires": { - "debug": "^3.2.7", - "is-core-module": "^2.13.0", - "resolve": "^1.22.4" - }, - "dependencies": { - "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - } - } - }, - "eslint-import-resolver-typescript": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.7.0.tgz", - "integrity": "sha512-Vrwyi8HHxY97K5ebydMtffsWAn1SCR9eol49eCd5fJS4O1WV7PaAjbcjmbfJJSMz/t4Mal212Uz/fQZrOB8mow==", - "dev": true, - "requires": { - "@nolyfill/is-core-module": "1.0.39", - "debug": "^4.3.7", - "enhanced-resolve": "^5.15.0", - "fast-glob": "^3.3.2", - "get-tsconfig": "^4.7.5", - "is-bun-module": "^1.0.2", - "is-glob": "^4.0.3", - "stable-hash": "^0.0.4" - } - }, - "eslint-module-utils": { - "version": "2.12.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.0.tgz", - "integrity": "sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg==", - "dev": true, - "requires": { - "debug": "^3.2.7" - }, - "dependencies": { - "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - } - } - }, - "eslint-plugin-import": { - "version": "2.31.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.31.0.tgz", - "integrity": "sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A==", - "dev": true, - "requires": { - "@rtsao/scc": "^1.1.0", - "array-includes": "^3.1.8", - "array.prototype.findlastindex": "^1.2.5", - "array.prototype.flat": "^1.3.2", - "array.prototype.flatmap": "^1.3.2", - "debug": "^3.2.7", - "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.9", - "eslint-module-utils": "^2.12.0", - "hasown": "^2.0.2", - "is-core-module": "^2.15.1", - "is-glob": "^4.0.3", - "minimatch": "^3.1.2", - "object.fromentries": "^2.0.8", - "object.groupby": "^1.0.3", - "object.values": "^1.2.0", - "semver": "^6.3.1", - "string.prototype.trimend": "^1.0.8", - "tsconfig-paths": "^3.15.0" - }, - "dependencies": { - "debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "doctrine": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", - "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", - "dev": true, - "requires": { - "esutils": "^2.0.2" - } - } - } - }, - "eslint-plugin-mocha": { - "version": "10.5.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-mocha/-/eslint-plugin-mocha-10.5.0.tgz", - "integrity": "sha512-F2ALmQVPT1GoP27O1JTZGrV9Pqg8k79OeIuvw63UxMtQKREZtmkK1NFgkZQ2TW7L2JSSFKHFPTtHu5z8R9QNRw==", - "dev": true, - "requires": { - "eslint-utils": "^3.0.0", - "globals": "^13.24.0", - "rambda": "^7.4.0" - } - }, - "eslint-plugin-prettier": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.1.tgz", - "integrity": "sha512-gH3iR3g4JfF+yYPaJYkN7jEl9QbweL/YfkoRlNnuIEHEz1vHVlCmWOS+eGGiRuzHQXdJFCOTxRgvju9b8VUmrw==", - "dev": true, - "requires": { - "prettier-linter-helpers": "^1.0.0", - "synckit": "^0.9.1" - } - }, - "eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", - "dev": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - } - }, - "eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, - "requires": { - "eslint-visitor-keys": "^2.0.0" - }, - "dependencies": { - "eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", - "dev": true - } - } - }, - "eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true - }, - "espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", - "dev": true, - "requires": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" - } - }, - "esquery": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", - "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", - "dev": true, - "requires": { - "estraverse": "^5.1.0" - } - }, - "esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "requires": { - "estraverse": "^5.2.0" - } - }, - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true - }, - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true - }, - "ethereum-bloom-filters": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/ethereum-bloom-filters/-/ethereum-bloom-filters-1.0.10.tgz", - "integrity": "sha512-rxJ5OFN3RwjQxDcFP2Z5+Q9ho4eIdEmSc2ht0fCu8Se9nbXjZ7/031uXoUYJ87KHCOdVeiUuwSnoS7hmYAGVHA==", - "dev": true, - "requires": { - "js-sha3": "^0.8.0" - } - }, - "ethereum-cryptography": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-1.1.2.tgz", - "integrity": "sha512-XDSJlg4BD+hq9N2FjvotwUET9Tfxpxc3kWGE2AqUG5vcbeunnbImVk3cj6e/xT3phdW21mE8R5IugU4fspQDcQ==", - "requires": { - "@noble/hashes": "1.1.2", - "@noble/secp256k1": "1.6.3", - "@scure/bip32": "1.1.0", - "@scure/bip39": "1.1.0" - } - }, - "ethereumjs-abi": { - "version": "git+ssh://git@github.com/ethereumjs/ethereumjs-abi.git#ee3994657fa7a427238e6ba92a84d0b529bbcde0", - "from": "ethereumjs-abi@^0.6.8", - "requires": { - "bn.js": "^4.11.8", - "ethereumjs-util": "^6.0.0" - }, - "dependencies": { - "@types/bn.js": { - "version": "4.11.6", - "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz", - "integrity": "sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==", - "requires": { - "@types/node": "*" - } - }, - "bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" - }, - "ethereum-cryptography": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", - "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", - "requires": { - "@types/pbkdf2": "^3.0.0", - "@types/secp256k1": "^4.0.1", - "blakejs": "^1.1.0", - "browserify-aes": "^1.2.0", - "bs58check": "^2.1.2", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "hash.js": "^1.1.7", - "keccak": "^3.0.0", - "pbkdf2": "^3.0.17", - "randombytes": "^2.1.0", - "safe-buffer": "^5.1.2", - "scrypt-js": "^3.0.0", - "secp256k1": "^4.0.1", - "setimmediate": "^1.0.5" - } - }, - "ethereumjs-util": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz", - "integrity": "sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==", - "requires": { - "@types/bn.js": "^4.11.3", - "bn.js": "^4.11.0", - "create-hash": "^1.1.2", - "elliptic": "^6.5.2", - "ethereum-cryptography": "^0.1.3", - "ethjs-util": "0.1.6", - "rlp": "^2.2.3" - } - } - } - }, - "ethereumjs-util": { - "version": "7.1.5", - "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.1.5.tgz", - "integrity": "sha512-SDl5kKrQAudFBUe5OJM9Ac6WmMyYmXX/6sTmLZ3ffG2eY6ZIGBes3pEDxNN6V72WyOw4CPD5RomKdsa8DAAwLg==", - "dev": true, - "requires": { - "@types/bn.js": "^5.1.0", - "bn.js": "^5.1.2", - "create-hash": "^1.1.2", - "ethereum-cryptography": "^0.1.3", - "rlp": "^2.2.4" - }, - "dependencies": { - "ethereum-cryptography": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", - "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", - "dev": true, - "requires": { - "@types/pbkdf2": "^3.0.0", - "@types/secp256k1": "^4.0.1", - "blakejs": "^1.1.0", - "browserify-aes": "^1.2.0", - "bs58check": "^2.1.2", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "hash.js": "^1.1.7", - "keccak": "^3.0.0", - "pbkdf2": "^3.0.17", - "randombytes": "^2.1.0", - "safe-buffer": "^5.1.2", - "scrypt-js": "^3.0.0", - "secp256k1": "^4.0.1", - "setimmediate": "^1.0.5" - } - } - } - }, - "ethers": { - "version": "6.13.4", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.13.4.tgz", - "integrity": "sha512-21YtnZVg4/zKkCQPjrDj38B1r4nQvTZLopUGMLQ1ePU2zV/joCfDC3t3iKQjWRzjjjbzR+mdAIoikeBRNkdllA==", - "requires": { - "@adraffy/ens-normalize": "1.10.1", - "@noble/curves": "1.2.0", - "@noble/hashes": "1.3.2", - "@types/node": "22.7.5", - "aes-js": "4.0.0-beta.5", - "tslib": "2.7.0", - "ws": "8.17.1" - }, - "dependencies": { - "@adraffy/ens-normalize": { - "version": "1.10.1", - "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz", - "integrity": "sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==" - }, - "@noble/curves": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz", - "integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==", - "requires": { - "@noble/hashes": "1.3.2" - } - }, - "@noble/hashes": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", - "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==" - }, - "@types/node": { - "version": "22.7.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.5.tgz", - "integrity": "sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==", - "requires": { - "undici-types": "~6.19.2" - } - }, - "aes-js": { - "version": "4.0.0-beta.5", - "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-4.0.0-beta.5.tgz", - "integrity": "sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==" - }, - "tslib": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", - "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==" - }, - "ws": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", - "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", - "requires": {} - } - } - }, - "ethjs-unit": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/ethjs-unit/-/ethjs-unit-0.1.6.tgz", - "integrity": "sha512-/Sn9Y0oKl0uqQuvgFk/zQgR7aw1g36qX/jzSQ5lSwlO0GigPymk4eGQfeNTD03w1dPOqfz8V77Cy43jH56pagw==", - "dev": true, - "requires": { - "bn.js": "4.11.6", - "number-to-bn": "1.7.0" - }, - "dependencies": { - "bn.js": { - "version": "4.11.6", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", - "integrity": "sha512-XWwnNNFCuuSQ0m3r3C4LE3EiORltHd9M05pq6FOlVeiophzRbMo50Sbz1ehl8K3Z+jw9+vmgnXefY1hz8X+2wA==", - "dev": true - } - } - }, - "ethjs-util": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/ethjs-util/-/ethjs-util-0.1.6.tgz", - "integrity": "sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==", - "requires": { - "is-hex-prefixed": "1.0.0", - "strip-hex-prefix": "1.0.0" - } - }, - "event-target-shim": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", - "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", - "dev": true - }, - "eventemitter3": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", - "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==" - }, - "evp_bytestokey": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", - "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", - "requires": { - "md5.js": "^1.3.4", - "safe-buffer": "^5.1.1" - } - }, - "execa": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", - "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.3", - "get-stream": "^8.0.1", - "human-signals": "^5.0.0", - "is-stream": "^3.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^5.1.0", - "onetime": "^6.0.0", - "signal-exit": "^4.1.0", - "strip-final-newline": "^3.0.0" - }, - "dependencies": { - "get-stream": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", - "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", - "dev": true - } - } - }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "fast-diff": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", - "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", - "dev": true - }, - "fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", - "dev": true, - "requires": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - } - }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true - }, - "fast-uri": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.3.tgz", - "integrity": "sha512-aLrHthzCjH5He4Z2H9YZ+v6Ujb9ocRuW6ZzkJQOrTxleEijANq4v1TsaPaVG1PZcuurEzrLcWRyYBYXD5cEiaw==", - "dev": true - }, - "fastq": { - "version": "1.13.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz", - "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==", - "dev": true, - "requires": { - "reusify": "^1.0.4" - } - }, - "fetch-blob": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", - "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", - "requires": { - "node-domexception": "^1.0.0", - "web-streams-polyfill": "^3.0.3" - } - }, - "file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "requires": { - "flat-cache": "^3.0.4" - } - }, - "fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "find-replace": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-3.0.0.tgz", - "integrity": "sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ==", - "dev": true, - "requires": { - "array-back": "^3.0.1" - } - }, - "find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "requires": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - } - }, - "flat": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==" - }, - "flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", - "dev": true, - "requires": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" - } - }, - "flatted": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", - "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", - "dev": true - }, - "fmix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/fmix/-/fmix-0.1.0.tgz", - "integrity": "sha512-Y6hyofImk9JdzU8k5INtTXX1cu8LDlePWDFU5sftm9H+zKCr5SGrVjdhkvsim646cw5zD0nADj8oHyXMZmCZ9w==", - "requires": { - "imul": "^1.0.0" - } - }, - "follow-redirects": { - "version": "1.15.6", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", - "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==" - }, - "for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", - "dev": true, - "requires": { - "is-callable": "^1.1.3" - } - }, - "foreground-child": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", - "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.0", - "signal-exit": "^4.0.1" - } - }, - "form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - } - }, - "form-data-encoder": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-1.7.1.tgz", - "integrity": "sha512-EFRDrsMm/kyqbTQocNvRXMLjc7Es2Vk+IQFx/YW7hkUH1eBl4J1fqiP34l74Yt0pFLCNpc06fkbVk00008mzjg==", - "dev": true - }, - "formdata-polyfill": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", - "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", - "requires": { - "fetch-blob": "^3.1.2" - } - }, - "fp-ts": { - "version": "1.19.3", - "resolved": "https://registry.npmjs.org/fp-ts/-/fp-ts-1.19.3.tgz", - "integrity": "sha512-H5KQDspykdHuztLTg+ajGN0Z2qUjcEf3Ybxc6hLt0k7/zPkn29XnKnxlBPyW2XIddWrGaJBzBl4VLYOtk39yZg==" - }, - "fs-extra": { - "version": "11.2.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", - "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "dependencies": { - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - } - }, - "universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true - } - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" - }, - "fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "optional": true - }, - "function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==" - }, - "function.prototype.name": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", - "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "functions-have-names": "^1.2.3" - } - }, - "functions-have-names": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", - "dev": true - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" - }, - "get-east-asian-width": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.3.0.tgz", - "integrity": "sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==", - "dev": true - }, - "get-func-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.2.tgz", - "integrity": "sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==", - "dev": true - }, - "get-intrinsic": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", - "requires": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" - } - }, - "get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true - }, - "get-symbol-description": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", - "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", - "dev": true, - "requires": { - "call-bind": "^1.0.5", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4" - } - }, - "get-tsconfig": { - "version": "4.8.1", - "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.8.1.tgz", - "integrity": "sha512-k9PN+cFBmaLWtVz29SkUoqU5O0slLuHJXt/2P+tMVFT+phsSGXGkp9t3rQIqdz0e+06EHNGs3oM6ZX1s2zHxRg==", - "dev": true, - "requires": { - "resolve-pkg-maps": "^1.0.0" - } - }, - "ghost-testrpc": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/ghost-testrpc/-/ghost-testrpc-0.0.2.tgz", - "integrity": "sha512-i08dAEgJ2g8z5buJIrCTduwPIhih3DP+hOCTyyryikfV8T0bNvHnGXO67i0DD1H4GBDETTclPy9njZbfluQYrQ==", - "dev": true, - "requires": { - "chalk": "^2.4.2", - "node-emoji": "^1.10.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "glob": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", - "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "requires": { - "is-glob": "^4.0.1" - } - }, - "global-modules": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", - "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", - "dev": true, - "requires": { - "global-prefix": "^3.0.0" - } - }, - "global-prefix": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", - "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", - "dev": true, - "requires": { - "ini": "^1.3.5", - "kind-of": "^6.0.2", - "which": "^1.3.1" - }, - "dependencies": { - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } - } - }, - "globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "dev": true, - "requires": { - "type-fest": "^0.20.2" - } - }, - "globalthis": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", - "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", - "dev": true, - "requires": { - "define-properties": "^1.2.1", - "gopd": "^1.0.1" - } - }, - "gopd": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", - "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==" - }, - "got": { - "version": "12.1.0", - "resolved": "https://registry.npmjs.org/got/-/got-12.1.0.tgz", - "integrity": "sha512-hBv2ty9QN2RdbJJMK3hesmSkFTjVIHyIDDbssCKnSmq62edGgImJWD10Eb1k77TiV1bxloxqcFAVK8+9pkhOig==", - "dev": true, - "requires": { - "@sindresorhus/is": "^4.6.0", - "@szmarczak/http-timer": "^5.0.1", - "@types/cacheable-request": "^6.0.2", - "@types/responselike": "^1.0.0", - "cacheable-lookup": "^6.0.4", - "cacheable-request": "^7.0.2", - "decompress-response": "^6.0.0", - "form-data-encoder": "1.7.1", - "get-stream": "^6.0.1", - "http2-wrapper": "^2.1.10", - "lowercase-keys": "^3.0.0", - "p-cancelable": "^3.0.0", - "responselike": "^2.0.0" - } - }, - "graceful-fs": { - "version": "4.2.10", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" - }, - "graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true - }, - "handlebars": { - "version": "4.7.8", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", - "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", - "dev": true, - "requires": { - "minimist": "^1.2.5", - "neo-async": "^2.6.2", - "source-map": "^0.6.1", - "uglify-js": "^3.1.4", - "wordwrap": "^1.0.0" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "hardhat": { - "version": "2.22.17", - "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-2.22.17.tgz", - "integrity": "sha512-tDlI475ccz4d/dajnADUTRc1OJ3H8fpP9sWhXhBPpYsQOg8JHq5xrDimo53UhWPl7KJmAeDCm1bFG74xvpGRpg==", - "requires": { - "@ethersproject/abi": "^5.1.2", - "@metamask/eth-sig-util": "^4.0.0", - "@nomicfoundation/edr": "^0.6.5", - "@nomicfoundation/ethereumjs-common": "4.0.4", - "@nomicfoundation/ethereumjs-tx": "5.0.4", - "@nomicfoundation/ethereumjs-util": "9.0.4", - "@nomicfoundation/solidity-analyzer": "^0.1.0", - "@sentry/node": "^5.18.1", - "@types/bn.js": "^5.1.0", - "@types/lru-cache": "^5.1.0", - "adm-zip": "^0.4.16", - "aggregate-error": "^3.0.0", - "ansi-escapes": "^4.3.0", - "boxen": "^5.1.2", - "chokidar": "^4.0.0", - "ci-info": "^2.0.0", - "debug": "^4.1.1", - "enquirer": "^2.3.0", - "env-paths": "^2.2.0", - "ethereum-cryptography": "^1.0.3", - "ethereumjs-abi": "^0.6.8", - "find-up": "^5.0.0", - "fp-ts": "1.19.3", - "fs-extra": "^7.0.1", - "immutable": "^4.0.0-rc.12", - "io-ts": "1.10.4", - "json-stream-stringify": "^3.1.4", - "keccak": "^3.0.2", - "lodash": "^4.17.11", - "mnemonist": "^0.38.0", - "mocha": "^10.0.0", - "p-map": "^4.0.0", - "picocolors": "^1.1.0", - "raw-body": "^2.4.1", - "resolve": "1.17.0", - "semver": "^6.3.0", - "solc": "0.8.26", - "source-map-support": "^0.5.13", - "stacktrace-parser": "^0.1.10", - "tinyglobby": "^0.2.6", - "tsort": "0.0.1", - "undici": "^5.14.0", - "uuid": "^8.3.2", - "ws": "^7.4.6" - }, - "dependencies": { - "ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "requires": { - "type-fest": "^0.21.3" - } - }, - "chokidar": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.1.tgz", - "integrity": "sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA==", - "requires": { - "readdirp": "^4.0.1" - } - }, - "commander": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", - "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==" - }, - "fs-extra": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", - "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", - "requires": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "resolve": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", - "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", - "requires": { - "path-parse": "^1.0.6" - } - }, - "solc": { - "version": "0.8.26", - "resolved": "https://registry.npmjs.org/solc/-/solc-0.8.26.tgz", - "integrity": "sha512-yiPQNVf5rBFHwN6SIf3TUUvVAFKcQqmSUFeq+fb6pNRCo0ZCgpYOZDi3BVoezCPIAcKrVYd/qXlBLUP9wVrZ9g==", - "requires": { - "command-exists": "^1.2.8", - "commander": "^8.1.0", - "follow-redirects": "^1.12.1", - "js-sha3": "0.8.0", - "memorystream": "^0.3.1", - "semver": "^5.5.0", - "tmp": "0.0.33" - }, - "dependencies": { - "semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==" - } - } - }, - "type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==" - }, - "ws": { - "version": "7.5.10", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", - "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", - "requires": {} - } - } - }, - "hardhat-abi-exporter": { - "version": "2.10.1", - "resolved": "https://registry.npmjs.org/hardhat-abi-exporter/-/hardhat-abi-exporter-2.10.1.tgz", - "integrity": "sha512-X8GRxUTtebMAd2k4fcPyVnCdPa6dYK4lBsrwzKP5yiSq4i+WadWPIumaLfce53TUf/o2TnLpLOduyO1ylE2NHQ==", - "dev": true, - "requires": { - "@ethersproject/abi": "^5.5.0", - "delete-empty": "^3.0.0" - } - }, - "hardhat-contract-sizer": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/hardhat-contract-sizer/-/hardhat-contract-sizer-2.10.0.tgz", - "integrity": "sha512-QiinUgBD5MqJZJh1hl1jc9dNnpJg7eE/w4/4GEnrcmZJJTDbVFNe3+/3Ep24XqISSkYxRz36czcPHKHd/a0dwA==", - "dev": true, - "requires": { - "chalk": "^4.0.0", - "cli-table3": "^0.6.0", - "strip-ansi": "^6.0.0" - } - }, - "hardhat-deploy": { - "version": "0.12.4", - "resolved": "https://registry.npmjs.org/hardhat-deploy/-/hardhat-deploy-0.12.4.tgz", - "integrity": "sha512-bYO8DIyeGxZWlhnMoCBon9HNZb6ji0jQn7ngP1t5UmGhC8rQYhji7B73qETMOFhzt5ECZPr+U52duj3nubsqdQ==", - "requires": { - "@ethersproject/abi": "^5.7.0", - "@ethersproject/abstract-signer": "^5.7.0", - "@ethersproject/address": "^5.7.0", - "@ethersproject/bignumber": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/constants": "^5.7.0", - "@ethersproject/contracts": "^5.7.0", - "@ethersproject/providers": "^5.7.2", - "@ethersproject/solidity": "^5.7.0", - "@ethersproject/transactions": "^5.7.0", - "@ethersproject/wallet": "^5.7.0", - "@types/qs": "^6.9.7", - "axios": "^0.21.1", - "chalk": "^4.1.2", - "chokidar": "^3.5.2", - "debug": "^4.3.2", - "enquirer": "^2.3.6", - "ethers": "^5.7.0", - "form-data": "^4.0.0", - "fs-extra": "^10.0.0", - "match-all": "^1.2.6", - "murmur-128": "^0.2.1", - "qs": "^6.9.4", - "zksync-ethers": "^5.0.0" - }, - "dependencies": { - "ethers": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.7.2.tgz", - "integrity": "sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg==", - "requires": { - "@ethersproject/abi": "5.7.0", - "@ethersproject/abstract-provider": "5.7.0", - "@ethersproject/abstract-signer": "5.7.0", - "@ethersproject/address": "5.7.0", - "@ethersproject/base64": "5.7.0", - "@ethersproject/basex": "5.7.0", - "@ethersproject/bignumber": "5.7.0", - "@ethersproject/bytes": "5.7.0", - "@ethersproject/constants": "5.7.0", - "@ethersproject/contracts": "5.7.0", - "@ethersproject/hash": "5.7.0", - "@ethersproject/hdnode": "5.7.0", - "@ethersproject/json-wallets": "5.7.0", - "@ethersproject/keccak256": "5.7.0", - "@ethersproject/logger": "5.7.0", - "@ethersproject/networks": "5.7.1", - "@ethersproject/pbkdf2": "5.7.0", - "@ethersproject/properties": "5.7.0", - "@ethersproject/providers": "5.7.2", - "@ethersproject/random": "5.7.0", - "@ethersproject/rlp": "5.7.0", - "@ethersproject/sha2": "5.7.0", - "@ethersproject/signing-key": "5.7.0", - "@ethersproject/solidity": "5.7.0", - "@ethersproject/strings": "5.7.0", - "@ethersproject/transactions": "5.7.0", - "@ethersproject/units": "5.7.0", - "@ethersproject/wallet": "5.7.0", - "@ethersproject/web": "5.7.1", - "@ethersproject/wordlists": "5.7.0" - } - }, - "fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - } - }, - "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "requires": { - "graceful-fs": "^4.1.6", - "universalify": "^2.0.0" - } - }, - "universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" - } - } - }, - "hardhat-deploy-ethers": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/hardhat-deploy-ethers/-/hardhat-deploy-ethers-0.4.2.tgz", - "integrity": "sha512-AskNH/XRYYYqPT94MvO5s1yMi+/QvoNjS4oU5VcVqfDU99kgpGETl+uIYHIrSXtH5sy7J6gyVjpRMf4x0tjLSQ==", - "requires": {} - }, - "hardhat-gas-reporter": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/hardhat-gas-reporter/-/hardhat-gas-reporter-2.2.2.tgz", - "integrity": "sha512-xlg3d00wrgUvP2S5tw3Zf6nO7OyS5crK3P6/ZP69i24pz4grM+6oFHGW/eJPSGqiDWBYX+gKp9XoqP4rwRXrdQ==", - "dev": true, - "requires": { - "@ethersproject/abi": "^5.7.0", - "@ethersproject/bytes": "^5.7.0", - "@ethersproject/units": "^5.7.0", - "@solidity-parser/parser": "^0.19.0", - "axios": "^1.6.7", - "brotli-wasm": "^2.0.1", - "chalk": "4.1.2", - "cli-table3": "^0.6.3", - "ethereum-cryptography": "^2.1.3", - "glob": "^10.3.10", - "jsonschema": "^1.4.1", - "lodash": "^4.17.21", - "markdown-table": "2.0.0", - "sha1": "^1.1.1", - "viem": "2.7.14" - }, - "dependencies": { - "@noble/curves": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.4.2.tgz", - "integrity": "sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw==", - "dev": true, - "requires": { - "@noble/hashes": "1.4.0" - } - }, - "@noble/hashes": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", - "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", - "dev": true - }, - "@scure/bip32": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.4.0.tgz", - "integrity": "sha512-sVUpc0Vq3tXCkDGYVWGIZTRfnvu8LoTDaev7vbwh0omSvVORONr960MQWdKqJDCReIEmTj3PAr73O3aoxz7OPg==", - "dev": true, - "requires": { - "@noble/curves": "~1.4.0", - "@noble/hashes": "~1.4.0", - "@scure/base": "~1.1.6" - } - }, - "@scure/bip39": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.3.0.tgz", - "integrity": "sha512-disdg7gHuTDZtY+ZdkmLpPCk7fxZSu3gBiEGuoC1XYxv9cGx3Z6cpTggCgW6odSOOIXCiDjuGejW+aJKCY/pIQ==", - "dev": true, - "requires": { - "@noble/hashes": "~1.4.0", - "@scure/base": "~1.1.6" - } - }, - "@solidity-parser/parser": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.19.0.tgz", - "integrity": "sha512-RV16k/qIxW/wWc+mLzV3ARyKUaMUTBy9tOLMzFhtNSKYeTAanQ3a5MudJKf/8arIFnA2L27SNjarQKmFg0w/jA==", - "dev": true - }, - "abitype": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/abitype/-/abitype-1.0.0.tgz", - "integrity": "sha512-NMeMah//6bJ56H5XRj8QCV4AwuW6hB6zqz2LnhhLdcWVQOsXki6/Pn3APeqxCma62nXIcmZWdu1DlHWS74umVQ==", - "dev": true, - "requires": {} - }, - "axios": { - "version": "1.7.9", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.9.tgz", - "integrity": "sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==", - "dev": true, - "requires": { - "follow-redirects": "^1.15.6", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" - } - }, - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "ethereum-cryptography": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.2.1.tgz", - "integrity": "sha512-r/W8lkHSiTLxUxW8Rf3u4HGB0xQweG2RyETjywylKZSzLWoWAijRz8WCuOtJ6wah+avllXBqZuk29HCCvhEIRg==", - "dev": true, - "requires": { - "@noble/curves": "1.4.2", - "@noble/hashes": "1.4.0", - "@scure/bip32": "1.4.0", - "@scure/bip39": "1.3.0" - } - }, - "glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", - "dev": true, - "requires": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - } - }, - "minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - }, - "minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true - }, - "viem": { - "version": "2.7.14", - "resolved": "https://registry.npmjs.org/viem/-/viem-2.7.14.tgz", - "integrity": "sha512-5b1KB1gXli02GOQHZIUsRluNUwssl2t4hqdFAzyWPwJ744N83jAOBOjOkrGz7K3qMIv9b0GQt3DoZIErSQTPkQ==", - "dev": true, - "requires": { - "@adraffy/ens-normalize": "1.10.0", - "@noble/curves": "1.2.0", - "@noble/hashes": "1.3.2", - "@scure/bip32": "1.3.2", - "@scure/bip39": "1.2.1", - "abitype": "1.0.0", - "isows": "1.0.3", - "ws": "8.13.0" - }, - "dependencies": { - "@noble/curves": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz", - "integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==", - "dev": true, - "requires": { - "@noble/hashes": "1.3.2" - } - }, - "@noble/hashes": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", - "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==", - "dev": true - }, - "@scure/bip32": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.3.2.tgz", - "integrity": "sha512-N1ZhksgwD3OBlwTv3R6KFEcPojl/W4ElJOeCZdi+vuI5QmTFwLq3OFf2zd2ROpKvxFdgZ6hUpb0dx9bVNEwYCA==", - "dev": true, - "requires": { - "@noble/curves": "~1.2.0", - "@noble/hashes": "~1.3.2", - "@scure/base": "~1.1.2" - } - }, - "@scure/bip39": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.2.1.tgz", - "integrity": "sha512-Z3/Fsz1yr904dduJD0NpiyRHhRYHdcnyh73FZWiV+/qhWi83wNJ3NWolYqCEN+ZWsUz2TWwajJggcRE9r1zUYg==", - "dev": true, - "requires": { - "@noble/hashes": "~1.3.0", - "@scure/base": "~1.1.0" - } - } - } - }, - "ws": { - "version": "8.13.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.13.0.tgz", - "integrity": "sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==", - "dev": true, - "requires": {} - } - } - }, - "hardhat-tracer": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/hardhat-tracer/-/hardhat-tracer-3.1.0.tgz", - "integrity": "sha512-Ip16HQAuzbqbNJUIEVfqmbPmOY90bxZSpwu5Q73cwloy+LUYA04BATUM9Gui5H7zcgsgZ1IVy7pSYn6ZMjLmag==", - "dev": true, - "requires": { - "chalk": "^4.1.2", - "debug": "^4.3.4", - "ethers": "^5.6.1", - "semver": "^7.6.2" - }, - "dependencies": { - "ethers": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.7.2.tgz", - "integrity": "sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg==", - "dev": true, - "requires": { - "@ethersproject/abi": "5.7.0", - "@ethersproject/abstract-provider": "5.7.0", - "@ethersproject/abstract-signer": "5.7.0", - "@ethersproject/address": "5.7.0", - "@ethersproject/base64": "5.7.0", - "@ethersproject/basex": "5.7.0", - "@ethersproject/bignumber": "5.7.0", - "@ethersproject/bytes": "5.7.0", - "@ethersproject/constants": "5.7.0", - "@ethersproject/contracts": "5.7.0", - "@ethersproject/hash": "5.7.0", - "@ethersproject/hdnode": "5.7.0", - "@ethersproject/json-wallets": "5.7.0", - "@ethersproject/keccak256": "5.7.0", - "@ethersproject/logger": "5.7.0", - "@ethersproject/networks": "5.7.1", - "@ethersproject/pbkdf2": "5.7.0", - "@ethersproject/properties": "5.7.0", - "@ethersproject/providers": "5.7.2", - "@ethersproject/random": "5.7.0", - "@ethersproject/rlp": "5.7.0", - "@ethersproject/sha2": "5.7.0", - "@ethersproject/signing-key": "5.7.0", - "@ethersproject/solidity": "5.7.0", - "@ethersproject/strings": "5.7.0", - "@ethersproject/transactions": "5.7.0", - "@ethersproject/units": "5.7.0", - "@ethersproject/wallet": "5.7.0", - "@ethersproject/web": "5.7.1", - "@ethersproject/wordlists": "5.7.0" - } - }, - "semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true - } - } - }, - "has-bigints": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", - "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" - }, - "has-property-descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", - "requires": { - "es-define-property": "^1.0.0" - } - }, - "has-proto": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.1.0.tgz", - "integrity": "sha512-QLdzI9IIO1Jg7f9GT1gXpPpXArAn6cS31R1eEZqz08Gc+uQ8/XiqHWt17Fiw+2p6oTTIq5GXEpQkAlA88YRl/Q==", - "requires": { - "call-bind": "^1.0.7" - } - }, - "has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" - }, - "has-tostringtag": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", - "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", - "dev": true, - "requires": { - "has-symbols": "^1.0.3" - } - }, - "hash-base": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", - "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", - "requires": { - "inherits": "^2.0.4", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" - }, - "dependencies": { - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - } - } - }, - "hash.js": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", - "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", - "requires": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.1" - } - }, - "hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "requires": { - "function-bind": "^1.1.2" - } - }, - "he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==" - }, - "heap": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/heap/-/heap-0.2.7.tgz", - "integrity": "sha512-2bsegYkkHO+h/9MGbn6KWcE45cHZgPANo5LXF7EvWdT0yT2EguSVO1nDgU5c8+ZOPwp2vMNa7YFsJhVcDR9Sdg==", - "dev": true - }, - "hmac-drbg": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", - "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==", - "requires": { - "hash.js": "^1.0.3", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.1" - } - }, - "http-cache-semantics": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", - "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", - "dev": true - }, - "http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "requires": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "dependencies": { - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" - } - } - }, - "http2-wrapper": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-2.2.0.tgz", - "integrity": "sha512-kZB0wxMo0sh1PehyjJUWRFEd99KC5TLjZ2cULC4f9iqJBAmKQQXEICjxl5iPJRwP40dpeHFqqhm7tYCvODpqpQ==", - "dev": true, - "requires": { - "quick-lru": "^5.1.1", - "resolve-alpn": "^1.2.0" - } - }, - "https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "requires": { - "agent-base": "6", - "debug": "4" - } - }, - "human-signals": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", - "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", - "dev": true - }, - "husky": { - "version": "9.1.7", - "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz", - "integrity": "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==", - "dev": true - }, - "iconv-lite": { - "version": "0.4.24", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", - "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", - "requires": { - "safer-buffer": ">= 2.1.2 < 3" - } - }, - "ignore": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", - "dev": true - }, - "immutable": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.1.0.tgz", - "integrity": "sha512-oNkuqVTA8jqG1Q6c+UglTOD1xhC1BtjKI7XkCXRkZHrN5m18/XsnUp8Q89GkQO/z+0WjonSvl0FLhDYftp46nQ==" - }, - "import-fresh": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", - "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", - "dev": true, - "requires": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - } - }, - "imul": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/imul/-/imul-1.0.1.tgz", - "integrity": "sha512-WFAgfwPLAjU66EKt6vRdTlKj4nAgIDQzh29JonLa4Bqtl6D8JrIMvWjCnx7xEjVNmP3U0fM5o8ZObk7d0f62bA==" - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true - }, - "indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==" - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==" - }, - "ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true - }, - "internal-slot": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", - "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", - "dev": true, - "requires": { - "es-errors": "^1.3.0", - "hasown": "^2.0.0", - "side-channel": "^1.0.4" - } - }, - "interpret": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", - "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", - "dev": true - }, - "io-ts": { - "version": "1.10.4", - "resolved": "https://registry.npmjs.org/io-ts/-/io-ts-1.10.4.tgz", - "integrity": "sha512-b23PteSnYXSONJ6JQXRAlvJhuw8KOtkqa87W4wDtvMrud/DTJd5X+NpOOI+O/zZwVq6v0VLAaJ+1EDViKEuN9g==", - "requires": { - "fp-ts": "^1.0.0" - } - }, - "is-array-buffer": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", - "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.1" - } - }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true - }, - "is-async-function": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", - "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", - "dev": true, - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "is-bigint": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", - "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", - "dev": true, - "requires": { - "has-bigints": "^1.0.2" - } - }, - "is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "is-boolean-object": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.0.tgz", - "integrity": "sha512-kR5g0+dXf/+kXnqI+lu0URKYPKgICtHGGNCDSB10AaUFj3o/HkB3u7WfpRBJGFopxxY0oH3ux7ZsDjLtK7xqvw==", - "dev": true, - "requires": { - "call-bind": "^1.0.7", - "has-tostringtag": "^1.0.2" - } - }, - "is-bun-module": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/is-bun-module/-/is-bun-module-1.3.0.tgz", - "integrity": "sha512-DgXeu5UWI0IsMQundYb5UAOzm6G2eVnarJ0byP6Tm55iZNKceD59LNPA2L4VvsScTtHcw0yEkVwSf7PC+QoLSA==", - "dev": true, - "requires": { - "semver": "^7.6.3" - }, - "dependencies": { - "semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true - } - } - }, - "is-callable": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", - "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", - "dev": true - }, - "is-core-module": { - "version": "2.15.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", - "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", - "dev": true, - "requires": { - "hasown": "^2.0.2" - } - }, - "is-data-view": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", - "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", - "dev": true, - "requires": { - "is-typed-array": "^1.1.13" - } - }, - "is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", - "dev": true, - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==" - }, - "is-finalizationregistry": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.0.tgz", - "integrity": "sha512-qfMdqbAQEwBw78ZyReKnlA8ezmPdb9BemzIIip/JkjaZUhitfXDkkr+3QTboW0JrSXT1QWyYShpvnNHGZ4c4yA==", - "dev": true, - "requires": { - "call-bind": "^1.0.7" - } - }, - "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==" - }, - "is-generator-function": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", - "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", - "dev": true, - "requires": { - "has-tostringtag": "^1.0.0" - } - }, - "is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-hex-prefixed": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz", - "integrity": "sha512-WvtOiug1VFrE9v1Cydwm+FnXd3+w9GaeVUss5W4v/SLy3UW00vP+6iNF2SdnfiBoLy4bTqVdkftNGTUeOFVsbA==" - }, - "is-map": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", - "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", - "dev": true - }, - "is-negative-zero": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", - "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", - "dev": true - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" - }, - "is-number-object": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.0.tgz", - "integrity": "sha512-KVSZV0Dunv9DTPkhXwcZ3Q+tUc9TsaE1ZwX5J2WMvsSGS6Md8TFPun5uwh0yRdrNerI6vf/tbJxqSx4c1ZI1Lw==", - "dev": true, - "requires": { - "call-bind": "^1.0.7", - "has-tostringtag": "^1.0.2" - } - }, - "is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true - }, - "is-regex": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.0.tgz", - "integrity": "sha512-B6ohK4ZmoftlUe+uvenXSbPJFo6U37BH7oO1B3nQH8f/7h27N56s85MhUtbFJAziz5dcmuR3i8ovUl35zp8pFA==", - "dev": true, - "requires": { - "call-bind": "^1.0.7", - "gopd": "^1.1.0", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.2" - } - }, - "is-set": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", - "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", - "dev": true - }, - "is-shared-array-buffer": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", - "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", - "dev": true, - "requires": { - "call-bind": "^1.0.7" - } - }, - "is-stream": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", - "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", - "dev": true - }, - "is-string": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.0.tgz", - "integrity": "sha512-PlfzajuF9vSo5wErv3MJAKD/nqf9ngAs1NFQYm16nUYFO2IzxJ2hcm+IOCg+EEopdykNNUhVq5cz35cAUxU8+g==", - "dev": true, - "requires": { - "call-bind": "^1.0.7", - "has-tostringtag": "^1.0.2" - } - }, - "is-symbol": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.0.tgz", - "integrity": "sha512-qS8KkNNXUZ/I+nX6QT8ZS1/Yx0A444yhzdTKxCzKkNjQ9sHErBxJnJAgh+f5YhusYECEcjo4XcyH87hn6+ks0A==", - "dev": true, - "requires": { - "call-bind": "^1.0.7", - "has-symbols": "^1.0.3", - "safe-regex-test": "^1.0.3" - } - }, - "is-typed-array": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", - "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", - "dev": true, - "requires": { - "which-typed-array": "^1.1.14" - } - }, - "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-weakmap": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", - "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", - "dev": true - }, - "is-weakref": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", - "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", - "dev": true, - "requires": { - "call-bind": "^1.0.2" - } - }, - "is-weakset": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.3.tgz", - "integrity": "sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==", - "dev": true, - "requires": { - "call-bind": "^1.0.7", - "get-intrinsic": "^1.2.4" - } - }, - "isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true - }, - "isows": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/isows/-/isows-1.0.3.tgz", - "integrity": "sha512-2cKei4vlmg2cxEjm3wVSqn8pcoRF/LX/wpifuuNquFO4SQmPwarClT+SUCA2lt+l581tTeZIPIZuIDo2jWN1fg==", - "dev": true, - "requires": {} - }, - "jackspeak": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", - "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", - "dev": true, - "requires": { - "@isaacs/cliui": "^8.0.2", - "@pkgjs/parseargs": "^0.11.0" - } - }, - "js-sha3": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", - "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==" - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "requires": { - "argparse": "^2.0.1" - } - }, - "json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true - }, - "json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true - }, - "json-stream-stringify": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/json-stream-stringify/-/json-stream-stringify-3.1.6.tgz", - "integrity": "sha512-x7fpwxOkbhFCaJDJ8vb1fBY3DdSa4AlITaz+HHILQJzdPMnHEFjxPwVUi1ALIbcIxDE0PNe/0i7frnY8QnBQog==" - }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==" - }, - "json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", - "dev": true, - "requires": { - "minimist": "^1.2.0" - } - }, - "jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", - "requires": { - "graceful-fs": "^4.1.6" - } - }, - "jsonld": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/jsonld/-/jsonld-8.1.0.tgz", - "integrity": "sha512-6tYhiEVYO3rTcoYCGCArw8SqawuW0hf/cqmaE5WbX44CGb7d8N2UFvmUj9OYkJhChD98bfdPljUj7S39MrzsHg==", - "dev": true, - "requires": { - "@digitalbazaar/http-client": "^3.2.0", - "canonicalize": "^1.0.1", - "lru-cache": "^6.0.0", - "rdf-canonize": "^3.0.0" - } - }, - "jsonschema": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.4.1.tgz", - "integrity": "sha512-S6cATIPVv1z0IlxdN+zUk5EPjkGCdnhN4wVSBlvoUO1tOLJootbo9CquNJmbIh4yikWHiUedhRYrNPn1arpEmQ==", - "dev": true - }, - "keccak": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.2.tgz", - "integrity": "sha512-PyKKjkH53wDMLGrvmRGSNWgmSxZOUqbnXwKL9tmgbFYA1iAYqW21kfR7mZXV0MlESiefxQQE9X9fTa3X+2MPDQ==", - "requires": { - "node-addon-api": "^2.0.0", - "node-gyp-build": "^4.2.0", - "readable-stream": "^3.6.0" - } - }, - "keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", - "dev": true, - "requires": { - "json-buffer": "3.0.1" - } - }, - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true - }, - "ky": { - "version": "0.30.0", - "resolved": "https://registry.npmjs.org/ky/-/ky-0.30.0.tgz", - "integrity": "sha512-X/u76z4JtDVq10u1JA5UQfatPxgPaVDMYTrgHyiTpGN2z4TMEJkIHsoSBBSg9SWZEIXTKsi9kHgiQ9o3Y/4yog==", - "dev": true - }, - "ky-universal": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/ky-universal/-/ky-universal-0.10.1.tgz", - "integrity": "sha512-r8909k+ELKZAxhVA5c440x22hqw5XcMRwLRbgpPQk4JHy3/ddJnvzcnSo5Ww3HdKdNeS3Y8dBgcIYyVahMa46g==", - "dev": true, - "requires": { - "abort-controller": "^3.0.0", - "node-fetch": "^3.2.2" - } - }, - "latest-version": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-7.0.0.tgz", - "integrity": "sha512-KvNT4XqAMzdcL6ka6Tl3i2lYeFDgXNCuIX+xNx6ZMVR1dFq+idXd9FLKNMOIx0t9mJ9/HudyX4oZWXZQ0UJHeg==", - "dev": true, - "requires": { - "package-json": "^8.1.0" - } - }, - "levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - } - }, - "lilconfig": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", - "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", - "dev": true - }, - "lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true - }, - "lint-staged": { - "version": "15.2.11", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.11.tgz", - "integrity": "sha512-Ev6ivCTYRTGs9ychvpVw35m/bcNDuBN+mnTeObCL5h+boS5WzBEC6LHI4I9F/++sZm1m+J2LEiy0gxL/R9TBqQ==", - "dev": true, - "requires": { - "chalk": "~5.3.0", - "commander": "~12.1.0", - "debug": "~4.4.0", - "execa": "~8.0.1", - "lilconfig": "~3.1.3", - "listr2": "~8.2.5", - "micromatch": "~4.0.8", - "pidtree": "~0.6.0", - "string-argv": "~0.3.2", - "yaml": "~2.6.1" - }, - "dependencies": { - "chalk": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", - "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", - "dev": true - }, - "commander": { - "version": "12.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", - "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", - "dev": true - } - } - }, - "listr2": { - "version": "8.2.5", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.2.5.tgz", - "integrity": "sha512-iyAZCeyD+c1gPyE9qpFu8af0Y+MRtmKOncdGoA2S5EY8iFq99dmmvkNnHiWo+pj0s7yH7l3KPIgee77tKpXPWQ==", - "dev": true, - "requires": { - "cli-truncate": "^4.0.0", - "colorette": "^2.0.20", - "eventemitter3": "^5.0.1", - "log-update": "^6.1.0", - "rfdc": "^1.4.1", - "wrap-ansi": "^9.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", - "dev": true - }, - "ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true - }, - "emoji-regex": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", - "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", - "dev": true - }, - "string-width": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", - "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", - "dev": true, - "requires": { - "emoji-regex": "^10.3.0", - "get-east-asian-width": "^1.0.0", - "strip-ansi": "^7.1.0" - } - }, - "strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "requires": { - "ansi-regex": "^6.0.1" - } - }, - "wrap-ansi": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", - "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", - "dev": true, - "requires": { - "ansi-styles": "^6.2.1", - "string-width": "^7.0.0", - "strip-ansi": "^7.1.0" - } - } - } - }, - "locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "requires": { - "p-locate": "^5.0.0" - } - }, - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" - }, - "lodash.camelcase": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", - "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", - "dev": true - }, - "lodash.isequal": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", - "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==", - "peer": true - }, - "lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true - }, - "lodash.truncate": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", - "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==", - "dev": true - }, - "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" - } - }, - "log-update": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz", - "integrity": "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==", - "dev": true, - "requires": { - "ansi-escapes": "^7.0.0", - "cli-cursor": "^5.0.0", - "slice-ansi": "^7.1.0", - "strip-ansi": "^7.1.0", - "wrap-ansi": "^9.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", - "dev": true - }, - "ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true - }, - "emoji-regex": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", - "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.0.0.tgz", - "integrity": "sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==", - "dev": true, - "requires": { - "get-east-asian-width": "^1.0.0" - } - }, - "slice-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.0.tgz", - "integrity": "sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==", - "dev": true, - "requires": { - "ansi-styles": "^6.2.1", - "is-fullwidth-code-point": "^5.0.0" - } - }, - "string-width": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", - "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", - "dev": true, - "requires": { - "emoji-regex": "^10.3.0", - "get-east-asian-width": "^1.0.0", - "strip-ansi": "^7.1.0" - } - }, - "strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "requires": { - "ansi-regex": "^6.0.1" - } - }, - "wrap-ansi": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", - "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", - "dev": true, - "requires": { - "ansi-styles": "^6.2.1", - "string-width": "^7.0.0", - "strip-ansi": "^7.1.0" - } - } - } - }, - "loupe": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", - "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", - "dev": true, - "requires": { - "get-func-name": "^2.0.1" - } - }, - "lowercase-keys": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-3.0.0.tgz", - "integrity": "sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==", - "dev": true - }, - "lru_map": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/lru_map/-/lru_map-0.3.3.tgz", - "integrity": "sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ==" - }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, - "make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==" - }, - "markdown-table": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-2.0.0.tgz", - "integrity": "sha512-Ezda85ToJUBhM6WGaG6veasyym+Tbs3cMAw/ZhOPqXiYsr0jgocBV3j3nx+4lk47plLlIqjwuTm/ywVI+zjJ/A==", - "dev": true, - "requires": { - "repeat-string": "^1.0.0" - } - }, - "match-all": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/match-all/-/match-all-1.2.6.tgz", - "integrity": "sha512-0EESkXiTkWzrQQntBu2uzKvLu6vVkUGz40nGPbSZuegcfE5UuSzNjLaIu76zJWuaT/2I3Z/8M06OlUOZLGwLlQ==" - }, - "md5.js": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", - "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", - "requires": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1", - "safe-buffer": "^5.1.2" - } - }, - "memorystream": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", - "integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==" - }, - "merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true - }, - "merkletreejs": { - "version": "0.3.11", - "resolved": "https://registry.npmjs.org/merkletreejs/-/merkletreejs-0.3.11.tgz", - "integrity": "sha512-LJKTl4iVNTndhL+3Uz/tfkjD0klIWsHlUzgtuNnNrsf7bAlXR30m+xYB7lHr5Z/l6e/yAIsr26Dabx6Buo4VGQ==", - "dev": true, - "requires": { - "bignumber.js": "^9.0.1", - "buffer-reverse": "^1.0.1", - "crypto-js": "^4.2.0", - "treeify": "^1.1.0", - "web3-utils": "^1.3.4" - } - }, - "micromatch": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "dev": true, - "requires": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - } - }, - "mime-db": { - "version": "1.51.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", - "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==" - }, - "mime-types": { - "version": "2.1.34", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz", - "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==", - "requires": { - "mime-db": "1.51.0" - } - }, - "mimic-fn": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", - "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", - "dev": true - }, - "mimic-function": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", - "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", - "dev": true - }, - "mimic-response": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", - "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", - "dev": true - }, - "minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" - }, - "minimalistic-crypto-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==" - }, - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", - "dev": true - }, - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true - }, - "mnemonist": { - "version": "0.38.5", - "resolved": "https://registry.npmjs.org/mnemonist/-/mnemonist-0.38.5.tgz", - "integrity": "sha512-bZTFT5rrPKtPJxj8KSV0WkPyNxl72vQepqqVUAW2ARUpUSF2qXMB6jZj7hW5/k7C1rtpzqbD/IIbJwLXUjCHeg==", - "requires": { - "obliterator": "^2.0.0" - } - }, - "mocha": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.2.0.tgz", - "integrity": "sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==", - "requires": { - "ansi-colors": "4.1.1", - "browser-stdout": "1.3.1", - "chokidar": "3.5.3", - "debug": "4.3.4", - "diff": "5.0.0", - "escape-string-regexp": "4.0.0", - "find-up": "5.0.0", - "glob": "7.2.0", - "he": "1.2.0", - "js-yaml": "4.1.0", - "log-symbols": "4.1.0", - "minimatch": "5.0.1", - "ms": "2.1.3", - "nanoid": "3.3.3", - "serialize-javascript": "6.0.0", - "strip-json-comments": "3.1.1", - "supports-color": "8.1.1", - "workerpool": "6.2.1", - "yargs": "16.2.0", - "yargs-parser": "20.2.4", - "yargs-unparser": "2.0.0" - }, - "dependencies": { - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "requires": { - "ms": "2.1.2" - }, - "dependencies": { - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - } - } - }, - "diff": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", - "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==" - }, - "glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "dependencies": { - "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "requires": { - "brace-expansion": "^1.1.7" - } - } - } - }, - "minimatch": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", - "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", - "requires": { - "brace-expansion": "^2.0.1" - }, - "dependencies": { - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "requires": { - "balanced-match": "^1.0.0" - } - } - } - }, - "strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==" - }, - "supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "mock-socket": { - "version": "9.3.1", - "resolved": "https://registry.npmjs.org/mock-socket/-/mock-socket-9.3.1.tgz", - "integrity": "sha512-qxBgB7Qa2sEQgHFjj0dSigq7fX4k6Saisd5Nelwp2q8mlbAFh5dHV9JTTlF8viYJLSSWgMCZFUom8PJcMNBoJw==" - }, - "ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" - }, - "murmur-128": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/murmur-128/-/murmur-128-0.2.1.tgz", - "integrity": "sha512-WseEgiRkI6aMFBbj8Cg9yBj/y+OdipwVC7zUo3W2W1JAJITwouUOtpqsmGSg67EQmwwSyod7hsVsWY5LsrfQVg==", - "requires": { - "encode-utf8": "^1.0.2", - "fmix": "^0.1.0", - "imul": "^1.0.0" - } - }, - "nanoid": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz", - "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==" - }, - "natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true - }, - "neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true - }, - "nock": { - "version": "13.5.6", - "resolved": "https://registry.npmjs.org/nock/-/nock-13.5.6.tgz", - "integrity": "sha512-o2zOYiCpzRqSzPj0Zt/dQ/DqZeYoaQ7TUonc/xUPjCGl9WeHpNbxgVvOquXYAaJzI0M9BXV3HTzG0p8IUAbBTQ==", - "requires": { - "debug": "^4.1.0", - "json-stringify-safe": "^5.0.1", - "propagate": "^2.0.0" - } - }, - "node-addon-api": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz", - "integrity": "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==" - }, - "node-domexception": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", - "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==" - }, - "node-emoji": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz", - "integrity": "sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==", - "dev": true, - "requires": { - "lodash": "^4.17.21" - } - }, - "node-fetch": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", - "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", - "requires": { - "data-uri-to-buffer": "^4.0.0", - "fetch-blob": "^3.1.4", - "formdata-polyfill": "^4.0.10" - } - }, - "node-gyp-build": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.5.0.tgz", - "integrity": "sha512-2iGbaQBV+ITgCz76ZEjmhUKAKVf7xfY1sRl4UiKQspfZMH2h06SyhNsnSVy50cwkFQDGLyif6m/6uFXHkOZ6rg==" - }, - "nopt": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", - "integrity": "sha512-4GUt3kSEYmk4ITxzB/b9vaIDfUVWN/Ml1Fwl11IlnIG2iaJ9O6WXZ9SrYM9NLI8OCBieN2Y8SWC2oJV0RQ7qYg==", - "dev": true, - "requires": { - "abbrev": "1" - } - }, - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" - }, - "normalize-url": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", - "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", - "dev": true - }, - "npm-run-path": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", - "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", - "dev": true, - "requires": { - "path-key": "^4.0.0" - }, - "dependencies": { - "path-key": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", - "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", - "dev": true - } - } - }, - "number-to-bn": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/number-to-bn/-/number-to-bn-1.7.0.tgz", - "integrity": "sha512-wsJ9gfSz1/s4ZsJN01lyonwuxA1tml6X1yBDnfpMglypcBRFZZkus26EdPSlqS5GJfYddVZa22p3VNb3z5m5Ig==", - "dev": true, - "requires": { - "bn.js": "4.11.6", - "strip-hex-prefix": "1.0.0" - }, - "dependencies": { - "bn.js": { - "version": "4.11.6", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", - "integrity": "sha512-XWwnNNFCuuSQ0m3r3C4LE3EiORltHd9M05pq6FOlVeiophzRbMo50Sbz1ehl8K3Z+jw9+vmgnXefY1hz8X+2wA==", - "dev": true - } - } - }, - "object-inspect": { - "version": "1.13.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.3.tgz", - "integrity": "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==" - }, - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true - }, - "object.assign": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", - "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", - "dev": true, - "requires": { - "call-bind": "^1.0.5", - "define-properties": "^1.2.1", - "has-symbols": "^1.0.3", - "object-keys": "^1.1.1" - } - }, - "object.fromentries": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", - "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", - "dev": true, - "requires": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-object-atoms": "^1.0.0" - } - }, - "object.groupby": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", - "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", - "dev": true, - "requires": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2" - } - }, - "object.values": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", - "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", - "dev": true, - "requires": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - } - }, - "obliterator": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/obliterator/-/obliterator-2.0.4.tgz", - "integrity": "sha512-lgHwxlxV1qIg1Eap7LgIeoBWIMFibOjbrYPIPJZcI1mmGAI2m3lNYpK12Y+GBdPQ0U1hRwSord7GIaawz962qQ==" - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "requires": { - "wrappy": "1" - } - }, - "onetime": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", - "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", - "dev": true, - "requires": { - "mimic-fn": "^4.0.0" - } - }, - "optionator": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", - "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", - "dev": true, - "requires": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.5" - } - }, - "ordinal": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/ordinal/-/ordinal-1.0.3.tgz", - "integrity": "sha512-cMddMgb2QElm8G7vdaa02jhUNbTSrhsgAGUz1OokD83uJTwSUn+nKoNoKVVaRa08yF6sgfO7Maou1+bgLd9rdQ==", - "dev": true - }, - "os-tmpdir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==" - }, - "p-cancelable": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-3.0.0.tgz", - "integrity": "sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==", - "dev": true - }, - "p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "requires": { - "yocto-queue": "^0.1.0" - } - }, - "p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "requires": { - "p-limit": "^3.0.2" - } - }, - "p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "requires": { - "aggregate-error": "^3.0.0" - } - }, - "package-json": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/package-json/-/package-json-8.1.1.tgz", - "integrity": "sha512-cbH9IAIJHNj9uXi196JVsRlt7cHKak6u/e6AkL/bkRelZ7rlL3X1YKxsZwa36xipOEKAsdtmaG6aAJoM1fx2zA==", - "dev": true, - "requires": { - "got": "^12.1.0", - "registry-auth-token": "^5.0.1", - "registry-url": "^6.0.0", - "semver": "^7.3.7" - }, - "dependencies": { - "semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true - } - } - }, - "package-json-from-dist": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", - "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", - "dev": true - }, - "parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "requires": { - "callsites": "^3.0.0" - } - }, - "parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - } - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==" - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" - }, - "path-scurry": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", - "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", - "dev": true, - "requires": { - "lru-cache": "^10.2.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" - }, - "dependencies": { - "lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "dev": true - }, - "minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true - } - } - }, - "path-starts-with": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/path-starts-with/-/path-starts-with-2.0.1.tgz", - "integrity": "sha512-wZ3AeiRBRlNwkdUxvBANh0+esnt38DLffHDujZyRHkqkaKHTglnY2EP5UX3b8rdeiSutgO4y9NEJwXezNP5vHg==", - "dev": true - }, - "path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true - }, - "pathval": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", - "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", - "dev": true - }, - "pbkdf2": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", - "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", - "requires": { - "create-hash": "^1.1.2", - "create-hmac": "^1.1.4", - "ripemd160": "^2.0.1", - "safe-buffer": "^5.0.1", - "sha.js": "^2.4.8" - } - }, - "picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" - }, - "picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" - }, - "pidtree": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz", - "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", - "dev": true - }, - "pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true - }, - "pluralize": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", - "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", - "dev": true - }, - "possible-typed-array-names": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", - "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", - "dev": true - }, - "prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true - }, - "prettier": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.4.2.tgz", - "integrity": "sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==", - "dev": true - }, - "prettier-linter-helpers": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", - "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", - "dev": true, - "requires": { - "fast-diff": "^1.1.2" - } - }, - "prettier-plugin-solidity": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/prettier-plugin-solidity/-/prettier-plugin-solidity-1.4.1.tgz", - "integrity": "sha512-Mq8EtfacVZ/0+uDKTtHZGW3Aa7vEbX/BNx63hmVg6YTiTXSiuKP0amj0G6pGwjmLaOfymWh3QgXEZkjQbU8QRg==", - "dev": true, - "requires": { - "@solidity-parser/parser": "^0.18.0", - "semver": "^7.5.4" - }, - "dependencies": { - "semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - } - } - }, - "propagate": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/propagate/-/propagate-2.0.1.tgz", - "integrity": "sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag==" - }, - "proto-list": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", - "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==", - "dev": true - }, - "proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", - "dev": true - }, - "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "punycode": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.0.tgz", - "integrity": "sha512-Yxz2kRwT90aPiWEMHVYnEf4+rhwF1tBmmZ4KepCP+Wkium9JxtWnUm1nqGwpiAHr/tnTSeHqr3wb++jgSkXjhA==", - "dev": true - }, - "qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", - "requires": { - "side-channel": "^1.0.4" - } - }, - "queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true - }, - "quick-lru": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", - "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", - "dev": true - }, - "rambda": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/rambda/-/rambda-7.4.0.tgz", - "integrity": "sha512-A9hihu7dUTLOUCM+I8E61V4kRXnN4DwYeK0DwCBydC1MqNI1PidyAtbtpsJlBBzK4icSctEcCQ1bGcLpBuETUQ==", - "dev": true - }, - "randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "requires": { - "safe-buffer": "^5.1.0" - } - }, - "raw-body": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", - "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", - "requires": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - } - }, - "rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "dev": true, - "requires": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - } - }, - "rdf-canonize": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/rdf-canonize/-/rdf-canonize-3.3.0.tgz", - "integrity": "sha512-gfSNkMua/VWC1eYbSkVaL/9LQhFeOh0QULwv7Or0f+po8pMgQ1blYQFe1r9Mv2GJZXw88Cz/drnAnB9UlNnHfQ==", - "dev": true, - "requires": { - "setimmediate": "^1.0.5" - } - }, - "readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "readdirp": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.2.tgz", - "integrity": "sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==" - }, - "rechoir": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "integrity": "sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==", - "dev": true, - "requires": { - "resolve": "^1.1.6" - } - }, - "recursive-readdir": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.3.tgz", - "integrity": "sha512-8HrF5ZsXk5FAH9dgsx3BlUer73nIhuj+9OrQwEbLTPOBzGkL1lsFCR01am+v+0m2Cmbs1nP12hLDl5FA7EszKA==", - "dev": true, - "requires": { - "minimatch": "^3.0.5" - } - }, - "reduce-flatten": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-2.0.0.tgz", - "integrity": "sha512-EJ4UNY/U1t2P/2k6oqotuX2Cc3T6nxJwsM0N0asT7dhrtH1ltUxDn4NalSYmPE2rCkVpcf/X6R0wDwcFpzhd4w==", - "dev": true - }, - "reflect.getprototypeof": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.7.tgz", - "integrity": "sha512-bMvFGIUKlc/eSfXNX+aZ+EL95/EgZzuwA0OBPTbZZDEJw/0AkentjMuM1oiRfwHrshqk4RzdgiTg5CcDalXN5g==", - "dev": true, - "requires": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.5", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "which-builtin-type": "^1.1.4" - } - }, - "regexp.prototype.flags": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.3.tgz", - "integrity": "sha512-vqlC04+RQoFalODCbCumG2xIOvapzVMHwsyIGM/SIE8fRhFFsXeH8/QQ+s0T0kDAhKc4k30s73/0ydkHQz6HlQ==", - "dev": true, - "requires": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-errors": "^1.3.0", - "set-function-name": "^2.0.2" - } - }, - "registry-auth-token": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-5.0.3.tgz", - "integrity": "sha512-1bpc9IyC+e+CNFRaWyn77tk4xGG4PPUyfakSmA6F6cvUDjrm58dfyJ3II+9yb10EDkHoy1LaPSmHaWLOH3m6HA==", - "dev": true, - "requires": { - "@pnpm/npm-conf": "^2.1.0" - } - }, - "registry-url": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-6.0.1.tgz", - "integrity": "sha512-+crtS5QjFRqFCoQmvGduwYWEBng99ZvmFvF+cUJkGYF1L1BfU8C6Zp9T7f5vPAwyLkUExpvK+ANVZmGU49qi4Q==", - "dev": true, - "requires": { - "rc": "1.2.8" - } - }, - "repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==", - "dev": true - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==" - }, - "require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true - }, - "resolve": { - "version": "1.22.8", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", - "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", - "dev": true, - "requires": { - "is-core-module": "^2.13.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - } - }, - "resolve-alpn": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", - "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", - "dev": true - }, - "resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true - }, - "resolve-pkg-maps": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", - "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", - "dev": true - }, - "responselike": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", - "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", - "dev": true, - "requires": { - "lowercase-keys": "^2.0.0" - }, - "dependencies": { - "lowercase-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", - "dev": true - } - } - }, - "restore-cursor": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", - "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", - "dev": true, - "requires": { - "onetime": "^7.0.0", - "signal-exit": "^4.1.0" - }, - "dependencies": { - "onetime": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", - "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", - "dev": true, - "requires": { - "mimic-function": "^5.0.0" - } - } - } - }, - "reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true - }, - "rfdc": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", - "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", - "dev": true - }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "ripemd160": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", - "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", - "requires": { - "hash-base": "^3.0.0", - "inherits": "^2.0.1" - } - }, - "rlp": { - "version": "2.2.7", - "resolved": "https://registry.npmjs.org/rlp/-/rlp-2.2.7.tgz", - "integrity": "sha512-d5gdPmgQ0Z+AklL2NVXr/IoSjNZFfTVvQWzL/AM2AOcSzYP2xjlb0AC8YyCLc41MSNf6P6QVtjgPdmVtzb+4lQ==", - "requires": { - "bn.js": "^5.2.0" - } - }, - "run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "requires": { - "queue-microtask": "^1.2.2" - } - }, - "rxjs": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", - "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", - "requires": { - "tslib": "^2.1.0" - } - }, - "safe-array-concat": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", - "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", - "dev": true, - "requires": { - "call-bind": "^1.0.7", - "get-intrinsic": "^1.2.4", - "has-symbols": "^1.0.3", - "isarray": "^2.0.5" - } - }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" - }, - "safe-regex-test": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", - "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", - "dev": true, - "requires": { - "call-bind": "^1.0.6", - "es-errors": "^1.3.0", - "is-regex": "^1.1.4" - } - }, - "safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" - }, - "sc-istanbul": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/sc-istanbul/-/sc-istanbul-0.4.6.tgz", - "integrity": "sha512-qJFF/8tW/zJsbyfh/iT/ZM5QNHE3CXxtLJbZsL+CzdJLBsPD7SedJZoUA4d8iAcN2IoMp/Dx80shOOd2x96X/g==", - "dev": true, - "requires": { - "abbrev": "1.0.x", - "async": "1.x", - "escodegen": "1.8.x", - "esprima": "2.7.x", - "glob": "^5.0.15", - "handlebars": "^4.0.1", - "js-yaml": "3.x", - "mkdirp": "0.5.x", - "nopt": "3.x", - "once": "1.x", - "resolve": "1.1.x", - "supports-color": "^3.1.0", - "which": "^1.1.1", - "wordwrap": "^1.0.0" - }, - "dependencies": { - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } - }, - "esprima": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", - "integrity": "sha512-OarPfz0lFCiW4/AV2Oy1Rp9qu0iusTKqykwTspGCZtPxmF81JR4MmIebvF1F9+UOKth2ZubLQ4XGGaU+hSn99A==", - "dev": true - }, - "glob": { - "version": "5.0.15", - "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", - "integrity": "sha512-c9IPMazfRITpmAAKi22dK1VKxGDX9ehhqfABDriL/lzO92xcUKEJPQHrVA/2YHSNFB4iFlykVmWvwo48nr3OxA==", - "dev": true, - "requires": { - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "2 || 3", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha512-DyYHfIYwAJmjAjSSPKANxI8bFY9YtFrgkAfinBojQ8YJTOuOuav64tMUJv584SES4xl74PmuaevIyaLESHdTAA==", - "dev": true - }, - "js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "dependencies": { - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true - } - } - }, - "mkdirp": { - "version": "0.5.6", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", - "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", - "dev": true, - "requires": { - "minimist": "^1.2.6" - } - }, - "resolve": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", - "integrity": "sha512-9znBF0vBcaSN3W2j7wKvdERPwqTxSpCq+if5C0WoTCyV9n24rua28jeuQ2pL/HOf+yUe/Mef+H/5p60K0Id3bg==", - "dev": true - }, - "supports-color": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", - "integrity": "sha512-Jds2VIYDrlp5ui7t8abHN2bjAu4LV/q4N2KivFPpGH0lrka0BMq/33AmECUXlKPcHigkNaqfXRENFju+rlcy+A==", - "dev": true, - "requires": { - "has-flag": "^1.0.0" - } - }, - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } - } - }, - "scale-ts": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/scale-ts/-/scale-ts-1.6.1.tgz", - "integrity": "sha512-PBMc2AWc6wSEqJYBDPcyCLUj9/tMKnLX70jLOSndMtcUoLQucP/DM0vnQo1wJAYjTrQiq8iG9rD0q6wFzgjH7g==", - "optional": true - }, - "scrypt-js": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-3.0.1.tgz", - "integrity": "sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==" - }, - "secp256k1": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.3.tgz", - "integrity": "sha512-NLZVf+ROMxwtEj3Xa562qgv2BK5e2WNmXPiOdVIPLgs6lyTzMvBq0aWTYMI5XCP9jZMVKOcqZLw/Wc4vDkuxhA==", - "requires": { - "elliptic": "^6.5.4", - "node-addon-api": "^2.0.0", - "node-gyp-build": "^4.2.0" - } - }, - "semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" - }, - "serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", - "requires": { - "randombytes": "^2.1.0" - } - }, - "set-function-length": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", - "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", - "requires": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2" - } - }, - "set-function-name": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", - "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", - "dev": true, - "requires": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "functions-have-names": "^1.2.3", - "has-property-descriptors": "^1.0.2" - } - }, - "setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==" - }, - "setprototypeof": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" - }, - "sha.js": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", - "requires": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" - } - }, - "sha1": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/sha1/-/sha1-1.1.1.tgz", - "integrity": "sha512-dZBS6OrMjtgVkopB1Gmo4RQCDKiZsqcpAQpkV/aaj+FCrCg8r4I4qMkDPQjBgLIxlmu9k4nUbWq6ohXahOneYA==", - "dev": true, - "requires": { - "charenc": ">= 0.0.1", - "crypt": ">= 0.0.1" - } - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, - "shelljs": { - "version": "0.8.5", - "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz", - "integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==", - "dev": true, - "requires": { - "glob": "^7.0.0", - "interpret": "^1.0.0", - "rechoir": "^0.6.2" - } - }, - "side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", - "requires": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" - } - }, - "signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true - }, - "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true - }, - "slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - } - }, - "smoldot": { - "version": "2.0.26", - "resolved": "https://registry.npmjs.org/smoldot/-/smoldot-2.0.26.tgz", - "integrity": "sha512-F+qYmH4z2s2FK+CxGj8moYcd1ekSIKH8ywkdqlOz88Dat35iB1DIYL11aILN46YSGMzQW/lbJNS307zBSDN5Ig==", - "optional": true, - "requires": { - "ws": "^8.8.1" - } - }, - "solady": { - "version": "0.0.285", - "resolved": "https://registry.npmjs.org/solady/-/solady-0.0.285.tgz", - "integrity": "sha512-MkY9KFFuhMeTkWU+4wIzBoEkGr1DXdMR98/zGB8S7efg9Wph9Z4d98RRu7c8pRpmRfrSPAYuMKkvauMCpWXStg==" - }, - "solhint": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/solhint/-/solhint-5.0.3.tgz", - "integrity": "sha512-OLCH6qm/mZTCpplTXzXTJGId1zrtNuDYP5c2e6snIv/hdRVxPfBBz/bAlL91bY/Accavkayp2Zp2BaDSrLVXTQ==", - "dev": true, - "requires": { - "@solidity-parser/parser": "^0.18.0", - "ajv": "^6.12.6", - "antlr4": "^4.13.1-patch-1", - "ast-parents": "^0.0.1", - "chalk": "^4.1.2", - "commander": "^10.0.0", - "cosmiconfig": "^8.0.0", - "fast-diff": "^1.2.0", - "glob": "^8.0.3", - "ignore": "^5.2.4", - "js-yaml": "^4.1.0", - "latest-version": "^7.0.0", - "lodash": "^4.17.21", - "pluralize": "^8.0.0", - "prettier": "^2.8.3", - "semver": "^7.5.2", - "strip-ansi": "^6.0.1", - "table": "^6.8.1", - "text-table": "^0.2.0" - }, - "dependencies": { - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - } - }, - "minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - }, - "prettier": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", - "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", - "dev": true, - "optional": true - }, - "semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true - } - } - }, - "solhint-plugin-prettier": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/solhint-plugin-prettier/-/solhint-plugin-prettier-0.1.0.tgz", - "integrity": "sha512-SDOTSM6tZxZ6hamrzl3GUgzF77FM6jZplgL2plFBclj/OjKP8Z3eIPojKU73gRr0MvOS8ACZILn8a5g0VTz/Gw==", - "dev": true, - "requires": { - "@prettier/sync": "^0.3.0", - "prettier-linter-helpers": "^1.0.0" - } - }, - "solidity-coverage": { - "version": "0.8.14", - "resolved": "https://registry.npmjs.org/solidity-coverage/-/solidity-coverage-0.8.14.tgz", - "integrity": "sha512-ItAAObe5GaEOp20kXC2BZRnph+9P7Rtoqg2mQc2SXGEHgSDF2wWd1Wxz3ntzQWXkbCtIIGdJT918HG00cObwbA==", - "dev": true, - "requires": { - "@ethersproject/abi": "^5.0.9", - "@solidity-parser/parser": "^0.19.0", - "chalk": "^2.4.2", - "death": "^1.1.0", - "difflib": "^0.2.4", - "fs-extra": "^8.1.0", - "ghost-testrpc": "^0.0.2", - "global-modules": "^2.0.0", - "globby": "^10.0.1", - "jsonschema": "^1.2.4", - "lodash": "^4.17.21", - "mocha": "^10.2.0", - "node-emoji": "^1.10.0", - "pify": "^4.0.1", - "recursive-readdir": "^2.2.2", - "sc-istanbul": "^0.4.5", - "semver": "^7.3.4", - "shelljs": "^0.8.3", - "web3-utils": "^1.3.6" - }, - "dependencies": { - "@solidity-parser/parser": { - "version": "0.19.0", - "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.19.0.tgz", - "integrity": "sha512-RV16k/qIxW/wWc+mLzV3ARyKUaMUTBy9tOLMzFhtNSKYeTAanQ3a5MudJKf/8arIFnA2L27SNjarQKmFg0w/jA==", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true - }, - "fs-extra": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", - "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", - "dev": true, - "requires": { - "graceful-fs": "^4.2.0", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "globby": { - "version": "10.0.2", - "resolved": "https://registry.npmjs.org/globby/-/globby-10.0.2.tgz", - "integrity": "sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg==", - "dev": true, - "requires": { - "@types/glob": "^7.1.1", - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.0.3", - "glob": "^7.1.3", - "ignore": "^5.1.1", - "merge2": "^1.2.3", - "slash": "^3.0.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true - }, - "semver": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", - "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "source-map": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", - "integrity": "sha512-CBdZ2oa/BHhS4xj5DlhjWNHcan57/5YuvfdLf17iVmIpd9KRm+DFLmC6nBNj+6Ua7Kt3TmOjDpQT1aTYOQtoUA==", - "dev": true, - "optional": true, - "requires": { - "amdefine": ">=0.0.4" - } - }, - "source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - } - } - }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true - }, - "stable-hash": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/stable-hash/-/stable-hash-0.0.4.tgz", - "integrity": "sha512-LjdcbuBeLcdETCrPn9i8AYAZ1eCtu4ECAWtP7UleOiZ9LzVxRzzUZEoZ8zB24nhkQnDWyET0I+3sWokSDS3E7g==", - "dev": true - }, - "stacktrace-parser": { - "version": "0.1.10", - "resolved": "https://registry.npmjs.org/stacktrace-parser/-/stacktrace-parser-0.1.10.tgz", - "integrity": "sha512-KJP1OCML99+8fhOHxwwzyWrlUuVX5GQ0ZpJTd1DFXhdkrvg1szxfHhawXUZ3g9TkXORQd4/WG68jMlQZ2p8wlg==", - "requires": { - "type-fest": "^0.7.1" - }, - "dependencies": { - "type-fest": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.7.1.tgz", - "integrity": "sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==" - } - } - }, - "statuses": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", - "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==" - }, - "string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "requires": { - "safe-buffer": "~5.2.0" - } - }, - "string-argv": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", - "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==", - "dev": true - }, - "string-format": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/string-format/-/string-format-2.0.0.tgz", - "integrity": "sha512-bbEs3scLeYNXLecRRuk6uJxdXUSj6le/8rNPHChIJTn2V79aXVTR1EH2OH5zLKKoz0V02fOUKZZcw01pLUShZA==", - "dev": true - }, - "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" - } - }, - "string-width-cjs": { - "version": "npm:string-width@4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "string.prototype.trim": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", - "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", - "dev": true, - "requires": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.0", - "es-object-atoms": "^1.0.0" - } - }, - "string.prototype.trimend": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", - "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", - "dev": true, - "requires": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0" - } - }, - "string.prototype.trimstart": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", - "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", - "dev": true, - "requires": { - "call-bind": "^1.0.7", - "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.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" - } - }, - "strip-ansi-cjs": { - "version": "npm:strip-ansi@6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", - "dev": true - }, - "strip-final-newline": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", - "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", - "dev": true - }, - "strip-hex-prefix": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz", - "integrity": "sha512-q8d4ue7JGEiVcypji1bALTos+0pWtyGlivAWyPuTkHzuTCJqrK9sWxYQZUq6Nq3cuyv3bm734IhHvHtGGURU6A==", - "requires": { - "is-hex-prefixed": "1.0.0" - } - }, - "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", - "dev": true - }, - "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" - } - }, - "supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true - }, - "synckit": { - "version": "0.9.2", - "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.2.tgz", - "integrity": "sha512-vrozgXDQwYO72vHjUb/HnFbQx1exDjoKzqx23aXEg2a9VIg2TSFZ8FmeZpTjUCFMYw7mpX4BE2SFu8wI7asYsw==", - "dev": true, - "requires": { - "@pkgr/core": "^0.1.0", - "tslib": "^2.6.2" - } - }, - "table": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/table/-/table-6.9.0.tgz", - "integrity": "sha512-9kY+CygyYM6j02t5YFHbNz2FN5QmYGv9zAjVp4lCDjlCw7amdckXlEt/bjMhUIfj4ThGRE4gCUH5+yGnNuPo5A==", - "dev": true, - "requires": { - "ajv": "^8.0.1", - "lodash.truncate": "^4.4.2", - "slice-ansi": "^4.0.0", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1" - }, - "dependencies": { - "ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "dev": true, - "requires": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - } - }, - "json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true - } - } - }, - "table-layout": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/table-layout/-/table-layout-1.0.2.tgz", - "integrity": "sha512-qd/R7n5rQTRFi+Zf2sk5XVVd9UQl6ZkduPFC3S7WEGJAmetDTjY3qPN50eSKzwuzEyQKy5TN2TiZdkIjos2L6A==", - "dev": true, - "requires": { - "array-back": "^4.0.1", - "deep-extend": "~0.6.0", - "typical": "^5.2.0", - "wordwrapjs": "^4.0.0" - }, - "dependencies": { - "array-back": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.2.tgz", - "integrity": "sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg==", - "dev": true - }, - "typical": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", - "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", - "dev": true - } - } - }, - "tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true - }, - "text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true - }, - "tinyglobby": { - "version": "0.2.10", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.10.tgz", - "integrity": "sha512-Zc+8eJlFMvgatPZTl6A9L/yht8QqdmUNtURHaKZLmKBE12hNPSrqNkUp2cs3M/UKmNVVAMFQYSjYIVHDjW5zew==", - "requires": { - "fdir": "^6.4.2", - "picomatch": "^4.0.2" - }, - "dependencies": { - "fdir": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.2.tgz", - "integrity": "sha512-KnhMXsKSPZlAhp7+IjUkRZKPb4fUyccpDrdFXbi4QL1qkmFh9kVY09Yox+n4MaOb3lHZ1Tv829C3oaaXoMYPDQ==", - "requires": {} - }, - "picomatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", - "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==" - } - } - }, - "tmp": { - "version": "0.0.33", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", - "requires": { - "os-tmpdir": "~1.0.2" - } - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "requires": { - "is-number": "^7.0.0" - } - }, - "toidentifier": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", - "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==" - }, - "treeify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/treeify/-/treeify-1.1.0.tgz", - "integrity": "sha512-1m4RA7xVAJrSGrrXGs0L3YTwyvBs2S8PbRHaLZAkFw7JR8oIFwYtysxlBZhYIa7xSyiYJKZ3iGrrk55cGA3i9A==", - "dev": true - }, - "ts-api-utils": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz", - "integrity": "sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==", - "dev": true, - "requires": {} - }, - "ts-command-line-args": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/ts-command-line-args/-/ts-command-line-args-2.3.1.tgz", - "integrity": "sha512-FR3y7pLl/fuUNSmnPhfLArGqRrpojQgIEEOVzYx9DhTmfIN7C9RWSfpkJEF4J+Gk7aVx5pak8I7vWZsaN4N84g==", - "dev": true, - "requires": { - "chalk": "^4.1.0", - "command-line-args": "^5.1.1", - "command-line-usage": "^6.1.0", - "string-format": "^2.0.0" - } - }, - "ts-essentials": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/ts-essentials/-/ts-essentials-7.0.3.tgz", - "integrity": "sha512-8+gr5+lqO3G84KdiTSMRLtuyJ+nTBVRKuCrK4lidMPdVeEp0uqC875uE5NMcaA7YYMN7XsNiFQuMvasF8HT/xQ==", - "dev": true, - "requires": {} - }, - "ts-node": { - "version": "10.9.2", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", - "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", - "requires": { - "@cspotcode/source-map-support": "^0.8.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.1", - "yn": "3.1.1" - } - }, - "tsconfig-paths": { - "version": "3.15.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", - "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", - "dev": true, - "requires": { - "@types/json5": "^0.0.29", - "json5": "^1.0.2", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" - } - }, - "tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" - }, - "tsort": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/tsort/-/tsort-0.0.1.tgz", - "integrity": "sha512-Tyrf5mxF8Ofs1tNoxA13lFeZ2Zrbd6cKbuH3V+MQ5sb6DtBj5FjrXVsRWT8YvNAQTqNoz66dz1WsbigI22aEnw==" - }, - "tweetnacl": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", - "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==" - }, - "tweetnacl-util": { - "version": "0.15.1", - "resolved": "https://registry.npmjs.org/tweetnacl-util/-/tweetnacl-util-0.15.1.tgz", - "integrity": "sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw==" - }, - "type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "requires": { - "prelude-ls": "^1.2.1" - } - }, - "type-detect": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.1.0.tgz", - "integrity": "sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==", - "dev": true - }, - "type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==" - }, - "typechain": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/typechain/-/typechain-8.3.2.tgz", - "integrity": "sha512-x/sQYr5w9K7yv3es7jo4KTX05CLxOf7TRWwoHlrjRh8H82G64g+k7VuWPJlgMo6qrjfCulOdfBjiaDtmhFYD/Q==", - "dev": true, - "requires": { - "@types/prettier": "^2.1.1", - "debug": "^4.3.1", - "fs-extra": "^7.0.0", - "glob": "7.1.7", - "js-sha3": "^0.8.0", - "lodash": "^4.17.15", - "mkdirp": "^1.0.4", - "prettier": "^2.3.1", - "ts-command-line-args": "^2.2.0", - "ts-essentials": "^7.0.1" - }, - "dependencies": { - "fs-extra": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", - "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } }, - "glob": { - "version": "7.1.7", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", - "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "prettier": { - "version": "2.8.8", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", - "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", - "dev": true - } - } - }, - "typed-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", - "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", - "dev": true, - "requires": { - "call-bind": "^1.0.7", - "es-errors": "^1.3.0", - "is-typed-array": "^1.1.13" - } - }, - "typed-array-byte-length": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", - "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", - "dev": true, - "requires": { - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13" - } - }, - "typed-array-byte-offset": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.3.tgz", - "integrity": "sha512-GsvTyUHTriq6o/bHcTd0vM7OQ9JEdlvluu9YISaA7+KzDzPaIzEeDFNkTfhdE3MYcNhNi0vq/LlegYgIs5yPAw==", - "dev": true, - "requires": { - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-proto": "^1.0.3", - "is-typed-array": "^1.1.13", - "reflect.getprototypeof": "^1.0.6" - } - }, - "typed-array-length": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz", - "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==", - "dev": true, - "requires": { - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "is-typed-array": "^1.1.13", - "possible-typed-array-names": "^1.0.0", - "reflect.getprototypeof": "^1.0.6" - } - }, - "typescript": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.2.tgz", - "integrity": "sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==" - }, - "typical": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/typical/-/typical-4.0.0.tgz", - "integrity": "sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==", - "dev": true - }, - "uglify-js": { - "version": "3.18.0", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.18.0.tgz", - "integrity": "sha512-SyVVbcNBCk0dzr9XL/R/ySrmYf0s372K6/hFklzgcp2lBFyXtw4I7BOdDjlLhE1aVqaI/SHWXWmYdlZxuyF38A==", - "dev": true, - "optional": true - }, - "unbox-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", - "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "has-bigints": "^1.0.2", - "has-symbols": "^1.0.3", - "which-boxed-primitive": "^1.0.2" - } - }, - "undici": { - "version": "5.28.4", - "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.4.tgz", - "integrity": "sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==", - "requires": { - "@fastify/busboy": "^2.0.0" - } - }, - "undici-types": { - "version": "6.19.8", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", - "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==" - }, - "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" - }, - "unpipe": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", - "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==" - }, - "uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "requires": { - "punycode": "^2.1.0" - } - }, - "utf-8-validate": { - "version": "5.0.9", - "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.9.tgz", - "integrity": "sha512-Yek7dAy0v3Kl0orwMlvi7TPtiCNrdfHNd7Gcc/pLq4BLXqfAmd0J7OWMizUQnTTJsyjKn02mU7anqwfmUP4J8Q==", - "optional": true, - "peer": true, - "requires": { - "node-gyp-build": "^4.3.0" - } - }, - "utf8": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/utf8/-/utf8-3.0.0.tgz", - "integrity": "sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ==", - "dev": true - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" - }, - "uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==" - }, - "v8-compile-cache-lib": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", - "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==" - }, - "web-streams-polyfill": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz", - "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==" - }, - "web3-utils": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.10.0.tgz", - "integrity": "sha512-kSaCM0uMcZTNUSmn5vMEhlo02RObGNRRCkdX0V9UTAU0+lrvn0HSaudyCo6CQzuXUsnuY2ERJGCGPfeWmv19Rg==", - "dev": true, - "requires": { - "bn.js": "^5.2.1", - "ethereum-bloom-filters": "^1.0.6", - "ethereumjs-util": "^7.1.0", - "ethjs-unit": "0.1.6", - "number-to-bn": "1.7.0", - "randombytes": "^2.1.0", - "utf8": "3.0.0" - } - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "which-boxed-primitive": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.0.tgz", - "integrity": "sha512-Ei7Miu/AXe2JJ4iNF5j/UphAgRoma4trE6PtisM09bPygb3egMH3YLW/befsWb1A1AxvNSFidOFTB18XtnIIng==", - "dev": true, - "requires": { - "is-bigint": "^1.1.0", - "is-boolean-object": "^1.2.0", - "is-number-object": "^1.1.0", - "is-string": "^1.1.0", - "is-symbol": "^1.1.0" - } - }, - "which-builtin-type": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.0.tgz", - "integrity": "sha512-I+qLGQ/vucCby4tf5HsLmGueEla4ZhwTBSqaooS+Y0BuxN4Cp+okmGuV+8mXZ84KDI9BA+oklo+RzKg0ONdSUA==", - "dev": true, - "requires": { - "call-bind": "^1.0.7", - "function.prototype.name": "^1.1.6", - "has-tostringtag": "^1.0.2", - "is-async-function": "^2.0.0", - "is-date-object": "^1.0.5", - "is-finalizationregistry": "^1.1.0", - "is-generator-function": "^1.0.10", - "is-regex": "^1.1.4", - "is-weakref": "^1.0.2", - "isarray": "^2.0.5", - "which-boxed-primitive": "^1.0.2", - "which-collection": "^1.0.2", - "which-typed-array": "^1.1.15" - } - }, - "which-collection": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", - "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", - "dev": true, - "requires": { - "is-map": "^2.0.3", - "is-set": "^2.0.3", - "is-weakmap": "^2.0.2", - "is-weakset": "^2.0.3" - } - }, - "which-typed-array": { - "version": "1.1.16", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.16.tgz", - "integrity": "sha512-g+N+GAWiRj66DngFwHvISJd+ITsyphZvD1vChfVg6cEdnzy53GzB3oy0fUNlvhz7H7+MiqhYr26qxQShCpKTTQ==", - "dev": true, - "requires": { - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.2" - } - }, - "widest-line": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", - "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", - "requires": { - "string-width": "^4.0.0" - } - }, - "word-wrap": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", - "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", - "dev": true - }, - "wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", - "dev": true - }, - "wordwrapjs": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/wordwrapjs/-/wordwrapjs-4.0.1.tgz", - "integrity": "sha512-kKlNACbvHrkpIw6oPeYDSmdCTu2hdMHoyXLTcUKala++lx5Y+wjJ/e474Jqv5abnVmwxw08DiTuHmw69lJGksA==", - "dev": true, - "requires": { - "reduce-flatten": "^2.0.0", - "typical": "^5.2.0" - }, - "dependencies": { - "typical": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", - "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", - "dev": true - } - } - }, - "workerpool": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", - "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==" - }, - "wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - }, - "wrap-ansi-cjs": { - "version": "npm:wrap-ansi@7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" - }, - "ws": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", - "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", - "requires": {} - }, - "y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==" - }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, - "yaml": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.1.tgz", - "integrity": "sha512-7r0XPzioN/Q9kXBro/XPnA6kznR73DHq+GXh5ON7ZozRO6aMjbmiBuKste2wslTFkC5d1dw0GooOCepZXJ2SAg==", - "dev": true - }, - "yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", - "requires": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - } - }, - "yargs-parser": { - "version": "20.2.4", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", - "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==" - }, - "yargs-unparser": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", - "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", - "requires": { - "camelcase": "^6.0.0", - "decamelize": "^4.0.0", - "flat": "^5.0.2", - "is-plain-obj": "^2.1.0" - }, - "dependencies": { - "is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==" - } - } - }, - "yn": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==" - }, - "yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==" - }, - "zksync-ethers": { - "version": "5.10.0", - "resolved": "https://registry.npmjs.org/zksync-ethers/-/zksync-ethers-5.10.0.tgz", - "integrity": "sha512-OAjTGAHF9wbdkRGkj7XZuF/a1Sk/FVbwH4pmLjAKlR7mJ7sQtQhBhrPU2dCc67xLaNvEESPfwil19ES5wooYFg==", - "requires": { - "ethers": "~5.7.0" - }, - "dependencies": { - "ethers": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.7.2.tgz", - "integrity": "sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg==", - "requires": { - "@ethersproject/abi": "5.7.0", - "@ethersproject/abstract-provider": "5.7.0", - "@ethersproject/abstract-signer": "5.7.0", - "@ethersproject/address": "5.7.0", - "@ethersproject/base64": "5.7.0", - "@ethersproject/basex": "5.7.0", - "@ethersproject/bignumber": "5.7.0", - "@ethersproject/bytes": "5.7.0", - "@ethersproject/constants": "5.7.0", - "@ethersproject/contracts": "5.7.0", - "@ethersproject/hash": "5.7.0", - "@ethersproject/hdnode": "5.7.0", - "@ethersproject/json-wallets": "5.7.0", - "@ethersproject/keccak256": "5.7.0", - "@ethersproject/logger": "5.7.0", - "@ethersproject/networks": "5.7.1", - "@ethersproject/pbkdf2": "5.7.0", - "@ethersproject/properties": "5.7.0", - "@ethersproject/providers": "5.7.2", - "@ethersproject/random": "5.7.0", - "@ethersproject/rlp": "5.7.0", - "@ethersproject/sha2": "5.7.0", - "@ethersproject/signing-key": "5.7.0", - "@ethersproject/solidity": "5.7.0", - "@ethersproject/strings": "5.7.0", - "@ethersproject/transactions": "5.7.0", - "@ethersproject/units": "5.7.0", - "@ethersproject/wallet": "5.7.0", - "@ethersproject/web": "5.7.1", - "@ethersproject/wordlists": "5.7.0" - } + "utf-8-validate": { + "optional": true } } } diff --git a/package.json b/package.json index d1334136..997eb511 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "dkg-evm-module", - "version": "8.0.4", + "version": "8.0.5", "description": "Smart contracts for OriginTrail V8", "main": "index.ts", "files": [ @@ -28,6 +28,7 @@ "author": "", "license": "Apache-2.0", "devDependencies": { + "@nomicfoundation/ethereumjs-util": "^9.0.4", "@nomicfoundation/hardhat-chai-matchers": "^2.0.8", "@nomicfoundation/hardhat-network-helpers": "^1.0.12", "@nomiclabs/hardhat-solhint": "^4.0.1", @@ -38,7 +39,7 @@ "@types/node": "^22.10.2", "@typescript-eslint/eslint-plugin": "^8.18.1", "@typescript-eslint/parser": "^8.18.1", - "assertion-tools": "^2.2.1", + "assertion-tools": "^8.0.3", "chai": "^4.5.0", "cross-env": "^7.0.3", "eslint": "^8.17.0", @@ -116,7 +117,7 @@ "test:parallel": "hardhat test --network hardhat --parallel", "test:trace": "hardhat test --network hardhat --trace", "test:unit": "hardhat test --network hardhat --grep '@unit'", - "test": "hardhat test --network hardhat", + "test": "bash test/scripts/run-tests-with-summary.sh", "typechain": "hardhat typechain" } } diff --git a/test/helpers/blockchain-helpers.ts b/test/helpers/blockchain-helpers.ts new file mode 100644 index 00000000..96788667 --- /dev/null +++ b/test/helpers/blockchain-helpers.ts @@ -0,0 +1,40 @@ +import hre from 'hardhat'; + +import { RandomSampling } from '../../typechain'; + +/** + * Mines a specified number of blocks + * @param blocks Number of blocks to mine + */ +export async function mineBlocks(blocks: number) { + for (let i = 0; i < blocks; i++) { + await hre.network.provider.send('evm_mine'); + } +} + +/** + * Mines blocks until a specific block number is reached + * @param targetBlockNumber Target block number to mine to + */ +export async function mineToBlock(targetBlockNumber: number) { + const currentBlock = await hre.ethers.provider.getBlockNumber(); + if (currentBlock >= targetBlockNumber) { + return; + } + await mineBlocks(targetBlockNumber - currentBlock); +} + +/** + * Mines blocks for a proof period + * @param startBlock Starting block number + * @param randomSamplingStorage RandomSamplingStorage contract instance + * @returns The number of blocks mined + */ +export async function mineProofPeriodBlocks( + randomSampling: RandomSampling, +): Promise { + const proofingPeriodDuration = + await randomSampling.getActiveProofingPeriodDurationInBlocks(); + await mineBlocks(Number(proofingPeriodDuration)); + return BigInt(proofingPeriodDuration); +} diff --git a/test/helpers/setup-helpers.ts b/test/helpers/setup-helpers.ts index 7cf5c109..ae24a898 100644 --- a/test/helpers/setup-helpers.ts +++ b/test/helpers/setup-helpers.ts @@ -1,5 +1,8 @@ import { SignerWithAddress } from '@nomicfoundation/hardhat-ethers/signers'; +import { createProfile } from './profile-helpers'; +import { Ask, Staking, Token, Profile } from '../../typechain'; + export function getDefaultPublishingNode(accounts: SignerWithAddress[]) { return { admin: accounts[1], @@ -20,3 +23,64 @@ export function getDefaultReceivingNodes( export function getDefaultKCCreator(accounts: SignerWithAddress[]) { return accounts[9]; } + +export async function setNodeStake( + node: { operational: SignerWithAddress; admin: SignerWithAddress }, + identityId: bigint, + amount: bigint, + deps: { Token: Token; Staking: Staking; Ask: Ask }, +) { + const { Token, Staking } = deps; + + await Token.mint(node.operational.address, amount); + await Token.connect(node.operational).approve( + await Staking.getAddress(), + amount, + ); + await Staking.connect(node.operational).stake(identityId, amount); +} + +export async function setupNodeWithStakeAndAsk( + accountIndex: number, + stakeAmount: bigint, + askAmount: bigint, + deps: { + accounts: SignerWithAddress[]; + Profile: Profile; + Token: Token; + Staking: Staking; + Ask: Ask; + }, +): Promise<{ + node: { operational: SignerWithAddress; admin: SignerWithAddress }; + identityId: number; +}> { + const { accounts, Profile, Token, Staking, Ask } = deps; + // Use distinct accounts for operational and admin keys + const operationalAccountIndex = accountIndex; + const adminAccountIndex = operationalAccountIndex + 1; + + if (adminAccountIndex >= accounts.length) { + throw new Error( + `Not enough accounts for score test setup (needed index ${adminAccountIndex})`, + ); + } + + const node = { + operational: accounts[operationalAccountIndex], + admin: accounts[adminAccountIndex], + }; + // create profile + const { identityId } = await createProfile(Profile, node); + // set stake + await setNodeStake(node, BigInt(identityId), stakeAmount, { + Token, + Staking, + Ask, + }); + // set ask + await Profile.connect(node.operational).updateAsk(identityId, askAmount); + await Ask.connect(accounts[0]).recalculateActiveSet(); + + return { node, identityId }; +} diff --git a/test/integration/OldParanet.test.ts b/test/integration/OldParanet.test.ts deleted file mode 100644 index 4127bb49..00000000 --- a/test/integration/OldParanet.test.ts +++ /dev/null @@ -1,494 +0,0 @@ -// import { randomBytes } from 'crypto'; - -// import { loadFixture } from '@nomicfoundation/hardhat-network-helpers'; -// import { expect } from 'chai'; -// import { BigNumberish, BytesLike } from 'ethers'; -// import hre from 'hardhat'; -// import { SignerWithAddress } from 'hardhat-deploy-ethers/signers'; -// import { Address } from 'hardhat-deploy/types'; - -// import { -// Paranet, -// ParanetsRegistry, -// ParanetKnowledgeMinersRegistry, -// HubController, -// ContentAssetV2, -// ServiceAgreementV1, -// ContentAssetStorageV2, -// Token, -// ParanetIncentivesPoolFactory, -// } from '../../typechain'; -// import { ContentAssetStructs } from '../../../typechain/contracts/v2/assets/ContentAsset.sol/ContentAssetV2'; - -// type ParanetNeuroIncentivesPoolFixture = { -// accounts: SignerWithAddress[]; -// ContentAsset: ContentAssetV2; -// ContentAssetStorage: ContentAssetStorageV2; -// ServiceAgreementV1: ServiceAgreementV1; -// Token: Token; -// ParanetKnowledgeMinersRegistry: ParanetKnowledgeMinersRegistry; -// ParanetsRegistry: ParanetsRegistry; -// Paranet: Paranet; -// ParanetIncentivesPoolFactory: ParanetIncentivesPoolFactory; -// }; - -// describe('@v2 @integration Paranet', function () { -// let accounts: SignerWithAddress[]; -// let operator: SignerWithAddress; -// let miner: SignerWithAddress; -// let HubController: HubController; -// let ContentAsset: ContentAssetV2; -// let ServiceAgreementV1: ServiceAgreementV1; -// let ContentAssetStorage: ContentAssetStorageV2; -// let Token: Token; -// let ParanetKnowledgeMinersRegistry: ParanetKnowledgeMinersRegistry; -// let ParanetsRegistry: ParanetsRegistry; -// let Paranet: Paranet; -// let ParanetIncentivesPoolFactory: ParanetIncentivesPoolFactory; - -// async function deployParanetNeuroIncentivesPoolFixture(): Promise { -// await hre.deployments.fixture([ -// 'Token', -// 'ServiceAgreementV1', -// 'ContentAssetStorageV2', -// 'ContentAssetV2', -// 'Paranet', -// 'ParanetIncentivesPoolFactory', -// ]); - -// ContentAssetStorage = await hre.ethers.getContract('ContentAssetStorage'); -// ContentAsset = await hre.ethers.getContract('ContentAsset'); -// ServiceAgreementV1 = await hre.ethers.getContract('ServiceAgreementV1'); -// Token = await hre.ethers.getContract('Token'); - -// ParanetKnowledgeMinersRegistry = await hre.ethers.getContract( -// 'ParanetKnowledgeMinersRegistry', -// ); -// ParanetsRegistry = await hre.ethers.getContract('ParanetsRegistry'); -// Paranet = await hre.ethers.getContract('Paranet'); -// ParanetIncentivesPoolFactory = await hre.ethers.getContract( -// 'ParanetIncentivesPoolFactory', -// ); - -// accounts = await hre.ethers.getSigners(); - -// HubController = await hre.ethers.getContract('HubController'); -// await HubController.setContractAddress('HubOwner', accounts[0].address); - -// return { -// accounts, -// ContentAssetStorage, -// ContentAsset, -// ServiceAgreementV1, -// Token, -// ParanetKnowledgeMinersRegistry, -// ParanetsRegistry, -// Paranet, -// ParanetIncentivesPoolFactory, -// }; -// } - -// async function createAsset( -// assetInputStruct: ContentAssetStructs.AssetInputArgsStruct, -// ): Promise<{ tokenId: number; keyword: BytesLike; agreementId: BytesLike }> { -// await Token.connect(operator).increaseAllowance(ServiceAgreementV1.address, assetInputStruct.tokenAmount); -// const receipt = await (await ContentAsset.connect(operator).createAsset(assetInputStruct)).wait(); -// const tokenId = Number(receipt.logs[0].topics[3]); - -// const keyword = hre.ethers.utils.solidityPack( -// ['address', 'bytes32'], -// [ContentAssetStorage.address, assetInputStruct.assertionId], -// ); -// const agreementId = hre.ethers.utils.soliditySha256( -// ['address', 'uint256', 'bytes'], -// [ContentAssetStorage.address, tokenId, keyword], -// ); -// return { tokenId, keyword, agreementId }; -// } - -// async function registerParanet( -// paranetKATokenId: BigNumberish, -// paranetName: string, -// paranetDescription: string, -// tracToNeuroEmissionMultiplier: BigNumberish, -// paranetOperatorRewardPercentage: BigNumberish, -// paranetIncentivizationProposalVotersRewardPercentage: BigNumberish, -// ): Promise<{ paranetId: BytesLike; ParanetNeuroIncentivesPoolAddress: Address }> { -// const tx1 = await Paranet.connect(operator).registerParanet( -// ContentAssetStorage.address, -// paranetKATokenId, -// paranetName, -// paranetDescription, -// 0, -// 0, -// ); -// await tx1.wait(); - -// const tx2 = await ParanetIncentivesPoolFactory.connect(operator).deployNeuroIncentivesPool( -// ContentAssetStorage.address, -// paranetKATokenId, -// tracToNeuroEmissionMultiplier, -// paranetOperatorRewardPercentage, -// paranetIncentivizationProposalVotersRewardPercentage, -// ); -// await tx2.wait(); - -// const paranetId = hre.ethers.utils.keccak256( -// hre.ethers.utils.solidityPack(['address', 'uint256'], [ContentAssetStorage.address, paranetKATokenId]), -// ); -// const ParanetNeuroIncentivesPoolAddress = await ParanetsRegistry.getIncentivesPoolAddress(paranetId, 'Neuroweb'); - -// return { -// paranetId, -// ParanetNeuroIncentivesPoolAddress, -// }; -// } - -// beforeEach(async function () { -// hre.helpers.resetDeploymentsJson(); -// ({ -// accounts, -// ContentAssetStorage, -// ContentAsset, -// ServiceAgreementV1, -// Token, -// ParanetKnowledgeMinersRegistry, -// ParanetsRegistry, -// Paranet, -// ParanetIncentivesPoolFactory, -// } = await loadFixture(deployParanetNeuroIncentivesPoolFixture)); - -// operator = accounts[1]; -// miner = accounts[2]; -// }); - -// it('Should accept native tokens, update balance and variable successfully', async function () { -// const paranetKAStruct: ContentAssetStructs.AssetInputArgsStruct = { -// assertionId: '0x' + randomBytes(32).toString('hex'), -// size: 1000, -// triplesNumber: 10, -// chunksNumber: 10, -// epochsNumber: 5, -// tokenAmount: hre.ethers.utils.parseEther('250'), -// scoreFunctionId: 2, -// immutable_: false, -// }; -// const { tokenId: paranetTokenId } = await createAsset(paranetKAStruct); - -// const { ParanetNeuroIncentivesPoolAddress } = await registerParanet( -// paranetTokenId, -// 'Paranet1', -// 'Test Paranet', -// hre.ethers.utils.parseEther('1'), // tracToNeuroRatio -- 1:1 -// 1000, // paranetOperatorRewardPercentage -- 10% -// 500, // paranetIncentivizationProposalVotersRewardPercentage -- 5% -// ); - -// const ParanetNeuroIncentivesPool = await hre.ethers.getContractAt( -// 'ParanetNeuroIncentivesPool', -// ParanetNeuroIncentivesPoolAddress, -// ); - -// const initialBalance = await ParanetNeuroIncentivesPool.getNeuroBalance(); - -// expect(initialBalance).to.be.equal(0); - -// const value = hre.ethers.utils.parseEther('100'); -// const tx = await operator.sendTransaction({ -// to: ParanetNeuroIncentivesPool.address, -// value, -// }); -// await tx.wait(); - -// const finalBalance = await ParanetNeuroIncentivesPool.getNeuroBalance(); -// const totalNeuroReceived = await ParanetNeuroIncentivesPool.totalNeuroReceived(); - -// expect(finalBalance).to.be.equal(totalNeuroReceived).to.be.equal(value); -// }); - -// // it('Should revert while getting operator reward before miner', async function () { -// // const paranetKAStruct: ContentAssetStructs.AssetInputArgsStruct = { -// // assertionId: '0x' + randomBytes(32).toString('hex'), -// // size: 1000, -// // triplesNumber: 10, -// // chunksNumber: 10, -// // epochsNumber: 5, -// // tokenAmount: hre.ethers.utils.parseEther('250'), -// // scoreFunctionId: 2, -// // immutable_: false, -// // }; -// // const { tokenId: paranetTokenId } = await createAsset(paranetKAStruct); - -// // const { ParanetNeuroIncentivesPoolAddress } = await registerParanet( -// // paranetTokenId, -// // 'Paranet1', -// // 'Test Paranet', -// // hre.ethers.utils.parseEther('1'), // tracToNeuroRatio - 1:1 -// // 1000, // operatorRewardPercentage -- 10% -// // 500, // paranetIncentivizationProposalVotersRewardPercentage -- 5% -// // ); - -// // const ParanetNeuroIncentivesPool = await hre.ethers.getContractAt( -// // 'ParanetNeuroIncentivesPool', -// // ParanetNeuroIncentivesPoolAddress, -// // ); - -// // const value = hre.ethers.utils.parseEther('1000'); -// // const tx = await operator.sendTransaction({ -// // to: ParanetNeuroIncentivesPool.address, -// // value, -// // }); -// // await tx.wait(); - -// // await expect( -// // ParanetNeuroIncentivesPool.connect(operator).claimParanetOperatorReward(), -// // ).to.be.revertedWithCustomError(ParanetNeuroIncentivesPool, 'NoRewardAvailable'); -// // }); - -// it('Should correctly calculate miner reward', async function () { -// const paranetKAStruct: ContentAssetStructs.AssetInputArgsStruct = { -// assertionId: '0x' + randomBytes(32).toString('hex'), -// size: 1000, -// triplesNumber: 10, -// chunksNumber: 10, -// epochsNumber: 5, -// tokenAmount: hre.ethers.utils.parseEther('250'), -// scoreFunctionId: 2, -// immutable_: false, -// }; -// const { tokenId: paranetTokenId } = await createAsset(paranetKAStruct); - -// const { ParanetNeuroIncentivesPoolAddress } = await registerParanet( -// paranetTokenId, -// 'Paranet1', -// 'Test Paranet', -// hre.ethers.utils.parseEther('1'), // tracToNeuroRatio -- 1:1 -// 1000, // operatorRewardPercentage -- 10% -// 500, // paranetIncentivizationProposalVotersRewardPercentage -- 5% -// ); - -// const ParanetNeuroIncentivesPool = await hre.ethers.getContractAt( -// 'ParanetNeuroIncentivesPool', -// ParanetNeuroIncentivesPoolAddress, -// ); - -// const value = hre.ethers.utils.parseEther('5000'); -// const tx1 = await operator.sendTransaction({ -// to: ParanetNeuroIncentivesPool.address, -// value, -// }); -// await tx1.wait(); - -// // Simulate some miner activity -// const testKAStruct: ContentAssetStructs.AssetInputArgsStruct = { -// assertionId: '0x' + randomBytes(32).toString('hex'), -// size: 1000, -// triplesNumber: 10, -// chunksNumber: 10, -// epochsNumber: 5, -// tokenAmount: hre.ethers.utils.parseEther('2500'), // Miner spent 2500 TRAC -// scoreFunctionId: 2, -// immutable_: false, -// }; -// await Token.connect(miner).increaseAllowance(ServiceAgreementV1.address, testKAStruct.tokenAmount); -// await Paranet.connect(miner).mintKnowledgeAsset(ContentAssetStorage.address, paranetTokenId, testKAStruct); - -// const initialMinerBalance = await miner.getBalance(); -// const tx2 = await ParanetNeuroIncentivesPool.connect(miner).claimKnowledgeMinerReward(); -// const tx2Receipt = await tx2.wait(); -// const tx2Details = await hre.ethers.provider.getTransaction(tx2Receipt.transactionHash); -// const finalMinerBalance = await miner.getBalance(); - -// const expectedMinerReward = value.div(2).mul(85).div(100); -// expect(finalMinerBalance.sub(initialMinerBalance).add(tx2Receipt.gasUsed.mul(tx2Details.gasPrice))).to.equal( -// expectedMinerReward, -// ); -// }); - -// it('Should correctly calculate and send operator reward after miners reward', async function () { -// const paranetKAStruct: ContentAssetStructs.AssetInputArgsStruct = { -// assertionId: '0x' + randomBytes(32).toString('hex'), -// size: 1000, -// triplesNumber: 10, -// chunksNumber: 10, -// epochsNumber: 5, -// tokenAmount: hre.ethers.utils.parseEther('250'), -// scoreFunctionId: 2, -// immutable_: false, -// }; -// const { tokenId: paranetTokenId } = await createAsset(paranetKAStruct); - -// const { ParanetNeuroIncentivesPoolAddress } = await registerParanet( -// paranetTokenId, -// 'Paranet1', -// 'Test Paranet', -// hre.ethers.utils.parseEther('1'), // tracToNeuroRatio -- 1:1 -// 1000, // operatorRewardPercentage -- 10% -// 500, // paranetIncentivizationProposalVotersRewardPercentage -- 5% -// ); - -// const ParanetNeuroIncentivesPool = await hre.ethers.getContractAt( -// 'ParanetNeuroIncentivesPool', -// ParanetNeuroIncentivesPoolAddress, -// ); - -// const value = hre.ethers.utils.parseEther('6783'); -// const tx1 = await operator.sendTransaction({ -// to: ParanetNeuroIncentivesPool.address, -// value, -// }); -// await tx1.wait(); - -// // Simulate some miner activity -// const testKAStruct: ContentAssetStructs.AssetInputArgsStruct = { -// assertionId: '0x' + randomBytes(32).toString('hex'), -// size: 1000, -// triplesNumber: 10, -// chunksNumber: 10, -// epochsNumber: 5, -// tokenAmount: hre.ethers.utils.parseEther('2000'), // Miner spent 5000 TRAC -// scoreFunctionId: 2, -// immutable_: false, -// }; -// await Token.connect(miner).increaseAllowance(ServiceAgreementV1.address, testKAStruct.tokenAmount); -// await Paranet.connect(miner).mintKnowledgeAsset(ContentAssetStorage.address, paranetTokenId, testKAStruct); - -// const initialMinerBalance = await miner.getBalance(); -// const tx2 = await ParanetNeuroIncentivesPool.connect(miner).claimKnowledgeMinerReward(); -// const tx2Receipt = await tx2.wait(); -// const tx2Details = await hre.ethers.provider.getTransaction(tx2Receipt.transactionHash); -// const finalMinerBalance = await miner.getBalance(); - -// const expectedMinerReward = hre.ethers.utils.parseEther('2000').mul(85).div(100); -// expect(finalMinerBalance.sub(initialMinerBalance).add(tx2Receipt.gasUsed.mul(tx2Details.gasPrice))).to.equal( -// expectedMinerReward, -// ); - -// const initialOperatorBalance = await operator.getBalance(); -// const tx3 = await ParanetNeuroIncentivesPool.connect(operator).claimParanetOperatorReward(); -// const tx3Receipt = await tx3.wait(); -// const tx3Details = await hre.ethers.provider.getTransaction(tx3Receipt.transactionHash); -// const finalOperatorBalance = await operator.getBalance(); - -// const expectedOperatorReward = hre.ethers.utils.parseEther('2000').mul(10).div(100); -// expect(finalOperatorBalance.sub(initialOperatorBalance).add(tx3Receipt.gasUsed.mul(tx3Details.gasPrice))).to.equal( -// expectedOperatorReward, -// ); -// }); - -// it('Should correctly handle additional Neuro deposit and reward claims', async function () { -// const paranetKAStruct: ContentAssetStructs.AssetInputArgsStruct = { -// assertionId: '0x' + randomBytes(32).toString('hex'), -// size: 1000, -// triplesNumber: 10, -// chunksNumber: 10, -// epochsNumber: 5, -// tokenAmount: hre.ethers.utils.parseEther('250'), -// scoreFunctionId: 2, -// immutable_: false, -// }; -// const { tokenId: paranetTokenId } = await createAsset(paranetKAStruct); - -// const { ParanetNeuroIncentivesPoolAddress } = await registerParanet( -// paranetTokenId, -// 'Paranet1', -// 'Test Paranet', -// hre.ethers.utils.parseEther('1'), // tracToNeuroRatio -- 1:1 -// 1000, // operatorRewardPercentage -- 10% -// 500, // paranetIncentivizationProposalVotersRewardPercentage -- 5% -// ); - -// const ParanetNeuroIncentivesPool = await hre.ethers.getContractAt( -// 'ParanetNeuroIncentivesPool', -// ParanetNeuroIncentivesPoolAddress, -// ); - -// const value = hre.ethers.utils.parseEther('6783'); -// const tx1 = await operator.sendTransaction({ -// to: ParanetNeuroIncentivesPool.address, -// value, -// }); -// await tx1.wait(); - -// // Simulate some miner activity -// const testKAStruct: ContentAssetStructs.AssetInputArgsStruct = { -// assertionId: '0x' + randomBytes(32).toString('hex'), -// size: 1000, -// triplesNumber: 10, -// chunksNumber: 10, -// epochsNumber: 5, -// tokenAmount: hre.ethers.utils.parseEther('2000'), // Miner spent 2000 TRAC -// scoreFunctionId: 2, -// immutable_: false, -// }; -// await Token.connect(miner).increaseAllowance(ServiceAgreementV1.address, testKAStruct.tokenAmount); -// await Paranet.connect(miner).mintKnowledgeAsset(ContentAssetStorage.address, paranetTokenId, testKAStruct); - -// const initialMinerBalance = await miner.getBalance(); -// const tx2 = await ParanetNeuroIncentivesPool.connect(miner).claimKnowledgeMinerReward(); -// const tx2Receipt = await tx2.wait(); -// const tx2Details = await hre.ethers.provider.getTransaction(tx2Receipt.transactionHash); -// const finalMinerBalance = await miner.getBalance(); - -// const expectedMinerReward = hre.ethers.utils.parseEther('2000').mul(85).div(100); -// expect(finalMinerBalance.sub(initialMinerBalance).add(tx2Receipt.gasUsed.mul(tx2Details.gasPrice))).to.equal( -// expectedMinerReward, -// ); - -// const initialOperatorBalance = await operator.getBalance(); -// const tx3 = await ParanetNeuroIncentivesPool.connect(operator).claimParanetOperatorReward(); -// const tx3Receipt = await tx3.wait(); -// const tx3Details = await hre.ethers.provider.getTransaction(tx3Receipt.transactionHash); -// const finalOperatorBalance = await operator.getBalance(); - -// const expectedOperatorReward = hre.ethers.utils.parseEther('2000').mul(10).div(100); -// expect(finalOperatorBalance.sub(initialOperatorBalance).add(tx3Receipt.gasUsed.mul(tx3Details.gasPrice))).to.equal( -// expectedOperatorReward, -// ); - -// // Send additional Neuro to the contract -// const additionalValue = hre.ethers.utils.parseEther('3000'); -// const tx4 = await operator.sendTransaction({ -// to: ParanetNeuroIncentivesPool.address, -// value: additionalValue, -// }); -// await tx4.wait(); - -// // Mint another Knowledge asset from miner address -// const additionalKAStruct: ContentAssetStructs.AssetInputArgsStruct = { -// assertionId: '0x' + randomBytes(32).toString('hex'), -// size: 1000, -// triplesNumber: 10, -// chunksNumber: 10, -// epochsNumber: 5, -// tokenAmount: hre.ethers.utils.parseEther('1500'), // Miner spent 1500 TRAC -// scoreFunctionId: 2, -// immutable_: false, -// }; -// await Token.connect(miner).increaseAllowance(ServiceAgreementV1.address, additionalKAStruct.tokenAmount); -// await Paranet.connect(miner).mintKnowledgeAsset(ContentAssetStorage.address, paranetTokenId, additionalKAStruct); - -// // Claim rewards for miner and operator again -// const initialMinerBalance2 = await miner.getBalance(); -// const tx5 = await ParanetNeuroIncentivesPool.connect(miner).claimKnowledgeMinerReward(); -// const tx5Receipt = await tx5.wait(); -// const tx5Details = await hre.ethers.provider.getTransaction(tx5Receipt.transactionHash); -// const finalMinerBalance2 = await miner.getBalance(); - -// const expectedMinerReward2 = hre.ethers.utils.parseEther('1500').mul(85).div(100); -// expect(finalMinerBalance2.sub(initialMinerBalance2).add(tx5Receipt.gasUsed.mul(tx5Details.gasPrice))).to.equal( -// expectedMinerReward2, -// ); - -// const initialOperatorBalance2 = await operator.getBalance(); -// const tx6 = await ParanetNeuroIncentivesPool.connect(operator).claimParanetOperatorReward(); -// const tx6Receipt = await tx6.wait(); -// const tx6Details = await hre.ethers.provider.getTransaction(tx6Receipt.transactionHash); -// const finalOperatorBalance2 = await operator.getBalance(); - -// const expectedOperatorReward2 = hre.ethers.utils.parseEther('1500').mul(10).div(100); -// expect( -// finalOperatorBalance2.sub(initialOperatorBalance2).add(tx6Receipt.gasUsed.mul(tx6Details.gasPrice)), -// ).to.equal(expectedOperatorReward2); -// }); -// }); diff --git a/test/integration/RandomSampling.test.ts b/test/integration/RandomSampling.test.ts new file mode 100644 index 00000000..75661c4e --- /dev/null +++ b/test/integration/RandomSampling.test.ts @@ -0,0 +1,2888 @@ +import { SignerWithAddress } from '@nomicfoundation/hardhat-ethers/signers'; +import { loadFixture, time } from '@nomicfoundation/hardhat-network-helpers'; +// @ts-expect-error: No type definitions available for assertion-tools +import { kcTools } from 'assertion-tools'; +import { expect } from 'chai'; +import hre, { network } from 'hardhat'; + +import { + RandomSampling, + RandomSamplingStorage, + IdentityStorage, + StakingStorage, + KnowledgeCollectionStorage, + ProfileStorage, + EpochStorage, + Chronos, + AskStorage, + DelegatorsInfo, + Profile, + Hub, + Token, + KnowledgeCollection, + ParanetKnowledgeMinersRegistry, + ParanetKnowledgeCollectionsRegistry, + Staking, + ShardingTableStorage, + ShardingTable, + ParametersStorage, + Ask, +} from '../../typechain'; +import { createKnowledgeCollection } from '../helpers/kc-helpers'; +import { createProfile, createProfiles } from '../helpers/profile-helpers'; +import { + getDefaultKCCreator, + getDefaultReceivingNodes, + getDefaultPublishingNode, + setupNodeWithStakeAndAsk, + setNodeStake, +} from '../helpers/setup-helpers'; + +// Sample values for tests +const SCALING_FACTOR = 10n ** 18n; +const quads = [ + ' "468.9 sq mi" .', + ' "New York" .', + ' "8,336,817" .', + ' "New York" .', + ' .', + ' "0xaac2a420672a1eb77506c544ff01beed2be58c0ee3576fe037c846f97481cefd" .', + ' .', + ' .', + ' .', +]; +// Generate the Merkle tree and get the root +const merkleRoot = kcTools.calculateMerkleRoot(quads, 32); + +// Fixture containing all contracts and accounts needed to test RandomSampling +type RandomSamplingFixture = { + accounts: SignerWithAddress[]; + RandomSampling: RandomSampling; + RandomSamplingStorage: RandomSamplingStorage; + IdentityStorage: IdentityStorage; + StakingStorage: StakingStorage; + KnowledgeCollectionStorage: KnowledgeCollectionStorage; + ProfileStorage: ProfileStorage; + EpochStorage: EpochStorage; + Chronos: Chronos; + AskStorage: AskStorage; + DelegatorsInfo: DelegatorsInfo; + Profile: Profile; + Hub: Hub; + KnowledgeCollection: KnowledgeCollection; + Token: Token; + ParanetKnowledgeMinersRegistry: ParanetKnowledgeMinersRegistry; + ParanetKnowledgeCollectionsRegistry: ParanetKnowledgeCollectionsRegistry; + Staking: Staking; + ShardingTableStorage: ShardingTableStorage; + ShardingTable: ShardingTable; + ParametersStorage: ParametersStorage; + Ask: Ask; +}; + +async function calculateExpectedNodeScore( + identityId: bigint, + nodeStake: bigint, + deps: { + ParametersStorage: ParametersStorage; + ProfileStorage: ProfileStorage; + AskStorage: AskStorage; + EpochStorage: EpochStorage; + }, +): Promise { + const { ParametersStorage, ProfileStorage, AskStorage, EpochStorage } = deps; + // Cap stake at maximum + const maximumStake = await ParametersStorage.maximumStake(); + const cappedStake = nodeStake > maximumStake ? maximumStake : nodeStake; + + // 1. Stake Factor + const stakeRatio = (cappedStake * SCALING_FACTOR) / maximumStake; + const nodeStakeFactor = (2n * stakeRatio ** 2n) / SCALING_FACTOR; + + // 2. Ask Factor + const nodeAsk = await ProfileStorage.getAsk(identityId); + const nodeAskScaled = nodeAsk * SCALING_FACTOR; + const [askLowerBound, askUpperBound] = await AskStorage.getAskBounds(); + let nodeAskFactor = 0n; + + if (nodeAskScaled <= askUpperBound && nodeAskScaled >= askLowerBound) { + const askBoundsDiff = askUpperBound - askLowerBound; + if (askBoundsDiff > 0n) { + // Prevent division by zero + const askDiffRatio = + ((askUpperBound - nodeAskScaled) * SCALING_FACTOR) / askBoundsDiff; + // Ensure intermediate multiplication doesn't overflow - use SCALING_FACTOR**2n directly + nodeAskFactor = + (stakeRatio * askDiffRatio ** 2n) / (SCALING_FACTOR * SCALING_FACTOR); + } else { + // If bounds are equal and ask matches, ratio is effectively 0 or 1 depending on perspective, + // but safer to assign 0 as boundsDiff is 0. + nodeAskFactor = 0n; + } + } + + // 3. Publishing Factor + // Assuming this test runs in an epoch where production has happened + const nodePubFactor = + await EpochStorage.getNodeCurrentEpochProducedKnowledgeValue(identityId); + const maxNodePubFactor = + await EpochStorage.getCurrentEpochNodeMaxProducedKnowledgeValue(); + let nodePublishingFactor = 0n; + if (maxNodePubFactor > 0n) { + // Prevent division by zero + const pubRatio = (nodePubFactor * SCALING_FACTOR) / maxNodePubFactor; + nodePublishingFactor = (nodeStakeFactor * pubRatio) / SCALING_FACTOR; + } + + return nodeStakeFactor + nodePublishingFactor + nodeAskFactor; +} + +describe('@integration RandomSampling', () => { + let accounts: SignerWithAddress[]; + let RandomSampling: RandomSampling; + let RandomSamplingStorage: RandomSamplingStorage; + let IdentityStorage: IdentityStorage; + let StakingStorage: StakingStorage; + let KnowledgeCollectionStorage: KnowledgeCollectionStorage; + let ProfileStorage: ProfileStorage; + let EpochStorage: EpochStorage; + let Chronos: Chronos; + let AskStorage: AskStorage; + let Ask: Ask; + let DelegatorsInfo: DelegatorsInfo; + let Profile: Profile; + let Hub: Hub; + let KnowledgeCollection: KnowledgeCollection; + let Token: Token; + let Staking: Staking; + let ShardingTableStorage: ShardingTableStorage; + let ShardingTable: ShardingTable; + let ParametersStorage: ParametersStorage; + let ParanetKnowledgeMinersRegistry: ParanetKnowledgeMinersRegistry; + let ParanetKnowledgeCollectionsRegistry: ParanetKnowledgeCollectionsRegistry; + + // Deploy all contracts, set the HubOwner and necessary accounts. Returns the RandomSamplingFixture + async function deployRandomSamplingFixture(): Promise { + await hre.deployments.fixture([ + 'KnowledgeCollection', + 'Token', + 'IdentityStorage', + 'StakingStorage', + 'ProfileStorage', + 'EpochStorage', + 'Chronos', + 'AskStorage', + 'DelegatorsInfo', + 'Profile', + 'RandomSamplingStorage', + 'RandomSampling', + 'ParanetKnowledgeMinersRegistry', + 'ParanetKnowledgeCollectionsRegistry', + 'Staking', + 'Ask', + ]); + + accounts = await hre.ethers.getSigners(); + Hub = await hre.ethers.getContract('Hub'); + + // Set hub owner + await Hub.setContractAddress('HubOwner', accounts[0].address); + + // Get contract instances + KnowledgeCollection = await hre.ethers.getContract( + 'KnowledgeCollection', + ); + Token = await hre.ethers.getContract('Token'); + ParanetKnowledgeMinersRegistry = + await hre.ethers.getContract( + 'ParanetKnowledgeMinersRegistry', + ); + ParanetKnowledgeCollectionsRegistry = + await hre.ethers.getContract( + 'ParanetKnowledgeCollectionsRegistry', + ); + IdentityStorage = + await hre.ethers.getContract('IdentityStorage'); + StakingStorage = + await hre.ethers.getContract('StakingStorage'); + KnowledgeCollectionStorage = + await hre.ethers.getContract( + 'KnowledgeCollectionStorage', + ); + ProfileStorage = + await hre.ethers.getContract('ProfileStorage'); + EpochStorage = await hre.ethers.getContract('EpochStorageV8'); + Chronos = await hre.ethers.getContract('Chronos'); + AskStorage = await hre.ethers.getContract('AskStorage'); + DelegatorsInfo = + await hre.ethers.getContract('DelegatorsInfo'); + Profile = await hre.ethers.getContract('Profile'); + Staking = await hre.ethers.getContract('Staking'); + ShardingTableStorage = await hre.ethers.getContract( + 'ShardingTableStorage', + ); + ShardingTable = + await hre.ethers.getContract('ShardingTable'); + ParametersStorage = + await hre.ethers.getContract('ParametersStorage'); + Ask = await hre.ethers.getContract('Ask'); + + // Get RandomSampling contract after all others are registered + RandomSampling = + await hre.ethers.getContract('RandomSampling'); + RandomSamplingStorage = await hre.ethers.getContract( + 'RandomSamplingStorage', + ); + + // Now initialize RandomSampling manually if needed + // This might not be necessary if initialization happens automatically in the deployment + + return { + accounts, + RandomSampling, + RandomSamplingStorage, + IdentityStorage, + StakingStorage, + KnowledgeCollectionStorage, + ProfileStorage, + EpochStorage, + Chronos, + AskStorage, + DelegatorsInfo, + Profile, + Hub, + KnowledgeCollection, + Token, + ParanetKnowledgeMinersRegistry, + ParanetKnowledgeCollectionsRegistry, + Staking, + ShardingTableStorage, + ShardingTable, + ParametersStorage, + Ask, + }; + } + + // Before each test, deploy all contracts and necessary accounts. These variables can be used in the tests + beforeEach(async () => { + ({ + accounts, + IdentityStorage, + StakingStorage, + KnowledgeCollectionStorage, + ProfileStorage, + EpochStorage, + Chronos, + AskStorage, + DelegatorsInfo, + Profile, + Hub, + RandomSampling, + RandomSamplingStorage, + ParanetKnowledgeMinersRegistry, + ParanetKnowledgeCollectionsRegistry, + Staking, + ShardingTableStorage, + ShardingTable, + ParametersStorage, + Ask, + } = await loadFixture(deployRandomSamplingFixture)); + }); + + describe('Contract Initialization', () => { + it('Should return the correct name and version of the RandomSampling contract', async () => { + const name = await RandomSampling.name(); + const version = await RandomSampling.version(); + expect(name).to.equal('RandomSampling'); + expect(version).to.equal('1.0.0'); + }); + + it('Should have the correct W1 after initialization', async () => { + const W1 = await RandomSamplingStorage.getW1(); + expect(W1).to.equal(0); + }); + + it('Should have the correct W2 after initialization', async () => { + const W2 = await RandomSamplingStorage.getW2(); + expect(W2).to.equal(2); + }); + + it('Should successfully initialize with all dependent contracts', async () => { + // Verify that all contract references are set correctly + expect(await RandomSampling.identityStorage()).to.equal( + await IdentityStorage.getAddress(), + ); + expect(await RandomSampling.randomSamplingStorage()).to.equal( + await RandomSamplingStorage.getAddress(), + ); + expect(await RandomSampling.knowledgeCollectionStorage()).to.equal( + await KnowledgeCollectionStorage.getAddress(), + ); + expect(await RandomSampling.stakingStorage()).to.equal( + await StakingStorage.getAddress(), + ); + expect(await RandomSampling.profileStorage()).to.equal( + await ProfileStorage.getAddress(), + ); + expect(await RandomSampling.epochStorage()).to.equal( + await EpochStorage.getAddress(), + ); + expect(await RandomSampling.chronos()).to.equal( + await Chronos.getAddress(), + ); + expect(await RandomSampling.askStorage()).to.equal( + await AskStorage.getAddress(), + ); + expect(await RandomSampling.delegatorsInfo()).to.equal( + await DelegatorsInfo.getAddress(), + ); + }); + }); + + describe('Proofing Period Duration Management', () => { + it('Should add proofing period duration if none is pending', async () => { + // Setup + const currentEpoch = await Chronos.getCurrentEpoch(); + const initialDuration = + await RandomSampling.getActiveProofingPeriodDurationInBlocks(); + const newDuration = initialDuration + 10n; + const expectedEffectiveEpoch = currentEpoch + 1n; + const hubOwner = accounts[0]; + + // Ensure no pending change initially + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + expect( + await RandomSampling.isPendingProofingPeriodDuration(), + 'Should be no pending duration initially', + ).to.be.false; + + // Action + const setDurationTx = + await RandomSampling.connect( + hubOwner, + ).setProofingPeriodDurationInBlocks(newDuration); + + // Verification + // 1. Event Emission + await expect(setDurationTx) + .to.emit(RandomSamplingStorage, 'ProofingPeriodDurationAdded') + .withArgs(newDuration, expectedEffectiveEpoch); + + // 2. Pending state updated + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + expect( + await RandomSampling.isPendingProofingPeriodDuration(), + 'Should be a pending duration after setting', + ).to.be.true; + + // 3. Active duration remains unchanged in the current epoch + expect( + await RandomSampling.getActiveProofingPeriodDurationInBlocks(), + 'Active duration should remain unchanged in current epoch', + ).to.equal(initialDuration); + }); + + it('Should replace pending proofing period duration if one exists', async () => { + // Setup + const currentEpoch = await Chronos.getCurrentEpoch(); + const initialDuration = + await RandomSampling.getActiveProofingPeriodDurationInBlocks(); + const firstNewDuration = initialDuration + 10n; + const secondNewDuration = firstNewDuration + 10n; + const expectedEffectiveEpoch = currentEpoch + 1n; + const hubOwner = accounts[0]; + + // Add the first pending change + await RandomSampling.connect(hubOwner).setProofingPeriodDurationInBlocks( + firstNewDuration, + ); + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + expect( + await RandomSampling.isPendingProofingPeriodDuration(), + 'Should have pending duration after first set', + ).to.be.true; + + // Action: Replace the pending change + const replaceDurationTx = + await RandomSampling.connect( + hubOwner, + ).setProofingPeriodDurationInBlocks(secondNewDuration); + + // Verification + // 1. Event Emission + await expect(replaceDurationTx) + .to.emit(RandomSamplingStorage, 'PendingProofingPeriodDurationReplaced') + .withArgs(firstNewDuration, secondNewDuration, expectedEffectiveEpoch); + + // 2. Pending state remains true + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + expect( + await RandomSampling.isPendingProofingPeriodDuration(), + 'Should still have pending duration after replace', + ).to.be.true; + + // 3. Active duration remains unchanged in the current epoch + expect( + await RandomSampling.getActiveProofingPeriodDurationInBlocks(), + 'Active duration should remain unchanged', + ).to.equal(initialDuration); + + // 4. Check the actual pending value + // Advance to the effective epoch + const timeUntilNextEpoch = await Chronos.timeUntilNextEpoch(); + await time.increase(Number(timeUntilNextEpoch) + 10); + + expect( + await Chronos.getCurrentEpoch(), + 'Should be in the next epoch', + ).to.equal(expectedEffectiveEpoch); + expect( + await RandomSampling.getActiveProofingPeriodDurationInBlocks(), + 'Active duration should be updated in effective epoch', + ).to.equal(secondNewDuration); + }); + + it('Should correctly apply the new duration only in the effective epoch', async () => { + // Setup + const currentEpoch = await Chronos.getCurrentEpoch(); + const effectiveEpoch = currentEpoch + 1n; + const initialDuration = + await RandomSampling.getActiveProofingPeriodDurationInBlocks(); + const newDuration = initialDuration + 20n; // Different new duration + const hubOwner = accounts[0]; + + // Schedule change for next epoch + await RandomSampling.connect(hubOwner).setProofingPeriodDurationInBlocks( + newDuration, + ); + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + expect( + await RandomSampling.isPendingProofingPeriodDuration(), + 'Duration change should be pending', + ).to.be.true; + + // Ensure activeProofPeriodStartBlock is initialized if needed + let initialStartBlockE = ( + await RandomSampling.getActiveProofPeriodStatus() + ).activeProofPeriodStartBlock; + if (initialStartBlockE === 0n) { + await RandomSampling.updateAndGetActiveProofPeriodStartBlock(); + initialStartBlockE = (await RandomSampling.getActiveProofPeriodStatus()) + .activeProofPeriodStartBlock; + } + expect(initialStartBlockE).to.be.greaterThan( + 0n, + 'Initial start block should be > 0', + ); + + // --- Verification in Current Epoch (Epoch E) --- + expect( + await RandomSampling.getActiveProofingPeriodDurationInBlocks(), + 'Active duration should be initial in Epoch E', + ).to.equal(initialDuration); + + // Advance blocks within Epoch E by the initial duration + for (let i = 0; i < Number(initialDuration); i++) { + await hre.network.provider.send('evm_mine'); + } + + // Update period and check if it used the initial duration + await RandomSampling.updateAndGetActiveProofPeriodStartBlock(); + const updatedStartBlockE = ( + await RandomSampling.getActiveProofPeriodStatus() + ).activeProofPeriodStartBlock; + expect(updatedStartBlockE).to.equal( + initialStartBlockE + initialDuration, + 'Start block should advance by initial duration in Epoch E', + ); + + // --- Advance to Next Epoch (Epoch E+1) --- + const timeUntilNextEpoch = await Chronos.timeUntilNextEpoch(); + await time.increase(Number(timeUntilNextEpoch) + 5); + expect( + await Chronos.getCurrentEpoch(), + 'Should now be in the effective epoch', + ).to.equal(effectiveEpoch); + + expect( + await Chronos.getCurrentEpoch(), + 'Should now be in the effective epoch', + ).to.equal(effectiveEpoch); + + // --- Verification in Effective Epoch (Epoch E+1) --- + expect( + await RandomSampling.getActiveProofingPeriodDurationInBlocks(), + 'Active duration should be new in Epoch E+1', + ).to.equal(newDuration); + + // Get the start block relevant for this new epoch + // It might have carried over or been updated by the block advance + await RandomSampling.updateAndGetActiveProofPeriodStartBlock(); + const startBlockE1 = (await RandomSampling.getActiveProofPeriodStatus()) + .activeProofPeriodStartBlock; + + // Advance blocks within Epoch E+1 by the *new* duration + for (let i = 0; i < Number(newDuration); i++) { + await hre.network.provider.send('evm_mine'); + } + + // Update period and check if it used the new duration + await RandomSampling.updateAndGetActiveProofPeriodStartBlock(); + const updatedStartBlockE1 = ( + await RandomSampling.getActiveProofPeriodStatus() + ).activeProofPeriodStartBlock; + expect(updatedStartBlockE1).to.equal( + startBlockE1 + newDuration, + 'Start block should advance by new duration in Epoch E+1', + ); + }); + }); + + describe('Challenge Creation', () => { + it('Should revert if an unsolved challenge already exists for this node in the current proof period', async () => { + // creator of the KC + const kcCreator = getDefaultKCCreator(accounts); + // create a publishing node with stake and ask + const nodeAsk = 200000000000000000n; // Same as 0.2 ETH + const minStake = await ParametersStorage.minimumStake(); + const deps = { + accounts, + Profile, + Token, + Staking, + Ask, + KnowledgeCollection, + }; + const { node: publishingNode, identityId: publishingNodeIdentityId } = + await setupNodeWithStakeAndAsk(1, minStake, 100n, deps); + // create receiving nodes + const receivingNodes = []; + const receivingNodesIdentityIds = []; + for (let i = 0; i < 5; i++) { + const { node, identityId } = await setupNodeWithStakeAndAsk( + i + 10, + minStake, + nodeAsk, + deps, + ); + receivingNodes.push(node); + receivingNodesIdentityIds.push(identityId); + } + + await createKnowledgeCollection( + kcCreator, + publishingNode, + publishingNodeIdentityId, + receivingNodes, + receivingNodesIdentityIds, + deps, + merkleRoot, + ); + + // Create first challenge + const tx1 = await RandomSampling.connect( + publishingNode.operational, + ).createChallenge(); + await tx1.wait(); + const challenge1 = await RandomSamplingStorage.getNodeChallenge( + publishingNodeIdentityId, + ); + + // Mine some blocks but stay within the period + const duration = + await RandomSampling.getActiveProofingPeriodDurationInBlocks(); + if (Number(duration) > 2) { + await hre.network.provider.send('evm_mine'); + } + + // Attempt to create second challenge - should revert + const tx2 = RandomSampling.connect( + publishingNode.operational, + ).createChallenge(); + await expect(tx2).to.be.revertedWith( + 'An unsolved challenge already exists for this node in the current proof period', + ); + + // Verify stored challenge hasn't changed + const challenge2 = await RandomSamplingStorage.getNodeChallenge( + publishingNodeIdentityId, + ); + expect(challenge2.knowledgeCollectionId).to.equal( + challenge1.knowledgeCollectionId, + ); + expect(challenge2.chunkId).to.equal(challenge1.chunkId); + expect(challenge2.epoch).to.equal(challenge1.epoch); + expect(challenge2.activeProofPeriodStartBlock).to.equal( + challenge1.activeProofPeriodStartBlock, + ); + expect(challenge2.proofingPeriodDurationInBlocks).to.equal( + challenge1.proofingPeriodDurationInBlocks, + ); + expect(challenge2.solved).to.equal(challenge1.solved); // Both false + }); + + it('Should revert if the challenge for this proof period has already been solved', async () => { + // Create profile and identity first + const kcCreator = getDefaultKCCreator(accounts); + const nodeAsk = 200000000000000000n; // Same as 0.2 ETH + const minStake = await ParametersStorage.minimumStake(); + const deps = { + accounts, + Profile, + Token, + Staking, + Ask, + KnowledgeCollection, + }; + const { node: publishingNode, identityId: publishingNodeIdentityId } = + await setupNodeWithStakeAndAsk(1, minStake, nodeAsk, deps); + + const receivingNodes = []; + const receivingNodesIdentityIds = []; + for (let i = 0; i < 5; i++) { + const { node, identityId } = await setupNodeWithStakeAndAsk( + i + 10, + minStake, + nodeAsk, + deps, + ); + receivingNodes.push(node); + receivingNodesIdentityIds.push(identityId); + } + + await createKnowledgeCollection( + kcCreator, + publishingNode, + publishingNodeIdentityId, + receivingNodes, + receivingNodesIdentityIds, + deps, + merkleRoot, + ); + + // Create first challenge + const tx1 = await RandomSampling.connect( + publishingNode.operational, + ).createChallenge(); + await tx1.wait(); + const challenge = await RandomSamplingStorage.getNodeChallenge( + publishingNodeIdentityId, + ); + + // Mark the challenge as solved + const solvedChallenge = { + knowledgeCollectionId: challenge.knowledgeCollectionId, + chunkId: challenge.chunkId, + knowledgeCollectionStorageContract: + challenge.knowledgeCollectionStorageContract, + epoch: challenge.epoch, + activeProofPeriodStartBlock: challenge.activeProofPeriodStartBlock, + proofingPeriodDurationInBlocks: + challenge.proofingPeriodDurationInBlocks, + solved: true, + }; + + // Store the mock challenge in the storage contract + await RandomSamplingStorage.setNodeChallenge( + publishingNodeIdentityId, + solvedChallenge, + ); + + // Try to create a new challenge for the same period - should revert + const challengeTx = RandomSampling.connect( + publishingNode.operational, + ).createChallenge(); + await expect(challengeTx).to.be.revertedWith( + 'The challenge for this proof period has already been solved', + ); + }); + + it('Should revert if no Knowledge Collections exist in the system', async () => { + // Setup a node profile + const publishingNode = getDefaultPublishingNode(accounts); + + const { identityId: publishingNodeIdentityId } = await createProfile( + Profile, + publishingNode, + ); + + const minStake = await ParametersStorage.minimumStake(); + await setNodeStake( + publishingNode, + BigInt(publishingNodeIdentityId), + BigInt(minStake), + { + Token, + Staking, + Ask, + }, + ); + await Profile.connect(publishingNode.operational).updateAsk( + BigInt(publishingNodeIdentityId), + 100n, + ); + await Ask.connect(accounts[0]).recalculateActiveSet(); + + // Ensure no KCs are created or they are expired (by default none are created here) + + // Attempt to create challenge + const createTx = RandomSampling.connect( + publishingNode.operational, + ).createChallenge(); + + // Verification + await expect(createTx).to.be.revertedWith( + 'No knowledge collections exist', + ); + }); + + it('Should set the node challenge successfully and emit ChallengeCreated event', async () => { + const kcCreator = getDefaultKCCreator(accounts); + const publishingNode = getDefaultPublishingNode(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); + + // Create profiles and KC first + const contracts = { + Profile, + KnowledgeCollection, + Token, + }; + + const { identityId: publishingNodeIdentityId } = await createProfile( + contracts.Profile, + publishingNode, + ); + const receivingNodesIdentityIds = ( + await createProfiles(contracts.Profile, receivingNodes) + ).map((p) => p.identityId); + + await createKnowledgeCollection( + kcCreator, + publishingNode, + publishingNodeIdentityId, + receivingNodes, + receivingNodesIdentityIds, + contracts, + ); + + // Update and get the new active proof period + const tx = await RandomSampling.updateAndGetActiveProofPeriodStartBlock(); + await tx.wait(); + + const proofPeriodStatus = + await RandomSampling.getActiveProofPeriodStatus(); + const proofPeriodStartBlock = + proofPeriodStatus.activeProofPeriodStartBlock; + // Create challenge + const challengeTx = await RandomSampling.connect( + publishingNode.operational, + ).createChallenge(); + const receipt = await challengeTx.wait(); + + // Get the challenge from storage to verify it + const challenge = await RandomSamplingStorage.getNodeChallenge( + publishingNodeIdentityId, + ); + + await expect(receipt) + .to.emit(RandomSamplingStorage, 'NodeChallengeSet') + .withArgs(publishingNodeIdentityId, challenge); + + const proofPeriodDuration = + await RandomSampling.getActiveProofingPeriodDurationInBlocks(); + + // Verify challenge properties + expect(challenge.knowledgeCollectionId) + .to.be.a('bigint') + .and.to.be.equal(1n); + expect(challenge.chunkId).to.be.a('bigint').and.to.be.greaterThan(0n); + expect(challenge.epoch).to.be.a('bigint').and.to.be.equal(1n); + expect(challenge.activeProofPeriodStartBlock) + .to.be.a('bigint') + .and.to.be.equal(proofPeriodStartBlock); + expect(challenge.proofingPeriodDurationInBlocks) + .to.be.a('bigint') + .and.to.be.equal(proofPeriodDuration); + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + expect(challenge.solved).to.be.false; + }); + + it('Should revert if it fails to find a Knowledge Collection that is active in the current epoch', async () => { + // Setup: create node profile/stake/ask + const nodeAsk = 200000000000000000n; + const minStake = await ParametersStorage.minimumStake(); + const deps = { + accounts, + Profile, + Token, + Staking, + Ask, + KnowledgeCollection, + }; + const { node: publishingNode, identityId: publishingNodeIdentityId } = + await setupNodeWithStakeAndAsk(1, minStake, nodeAsk, deps); + + // Create a KC but set its endEpoch to be in the past (e.g., epoch 0) + const kcCreator = getDefaultKCCreator(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); + const receivingNodesIdentityIds = ( + await createProfiles(Profile, receivingNodes) + ).map((p) => p.identityId); + const currentEpoch = await Chronos.getCurrentEpoch(); + expect(currentEpoch).to.be.greaterThan( + 0n, + 'Test requires current epoch > 0', + ); // Ensure test premise is valid + + // Use createKnowledgeCollection helper, setting endEpoch manually if possible, + // or directly interact with KnowledgeCollection contract + + const epochs = 1; + + await createKnowledgeCollection( + kcCreator, + publishingNode, + publishingNodeIdentityId, + receivingNodes, + receivingNodesIdentityIds, + deps, + ); + + // Advance to epochs + 10 + for (let i = 0; i < epochs + 10; i++) { + const timeUntilNextEpoch = await Chronos.timeUntilNextEpoch(); + await time.increase(Number(timeUntilNextEpoch) + 5); + } + + // Action: Call createChallenge + const createTx = RandomSampling.connect( + publishingNode.operational, + ).createChallenge(); + + // Verification: Expect revert with the specific message + await expect(createTx).to.be.revertedWith( + 'Failed to find a knowledge collection that is active in the current epoch', + ); + }); + }); + + describe('Proof Submission', () => { + it('Should revert if challenge is no longer active', async () => { + // Setup + const kcCreator = getDefaultKCCreator(accounts); + const publishingNode = getDefaultPublishingNode(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); + const contracts = { + Profile, + KnowledgeCollection, + Token, + }; + + const { identityId: publishingNodeIdentityId } = await createProfile( + contracts.Profile, + publishingNode, + ); + const receivingNodesIdentityIds = ( + await createProfiles(contracts.Profile, receivingNodes) + ).map((p) => p.identityId); + + await createKnowledgeCollection( + kcCreator, + publishingNode, + publishingNodeIdentityId, + receivingNodes, + receivingNodesIdentityIds, + contracts, + ); + const minStake = await ParametersStorage.minimumStake(); + await setNodeStake( + publishingNode, + BigInt(publishingNodeIdentityId), + BigInt(minStake), + { Token, Staking, Ask }, + ); + await Profile.connect(publishingNode.operational).updateAsk( + BigInt(publishingNodeIdentityId), + 100n, + ); + await Ask.connect(accounts[0]).recalculateActiveSet(); + + // Create challenge + await RandomSampling.connect( + publishingNode.operational, + ).createChallenge(); + const challenge = await RandomSamplingStorage.getNodeChallenge( + publishingNodeIdentityId, + ); + + // Advance time past the end of the proof period + const duration = challenge.proofingPeriodDurationInBlocks; + // Move past the end block + for (let i = 0; i < Number(duration) + 1; i++) { + await hre.network.provider.send('evm_mine'); + } + + // Try to submit proof + const chunks = kcTools.splitIntoChunks(quads, 32); + const challengeChunk = chunks[challenge.chunkId]; + const { proof } = kcTools.calculateMerkleProof( + quads, + 32, + Number(challenge.chunkId), + ); + + const submitProofTx = RandomSampling.connect( + publishingNode.operational, + ).submitProof(challengeChunk, proof); + + // We check the return value if the function signature allows, or check state hasn't changed. + // In this case, checking the stored challenge state: + await expect(submitProofTx).to.be.revertedWith( + 'This challenge is no longer active', + ); + }); + + it("Should revert with MerkleRootMismatchError if merkle roots don't match", async () => { + // Setup + const kcCreator = getDefaultKCCreator(accounts); + const publishingNode = getDefaultPublishingNode(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); + const contracts = { + Profile, + KnowledgeCollection, + Token, + }; + + const { identityId: publishingNodeIdentityId } = await createProfile( + contracts.Profile, + publishingNode, + ); + const receivingNodesIdentityIds = ( + await createProfiles(contracts.Profile, receivingNodes) + ).map((p) => p.identityId); + + await createKnowledgeCollection( + kcCreator, + publishingNode, + publishingNodeIdentityId, + receivingNodes, + receivingNodesIdentityIds, + contracts, + ); + const minStake = await ParametersStorage.minimumStake(); + await setNodeStake( + publishingNode, + BigInt(publishingNodeIdentityId), + BigInt(minStake), + { Token, Staking, Ask }, + ); + await Profile.connect(publishingNode.operational).updateAsk( + publishingNodeIdentityId, + 100n, + ); + await Ask.connect(accounts[0]).recalculateActiveSet(); + + // Create challenge + const challengeTx = await RandomSampling.connect( + publishingNode.operational, + ).createChallenge(); + await challengeTx.wait(); + const challenge = await RandomSamplingStorage.getNodeChallenge( + publishingNodeIdentityId, + ); + + // Generate invalid proof data + const chunks = kcTools.splitIntoChunks(quads, 32); + const correctChunk = chunks[challenge.chunkId]; + const wrongChunk = + challenge.chunkId + 1n < chunks.length + ? chunks[challenge.chunkId + 1n] + : challenge.chunkId > 0 + ? chunks[challenge.chunkId - 1n] + : 'invalid chunk data'; + const { proof: correctProof } = kcTools.calculateMerkleProof( + quads, + 32, + challenge.chunkId, + ); + const wrongProof: string[] = []; + + // Try submitting correct proof with wrong chunk + const submitWrongChunkTx = RandomSampling.connect( + publishingNode.operational, + ).submitProof(wrongChunk, correctProof); + await expect(submitWrongChunkTx).to.be.revertedWithCustomError( + RandomSampling, + 'MerkleRootMismatchError', + ); + let finalChallenge = await RandomSamplingStorage.getNodeChallenge( + publishingNodeIdentityId, + ); + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + expect(finalChallenge.solved).to.be.false; // Ensure state unchanged + + // Try submitting correct chunk with wrong proof + const submitWrongProofTx = RandomSampling.connect( + publishingNode.operational, + ).submitProof(correctChunk, wrongProof); + await expect(submitWrongProofTx).to.be.revertedWithCustomError( + RandomSampling, + 'MerkleRootMismatchError', + ); + finalChallenge = await RandomSamplingStorage.getNodeChallenge( + publishingNodeIdentityId, + ); + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + expect(finalChallenge.solved).to.be.false; // Ensure state unchanged + }); + + it('Should submit a valid proof and successfully update challenge state (solved=true)', async () => { + const kcCreator = getDefaultKCCreator(accounts); + const minStake = await ParametersStorage.minimumStake(); + const nodeAsk = 200000000000000000n; // Same as 0.2 ETH + const deps = { + accounts, + Profile, + Token, + Staking, + Ask, + KnowledgeCollection, + }; + + const { node: publishingNode, identityId: publishingNodeIdentityId } = + await setupNodeWithStakeAndAsk(1, minStake, nodeAsk, deps); + + const receivingNodes = []; + const receivingNodesIdentityIds = []; + for (let i = 0; i < 5; i++) { + const { node, identityId } = await setupNodeWithStakeAndAsk( + i + 10, + minStake, + nodeAsk, + deps, + ); + receivingNodes.push(node); + receivingNodesIdentityIds.push(identityId); + } + + await createKnowledgeCollection( + kcCreator, + publishingNode, + publishingNodeIdentityId, + receivingNodes, + receivingNodesIdentityIds, + deps, + merkleRoot, + ); + + // Update and get the new active proof period + await RandomSampling.updateAndGetActiveProofPeriodStartBlock(); + + // Create challenge + const challengeTx = await RandomSampling.connect( + publishingNode.operational, + ).createChallenge(); + await challengeTx.wait(); + + // Get the challenge from storage to verify it + let challenge = await RandomSamplingStorage.getNodeChallenge( + publishingNodeIdentityId, + ); + + // Get chunk from quads + const chunks = kcTools.splitIntoChunks(quads, 32); + const challengeChunk = chunks[challenge.chunkId]; + + // Generate a proof for our challenge chunk + const { proof } = kcTools.calculateMerkleProof( + quads, + 32, + Number(challenge.chunkId), + ); + + // Submit proof + await RandomSampling.connect(publishingNode.operational).submitProof( + challengeChunk, + proof, + ); + + // Get the challenge from storage to verify it + challenge = await RandomSamplingStorage.getNodeChallenge( + publishingNodeIdentityId, + ); + + // Since the challenge was solved, the challenge should be marked as solved + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + expect(challenge.solved).to.be.true; + }); + + it('Should submit a valid proof and successfully increment epochNodeValidProofsCount', async () => { + const kcCreator = getDefaultKCCreator(accounts); + const minStake = await ParametersStorage.minimumStake(); + const nodeAsk = 200000000000000000n; // Same as 0.2 ETH + const deps = { + accounts, + Profile, + Token, + Staking, + Ask, + KnowledgeCollection, + }; + + const { node: publishingNode, identityId: publishingNodeIdentityId } = + await setupNodeWithStakeAndAsk(1, minStake, nodeAsk, deps); + + const receivingNodes = []; + const receivingNodesIdentityIds = []; + for (let i = 0; i < 5; i++) { + const { node, identityId } = await setupNodeWithStakeAndAsk( + i + 10, + minStake, + nodeAsk, + deps, + ); + receivingNodes.push(node); + receivingNodesIdentityIds.push(identityId); + } + + await createKnowledgeCollection( + kcCreator, + publishingNode, + publishingNodeIdentityId, + receivingNodes, + receivingNodesIdentityIds, + deps, + merkleRoot, + ); + + // Update and get the new active proof period + await RandomSampling.updateAndGetActiveProofPeriodStartBlock(); + + // Create challenge + await RandomSampling.connect( + publishingNode.operational, + ).createChallenge(); + + // Get the challenge from storage to verify it + let challenge = await RandomSamplingStorage.getNodeChallenge( + publishingNodeIdentityId, + ); + + // Get chunk from quads + const chunks = kcTools.splitIntoChunks(quads, 32); + const challengeChunk = chunks[challenge.chunkId]; + + // Generate a proof for our challenge chunk + const { proof } = kcTools.calculateMerkleProof( + quads, + 32, + Number(challenge.chunkId), + ); + + // Submit proof + await RandomSampling.connect(publishingNode.operational).submitProof( + challengeChunk, + proof, + ); + + // Get the challenge from storage to verify it + challenge = await RandomSamplingStorage.getNodeChallenge( + publishingNodeIdentityId, + ); + + // Verify that epochNodeValidProofsCount was incremented + const epochNodeValidProofsCount = + await RandomSamplingStorage.getEpochNodeValidProofsCount( + challenge.epoch, + publishingNodeIdentityId, + ); + expect(epochNodeValidProofsCount).to.equal(1n); + }); + + it('Should submit a valid proof and successfully emit NodeEpochScoreAdded event with correct parameters', async () => { + const kcCreator = getDefaultKCCreator(accounts); + const minStake = await ParametersStorage.minimumStake(); + const nodeAsk = 200000000000000000n; // Same as 0.2 ETH + const deps = { + accounts, + Profile, + Token, + Staking, + Ask, + KnowledgeCollection, + }; + + const { node: publishingNode, identityId: publishingNodeIdentityId } = + await setupNodeWithStakeAndAsk(1, minStake, nodeAsk, deps); + + const receivingNodes = []; + const receivingNodesIdentityIds = []; + for (let i = 0; i < 5; i++) { + const { node, identityId } = await setupNodeWithStakeAndAsk( + i + 10, + minStake, + nodeAsk, + deps, + ); + receivingNodes.push(node); + receivingNodesIdentityIds.push(identityId); + } + + await createKnowledgeCollection( + kcCreator, + publishingNode, + publishingNodeIdentityId, + receivingNodes, + receivingNodesIdentityIds, + deps, + merkleRoot, + ); + + // Update and get the new active proof period + await RandomSampling.updateAndGetActiveProofPeriodStartBlock(); + + // Create challenge + await RandomSampling.connect( + publishingNode.operational, + ).createChallenge(); + + // Get the challenge from storage to verify it + let challenge = await RandomSamplingStorage.getNodeChallenge( + publishingNodeIdentityId, + ); + + // Get chunk from quads + const chunks = kcTools.splitIntoChunks(quads, 32); + const challengeChunk = chunks[challenge.chunkId]; + + // Generate a proof for our challenge chunk + const { proof } = kcTools.calculateMerkleProof( + quads, + 32, + Number(challenge.chunkId), + ); + + // Submit proof + const receipt = await RandomSampling.connect( + publishingNode.operational, + ).submitProof(challengeChunk, proof); + + // Get the challenge from storage to verify it + challenge = await RandomSamplingStorage.getNodeChallenge( + publishingNodeIdentityId, + ); + + const expectedScore = await calculateExpectedNodeScore( + BigInt(publishingNodeIdentityId), + BigInt(minStake), + { + ParametersStorage, + ProfileStorage, + AskStorage, + EpochStorage, + }, + ); + + // Verify that epochNodeValidProofsCount was incremented + await expect(receipt) + .to.emit(RandomSamplingStorage, 'NodeEpochScoreAdded') + .withArgs( + challenge.epoch, + publishingNodeIdentityId, + (score: bigint) => score.toString() === expectedScore.toString(), + (totalScore: bigint) => + totalScore.toString() === expectedScore.toString(), + ); + }); + + it('Should submit a valid proof and successfully and add score to nodeEpochProofPeriodScore', async () => { + const kcCreator = getDefaultKCCreator(accounts); + const minStake = await ParametersStorage.minimumStake(); + const nodeAsk = 200000000000000000n; // Same as 0.2 ETH + const deps = { + accounts, + Profile, + Token, + Staking, + Ask, + KnowledgeCollection, + }; + + const { node: publishingNode, identityId: publishingNodeIdentityId } = + await setupNodeWithStakeAndAsk(1, minStake, nodeAsk, deps); + + const receivingNodes = []; + const receivingNodesIdentityIds = []; + for (let i = 0; i < 5; i++) { + const { node, identityId } = await setupNodeWithStakeAndAsk( + i + 10, + minStake, + nodeAsk, + deps, + ); + receivingNodes.push(node); + receivingNodesIdentityIds.push(identityId); + } + + await createKnowledgeCollection( + kcCreator, + publishingNode, + publishingNodeIdentityId, + receivingNodes, + receivingNodesIdentityIds, + deps, + merkleRoot, + ); + + // Update and get the new active proof period + await RandomSampling.updateAndGetActiveProofPeriodStartBlock(); + + // Create challenge + await RandomSampling.connect( + publishingNode.operational, + ).createChallenge(); + + // Get the challenge from storage to verify it + let challenge = await RandomSamplingStorage.getNodeChallenge( + publishingNodeIdentityId, + ); + + // Get chunk from quads + const chunks = kcTools.splitIntoChunks(quads, 32); + const challengeChunk = chunks[challenge.chunkId]; + + // Generate a proof for our challenge chunk + const { proof } = kcTools.calculateMerkleProof( + quads, + 32, + Number(challenge.chunkId), + ); + + // Submit proof + await RandomSampling.connect(publishingNode.operational).submitProof( + challengeChunk, + proof, + ); + + // Get the challenge from storage to verify it + challenge = await RandomSamplingStorage.getNodeChallenge( + publishingNodeIdentityId, + ); + + const expectedScore = await calculateExpectedNodeScore( + BigInt(publishingNodeIdentityId), + BigInt(minStake), + { + ParametersStorage, + ProfileStorage, + AskStorage, + EpochStorage, + }, + ); + + expect( + await RandomSamplingStorage.getNodeEpochProofPeriodScore( + publishingNodeIdentityId, + challenge.epoch, + challenge.activeProofPeriodStartBlock, + ), + ).to.equal(expectedScore); + }); + + it('Should succeed if submitting proof exactly on the last block of the period', async () => { + // Setup + const kcCreator = getDefaultKCCreator(accounts); + const minStake = await ParametersStorage.minimumStake(); + const nodeAsk = 200000000000000000n; // 0.2 ETH + const deps = { + accounts, + Profile, + Token, + Staking, + Ask, + KnowledgeCollection, + }; + + const { node: publishingNode, identityId: publishingNodeIdentityId } = + await setupNodeWithStakeAndAsk(1, minStake, nodeAsk, deps); + + const receivingNodes = []; + const receivingNodesIdentityIds = []; + for (let i = 0; i < 5; i++) { + const { node, identityId } = await setupNodeWithStakeAndAsk( + i + 10, + minStake, + nodeAsk, + deps, + ); + receivingNodes.push(node); + receivingNodesIdentityIds.push(identityId); + } + + await createKnowledgeCollection( + kcCreator, + publishingNode, + publishingNodeIdentityId, + receivingNodes, + receivingNodesIdentityIds, + deps, + merkleRoot, + ); + + // Create challenge + await RandomSampling.connect( + publishingNode.operational, + ).createChallenge(); + const challenge = await RandomSamplingStorage.getNodeChallenge( + publishingNodeIdentityId, + ); + const startBlock = challenge.activeProofPeriodStartBlock; + const duration = challenge.proofingPeriodDurationInBlocks; + const targetBlock = startBlock + duration - 2n; + const currentBlock = BigInt(await hre.ethers.provider.getBlockNumber()); + + // Advance blocks to exactly S + D - 1 + if (targetBlock > currentBlock) { + const blocksToMine = Number(targetBlock - currentBlock); + for (let i = 0; i < blocksToMine; i++) { + await hre.network.provider.send('evm_mine'); + } + } + + expect(BigInt(await hre.ethers.provider.getBlockNumber())).to.equal( + targetBlock, + ); + + // Action: Prepare and submit proof + const chunks = kcTools.splitIntoChunks(quads, 32); + const challengeChunk = chunks[challenge.chunkId]; + const { proof } = kcTools.calculateMerkleProof( + quads, + 32, + Number(challenge.chunkId), + ); + + const submitTx = RandomSampling.connect( + publishingNode.operational, + ).submitProof(challengeChunk, proof); + + // Verification + await expect(submitTx).to.not.be.reverted; + + const updatedChallenge = await RandomSamplingStorage.getNodeChallenge( + publishingNodeIdentityId, + ); + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + expect(updatedChallenge.solved).to.be.true; + + const expectedScore = await calculateExpectedNodeScore( + BigInt(publishingNodeIdentityId), + BigInt(minStake), + { + ParametersStorage, + ProfileStorage, + AskStorage, + EpochStorage, + }, + ); + expect( + await RandomSamplingStorage.getNodeEpochProofPeriodScore( + publishingNodeIdentityId, + challenge.epoch, + startBlock, + ), + ).to.equal(expectedScore); + + await expect(submitTx) + .to.emit(RandomSamplingStorage, 'NodeEpochScoreAdded') + .withArgs( + challenge.epoch, + publishingNodeIdentityId, + (score: bigint) => score.toString() === expectedScore.toString(), + (totalScore: bigint) => + totalScore.toString() === expectedScore.toString(), + ); + }); + + it('Should revert if submitting proof exactly on the first block of the next period', async () => { + // Setup + const kcCreator = getDefaultKCCreator(accounts); + const minStake = await ParametersStorage.minimumStake(); + const nodeAsk = 200000000000000000n; // 0.2 ETH + const deps = { + accounts, + Profile, + Token, + Staking, + Ask, + KnowledgeCollection, + }; + + const { node: publishingNode, identityId: publishingNodeIdentityId } = + await setupNodeWithStakeAndAsk(1, minStake, nodeAsk, deps); + + const receivingNodes = []; + const receivingNodesIdentityIds = []; + for (let i = 0; i < 5; i++) { + const { node, identityId } = await setupNodeWithStakeAndAsk( + i + 10, + minStake, + nodeAsk, + deps, + ); + receivingNodes.push(node); + receivingNodesIdentityIds.push(identityId); + } + + await createKnowledgeCollection( + kcCreator, + publishingNode, + publishingNodeIdentityId, + receivingNodes, + receivingNodesIdentityIds, + deps, + merkleRoot, + ); + + // Create challenge + await RandomSampling.connect( + publishingNode.operational, + ).createChallenge(); + const challenge = await RandomSamplingStorage.getNodeChallenge( + publishingNodeIdentityId, + ); + const startBlock = challenge.activeProofPeriodStartBlock; + const duration = challenge.proofingPeriodDurationInBlocks; + const targetBlock = startBlock + duration - 1n; + const currentBlock = BigInt(await hre.ethers.provider.getBlockNumber()); + + // Advance blocks to exactly S + D + if (targetBlock > currentBlock) { + const blocksToMine = Number(targetBlock - currentBlock); + for (let i = 0; i < blocksToMine; i++) { + await hre.network.provider.send('evm_mine'); + } + } + expect(BigInt(await hre.ethers.provider.getBlockNumber())).to.equal( + targetBlock, + ); + + // Action: Prepare and submit proof for the previous period + const chunks = kcTools.splitIntoChunks(quads, 32); + const challengeChunk = chunks[challenge.chunkId]; + const { proof } = kcTools.calculateMerkleProof( + quads, + 32, + Number(challenge.chunkId), + ); + + const submitTx = RandomSampling.connect( + publishingNode.operational, + ).submitProof(challengeChunk, proof); + + // Verification + await expect(submitTx).to.be.revertedWith( + 'This challenge is no longer active', + ); + }); + + it('Should revert if proof for the same challenge is submitted twice', async () => { + const kcCreator = getDefaultKCCreator(accounts); + const minStake = await ParametersStorage.minimumStake(); + const nodeAsk = 200000000000000000n; // Same as 0.2 ETH + const deps = { + accounts, + Profile, + Token, + Staking, + Ask, + KnowledgeCollection, + }; + + const { node: publishingNode, identityId: publishingNodeIdentityId } = + await setupNodeWithStakeAndAsk(1, minStake, nodeAsk, deps); + + const receivingNodes = []; + const receivingNodesIdentityIds = []; + for (let i = 0; i < 5; i++) { + const { node, identityId } = await setupNodeWithStakeAndAsk( + i + 10, + minStake, + nodeAsk, + deps, + ); + receivingNodes.push(node); + receivingNodesIdentityIds.push(identityId); + } + + await createKnowledgeCollection( + kcCreator, + publishingNode, + publishingNodeIdentityId, + receivingNodes, + receivingNodesIdentityIds, + deps, + merkleRoot, + ); + + // Update and get the new active proof period + await RandomSampling.updateAndGetActiveProofPeriodStartBlock(); + + // Create challenge + await RandomSampling.connect( + publishingNode.operational, + ).createChallenge(); + + // Get the challenge from storage to verify it + const challenge = await RandomSamplingStorage.getNodeChallenge( + publishingNodeIdentityId, + ); + + // Get chunk from quads + const chunks = kcTools.splitIntoChunks(quads, 32); + const challengeChunk = chunks[challenge.chunkId]; + + // Generate a proof for our challenge chunk + const { proof } = kcTools.calculateMerkleProof( + quads, + 32, + Number(challenge.chunkId), + ); + + // Submit proof + await RandomSampling.connect(publishingNode.operational).submitProof( + challengeChunk, + proof, + ); + + // Submit proof again + const submitTx = RandomSampling.connect( + publishingNode.operational, + ).submitProof(challengeChunk, proof); + + // Expect revert + await expect(submitTx).to.be.revertedWith( + 'This challenge has already been solved', + ); + }); + }); + + describe('Optimized Knowledge Collection Search', () => { + let publishingNode: { + operational: SignerWithAddress; + admin: SignerWithAddress; + }; + let publishingNodeIdentityId: number; + let receivingNodes: { + operational: SignerWithAddress; + admin: SignerWithAddress; + }[]; + let receivingNodesIdentityIds: number[]; + let kcCreator: SignerWithAddress; + let deps: { + accounts: SignerWithAddress[]; + Profile: Profile; + Token: Token; + Staking: Staking; + Ask: Ask; + KnowledgeCollection: KnowledgeCollection; + }; + + beforeEach(async () => { + // Setup nodes + kcCreator = getDefaultKCCreator(accounts); + const minStake = await ParametersStorage.minimumStake(); + const nodeAsk = 200000000000000000n; // 0.2 ETH + + deps = { + accounts, + Profile, + Token, + Staking, + Ask, + KnowledgeCollection, + }; + + ({ node: publishingNode, identityId: publishingNodeIdentityId } = + await setupNodeWithStakeAndAsk(1, minStake, nodeAsk, deps)); + + receivingNodes = []; + receivingNodesIdentityIds = []; + for (let i = 0; i < 5; i++) { + const { node, identityId } = await setupNodeWithStakeAndAsk( + i + 10, + minStake, + nodeAsk, + deps, + ); + receivingNodes.push(node); + receivingNodesIdentityIds.push(identityId); + } + }); + + it('Should find active knowledge collections when mix of active and expired collections exist', async () => { + const initialEpoch = await Chronos.getCurrentEpoch(); + + // Create 20 knowledge collections with different expiration epochs + const collections = []; + + // Create 15 collections that expire in epoch 1 (will be expired) + for (let i = 0; i < 15; i++) { + await createKnowledgeCollection( + kcCreator, + publishingNode, + publishingNodeIdentityId, + receivingNodes, + receivingNodesIdentityIds, + deps, + merkleRoot, + `expired-operation-${i}`, + 10, + 1000, + 1, // epochsDuration = 1, so expires after current epoch + duration + 1 + ); + collections.push({ id: i + 1, active: false }); + } + + // Create 5 collections that expire in epoch 10 (will be active) + for (let i = 15; i < 20; i++) { + await createKnowledgeCollection( + kcCreator, + publishingNode, + publishingNodeIdentityId, + receivingNodes, + receivingNodesIdentityIds, + deps, + merkleRoot, + `active-operation-${i}`, + 10, + 1000, + 10, // epochsDuration = 10, so expires after current epoch + duration + 1 + ); + collections.push({ id: i + 1, active: true }); + } + + // Advance to epoch 5 (so first 15 collections are expired, last 5 are active) + for (let epoch = Number(initialEpoch); epoch < 5; epoch++) { + const timeUntilNextEpoch = await Chronos.timeUntilNextEpoch(); + await time.increase(Number(timeUntilNextEpoch) + 5); + } + + const currentEpoch = await Chronos.getCurrentEpoch(); + expect(currentEpoch).to.be.gte(5n, 'Should be in epoch 5 or later'); + + // Verify which collections are active/expired + for (const collection of collections) { + const endEpoch = await KnowledgeCollectionStorage.getEndEpoch( + collection.id, + ); + const isActive = currentEpoch <= endEpoch; + if (collection.active) { + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + expect(isActive).to.be.true; + } else { + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + expect(isActive).to.be.false; + } + } + + // Create challenge multiple times to verify it finds active collections + const foundCollections = new Set(); + const maxAttempts = 20; // Try multiple times to test randomness and consistency + + for (let attempt = 0; attempt < maxAttempts; attempt++) { + // Move to next proof period to allow new challenge + const duration = + await RandomSampling.getActiveProofingPeriodDurationInBlocks(); + for (let i = 0; i < Number(duration); i++) { + await hre.network.provider.send('evm_mine'); + } + + await RandomSampling.connect( + publishingNode.operational, + ).createChallenge(); + const challenge = await RandomSamplingStorage.getNodeChallenge( + publishingNodeIdentityId, + ); + + // Verify the found collection is one of the active ones + expect([16, 17, 18, 19, 20]).to.include( + Number(challenge.knowledgeCollectionId), + ); + foundCollections.add(Number(challenge.knowledgeCollectionId)); + + // Mark challenge as solved to allow next challenge + const solvedChallenge = { + knowledgeCollectionId: challenge.knowledgeCollectionId, + chunkId: challenge.chunkId, + knowledgeCollectionStorageContract: + challenge.knowledgeCollectionStorageContract, + epoch: challenge.epoch, + activeProofPeriodStartBlock: challenge.activeProofPeriodStartBlock, + proofingPeriodDurationInBlocks: + challenge.proofingPeriodDurationInBlocks, + solved: true, + }; + await RandomSamplingStorage.setNodeChallenge( + publishingNodeIdentityId, + solvedChallenge, + ); + } + + // Verify that the algorithm found at least 2 different active collections (shows it's working properly) + expect(foundCollections.size).to.be.gte( + 2, + 'Should find multiple different active collections', + ); + }); + + it('Should revert when all knowledge collections are expired', async () => { + // Create 3 knowledge collections that expire in epoch 1 + for (let i = 0; i < 3; i++) { + await createKnowledgeCollection( + kcCreator, + publishingNode, + publishingNodeIdentityId, + receivingNodes, + receivingNodesIdentityIds, + deps, + merkleRoot, + `expired-operation-${i}`, + 10, + 1000, + 1, // epochsDuration = 1, expires after epoch 1 + ); + } + + // Advance to epoch 5 (all collections expired) + for (let epoch = 1; epoch < 5; epoch++) { + const timeUntilNextEpoch = await Chronos.timeUntilNextEpoch(); + await time.increase(Number(timeUntilNextEpoch) + 5); + } + + // Verify all collections are expired + const currentEpoch = await Chronos.getCurrentEpoch(); + for (let kcId = 1; kcId <= 3; kcId++) { + const endEpoch = await KnowledgeCollectionStorage.getEndEpoch(kcId); + expect(currentEpoch).to.be.gt(endEpoch, `KC ${kcId} should be expired`); + } + + // Attempt to create challenge should revert + await expect( + RandomSampling.connect(publishingNode.operational).createChallenge(), + ).to.be.revertedWith( + 'Failed to find a knowledge collection that is active in the current epoch', + ); + }); + + it('Should work efficiently with single active collection among many expired ones', async () => { + // Create 9 expired collections + for (let i = 0; i < 9; i++) { + await createKnowledgeCollection( + kcCreator, + publishingNode, + publishingNodeIdentityId, + receivingNodes, + receivingNodesIdentityIds, + deps, + merkleRoot, + `expired-operation-${i}`, + 10, + 1000, + 1, // epochsDuration = 1, expires after epoch 1 + ); + } + + // Create 1 active collection (will be KC #10) + await createKnowledgeCollection( + kcCreator, + publishingNode, + publishingNodeIdentityId, + receivingNodes, + receivingNodesIdentityIds, + deps, + merkleRoot, + 'active-operation', + 10, + 1000, + 10, // epochsDuration = 10, active for longer + ); + + // Advance to epoch 4 (first 9 expired, last 1 active) + for (let epoch = 1; epoch < 4; epoch++) { + const timeUntilNextEpoch = await Chronos.timeUntilNextEpoch(); + await time.increase(Number(timeUntilNextEpoch) + 5); + } + + // Verify only the last collection is active + const currentEpoch = await Chronos.getCurrentEpoch(); + for (let kcId = 1; kcId <= 9; kcId++) { + const endEpoch = await KnowledgeCollectionStorage.getEndEpoch(kcId); + expect(currentEpoch).to.be.gt(endEpoch, `KC ${kcId} should be expired`); + } + + const activeKcEndEpoch = await KnowledgeCollectionStorage.getEndEpoch(10); + expect(currentEpoch).to.be.lte( + activeKcEndEpoch, + 'KC 10 should be active', + ); + + // Create challenge should find the active collection + await RandomSampling.connect( + publishingNode.operational, + ).createChallenge(); + const challenge = await RandomSamplingStorage.getNodeChallenge( + publishingNodeIdentityId, + ); + + expect(challenge.knowledgeCollectionId).to.equal( + 10n, + 'Should find the only active collection', + ); + }); + + it('Should demonstrate randomness by finding different collections over multiple attempts', async () => { + // Create 5 active knowledge collections + for (let i = 0; i < 5; i++) { + await createKnowledgeCollection( + kcCreator, + publishingNode, + publishingNodeIdentityId, + receivingNodes, + receivingNodesIdentityIds, + deps, + merkleRoot, + `active-operation-${i}`, + 10, + 1000, + 10, // All active for 10 epochs + ); + } + + const foundCollections = new Set(); + const maxAttempts = 15; + + for (let attempt = 0; attempt < maxAttempts; attempt++) { + // Move to next proof period + const duration = + await RandomSampling.getActiveProofingPeriodDurationInBlocks(); + for (let i = 0; i < Number(duration); i++) { + await hre.network.provider.send('evm_mine'); + } + + await RandomSampling.connect( + publishingNode.operational, + ).createChallenge(); + const challenge = await RandomSamplingStorage.getNodeChallenge( + publishingNodeIdentityId, + ); + + // All collections should be active + expect(challenge.knowledgeCollectionId).to.be.gte(1n); + expect(challenge.knowledgeCollectionId).to.be.lte(5n); + foundCollections.add(Number(challenge.knowledgeCollectionId)); + + // Mark as solved for next iteration + const solvedChallenge = { + knowledgeCollectionId: challenge.knowledgeCollectionId, + chunkId: challenge.chunkId, + knowledgeCollectionStorageContract: + challenge.knowledgeCollectionStorageContract, + epoch: challenge.epoch, + activeProofPeriodStartBlock: challenge.activeProofPeriodStartBlock, + proofingPeriodDurationInBlocks: + challenge.proofingPeriodDurationInBlocks, + solved: true, + }; + await RandomSamplingStorage.setNodeChallenge( + publishingNodeIdentityId, + solvedChallenge, + ); + } + + // Should find at least 3 different collections (demonstrates randomness) + expect(foundCollections.size).to.be.gte( + 3, + `Should find multiple collections for randomness. Found: ${Array.from(foundCollections)}`, + ); + }); + + it('Should handle edge case with collections at different positions in the range', async () => { + // Create specific pattern: active-expired-active-expired-active + const patterns = [ + { active: true, duration: 10 }, // KC 1: active + { active: false, duration: 1 }, // KC 2: expired + { active: true, duration: 10 }, // KC 3: active + { active: false, duration: 1 }, // KC 4: expired + { active: true, duration: 10 }, // KC 5: active + ]; + + for (let i = 0; i < patterns.length; i++) { + await createKnowledgeCollection( + kcCreator, + publishingNode, + publishingNodeIdentityId, + receivingNodes, + receivingNodesIdentityIds, + deps, + merkleRoot, + `pattern-operation-${i}`, + 10, + 1000, + patterns[i].duration, + ); + } + + // Advance to epoch 4 (expired ones are expired, active ones are active) + for (let epoch = 1; epoch < 4; epoch++) { + const timeUntilNextEpoch = await Chronos.timeUntilNextEpoch(); + await time.increase(Number(timeUntilNextEpoch) + 5); + } + + // Test multiple challenges to ensure it finds active collections (1, 3, 5) + const foundCollections = new Set(); + + for (let attempt = 0; attempt < 10; attempt++) { + const duration = + await RandomSampling.getActiveProofingPeriodDurationInBlocks(); + for (let i = 0; i < Number(duration); i++) { + await hre.network.provider.send('evm_mine'); + } + + await RandomSampling.connect( + publishingNode.operational, + ).createChallenge(); + const challenge = await RandomSamplingStorage.getNodeChallenge( + publishingNodeIdentityId, + ); + + foundCollections.add(Number(challenge.knowledgeCollectionId)); + + // Should only find active collections (1, 3, 5) + expect([1, 3, 5]).to.include(Number(challenge.knowledgeCollectionId)); + + // Mark as solved for next iteration + const solvedChallenge = { + knowledgeCollectionId: challenge.knowledgeCollectionId, + chunkId: challenge.chunkId, + knowledgeCollectionStorageContract: + challenge.knowledgeCollectionStorageContract, + epoch: challenge.epoch, + activeProofPeriodStartBlock: challenge.activeProofPeriodStartBlock, + proofingPeriodDurationInBlocks: + challenge.proofingPeriodDurationInBlocks, + solved: true, + }; + await RandomSamplingStorage.setNodeChallenge( + publishingNodeIdentityId, + solvedChallenge, + ); + } + + // Should find multiple active collections from the pattern + expect(foundCollections.size).to.be.gte( + 2, + 'Should find multiple active collections from the alternating pattern', + ); + + // Verify it never found expired collections (2, 4) + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + expect(foundCollections.has(2)).to.be.false; + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + expect(foundCollections.has(4)).to.be.false; + }); + }); + + describe('Node scoring', () => { + let nodeIdCounter = 100; // Start from high index to avoid conflicts with other tests + + beforeEach(async () => { + // Create a basic knowledge collection to initialize epoch publishing data + // Use unique account indices for setup to avoid conflicts + const kcCreator = accounts[70]; // Use high index account + const setupNode = { + admin: accounts[71], + operational: accounts[72], + }; + + const { identityId: setupNodeId } = await createProfile( + Profile, + setupNode, + ); + + // Set minimum stake and ask for the setup node + const minStake = await ParametersStorage.minimumStake(); + await setNodeStake(setupNode, BigInt(setupNodeId), minStake, { + Token, + Staking, + Ask, + }); + await Profile.connect(setupNode.operational).updateAsk(setupNodeId, 100n); + await Ask.recalculateActiveSet(); + + // Create receiving nodes with unique indices + const receivingNodes = Array.from({ length: 3 }, (_, i) => ({ + admin: accounts[73 + i * 2], + operational: accounts[74 + i * 2], + })); + + const receivingNodesIdentityIds = ( + await createProfiles(Profile, receivingNodes) + ).map((p) => p.identityId); + + const deps = { + accounts, + Profile, + Token, + Staking, + Ask, + KnowledgeCollection, + }; + + // Create a knowledge collection to initialize publishing data + await createKnowledgeCollection( + kcCreator, + setupNode, + setupNodeId, + receivingNodes, + receivingNodesIdentityIds, + deps, + merkleRoot, + ); + + // Reset node counter for each test + nodeIdCounter = 100; + }); + + it('Should return score of 0 for zero stake node', async () => { + // Setup: Create a node with zero stake using unique accounts + const publishingNode = { + admin: accounts[nodeIdCounter++], + operational: accounts[nodeIdCounter++], + }; + const { identityId: publishingNodeIdentityId } = await createProfile( + Profile, + publishingNode, + ); + + // Set ask to valid value within bounds + await Profile.connect(publishingNode.operational).updateAsk( + publishingNodeIdentityId, + 100n, + ); + await Ask.recalculateActiveSet(); + + // Verify zero stake + const nodeStake = await StakingStorage.getNodeStake( + publishingNodeIdentityId, + ); + expect(nodeStake).to.equal(0n); + + // Calculate score - should handle zero stake gracefully + const score = await RandomSampling.calculateNodeScore( + publishingNodeIdentityId, + ); + + // Should be zero because stake factor is zero + expect(score).to.equal(0n); + }); + + it('Should cap stake at maximumStake and calculate score correctly', async () => { + // Setup: Create a node with exactly maximum stake + const maximumStake = await ParametersStorage.maximumStake(); + const askLowerBoundBefore = await AskStorage.getAskLowerBound(); + const nodeAsk = askLowerBoundBefore / SCALING_FACTOR + 10n; // Slightly above lower bound + const deps = { + accounts, + Profile, + Token, + Staking, + Ask, + KnowledgeCollection, + }; + + const { identityId: publishingNodeIdentityId } = + await setupNodeWithStakeAndAsk( + nodeIdCounter, + maximumStake, + nodeAsk, + deps, + ); + nodeIdCounter += 2; // Account for both admin and operational accounts + + // Set stake to 2x maximum stake to test capping + await StakingStorage.setNodeStake( + publishingNodeIdentityId, + maximumStake * 2n, + ); + + expect( + await StakingStorage.getNodeStake(publishingNodeIdentityId), + ).to.equal(maximumStake * 2n); + + // Calculate expected score using helper function + const expectedScore = await calculateExpectedNodeScore( + BigInt(publishingNodeIdentityId), + maximumStake * 2n, + { + ParametersStorage, + ProfileStorage, + AskStorage, + EpochStorage, + }, + ); + + // Calculate actual score from contract + const actualScore = await RandomSampling.calculateNodeScore( + publishingNodeIdentityId, + ); + + expect(actualScore).to.equal(expectedScore); + }); + + it('Should handle stake calculation correctly when node has maximum stake', async () => { + // Setup: Create a node with exactly maximum stake and verify internal capping + const maximumStake = await ParametersStorage.maximumStake(); + const askLowerBoundBefore = await AskStorage.getAskLowerBound(); + const nodeAsk = askLowerBoundBefore / SCALING_FACTOR + 10n; // Slightly above lower bound + const deps = { + accounts, + Profile, + Token, + Staking, + Ask, + KnowledgeCollection, + }; + + const { identityId: publishingNodeIdentityId } = + await setupNodeWithStakeAndAsk( + nodeIdCounter, + maximumStake, + nodeAsk, + deps, + ); + nodeIdCounter += 2; // Account for both admin and operational accounts + + // Verify stake is exactly at maximum + const actualNodeStake = await StakingStorage.getNodeStake( + publishingNodeIdentityId, + ); + expect(actualNodeStake).to.equal(maximumStake); + + // Calculate actual score from contract + const actualScore = await RandomSampling.calculateNodeScore( + publishingNodeIdentityId, + ); + + const expectedScore = await calculateExpectedNodeScore( + BigInt(publishingNodeIdentityId), + maximumStake, + { + ParametersStorage, + ProfileStorage, + AskStorage, + EpochStorage, + }, + ); + + expect(actualScore).to.equal(expectedScore); + }); + + it('Should calculate correct score for minimum viable stake', async () => { + // Setup: Create a node with minimum stake + 1 + const minimumStake = await ParametersStorage.minimumStake(); + const minViableStake = minimumStake + 1n; + const askLowerBoundBefore = await AskStorage.getAskLowerBound(); + const nodeAsk = askLowerBoundBefore / SCALING_FACTOR + 10n; // Slightly above lower bound + const deps = { + accounts, + Profile, + Token, + Staking, + Ask, + KnowledgeCollection, + }; + + const { identityId: publishingNodeIdentityId } = + await setupNodeWithStakeAndAsk( + nodeIdCounter, + minViableStake, + nodeAsk, + deps, + ); + nodeIdCounter += 2; // Account for both admin and operational accounts + + // Calculate expected score + const expectedScore = await calculateExpectedNodeScore( + BigInt(publishingNodeIdentityId), + minViableStake, + { + ParametersStorage, + ProfileStorage, + AskStorage, + EpochStorage, + }, + ); + + // Calculate actual score from contract + const actualScore = await RandomSampling.calculateNodeScore( + publishingNodeIdentityId, + ); + + expect(actualScore).to.equal(expectedScore); + }); + + it('Should handle precision loss testing and maintain accuracy', async () => { + // Setup: Use stakes that might cause precision issues + const minimumStake = await ParametersStorage.minimumStake(); + const maximumStake = await ParametersStorage.maximumStake(); + + const deps = { + accounts, + Profile, + Token, + Staking, + Ask, + KnowledgeCollection, + }; + + const stake = minimumStake * 10n; + + // Get ask bounds to set a valid ask price + const askLowerBoundBefore = await AskStorage.getAskLowerBound(); + const nodeAsk = askLowerBoundBefore / SCALING_FACTOR + 10n; // Slightly above lower bound + + const { identityId: publishingNodeIdentityId } = + await setupNodeWithStakeAndAsk(nodeIdCounter, stake, nodeAsk, deps); + nodeIdCounter += 2; // Account for both admin and operational accounts + + const [askLowerBound, askUpperBound] = await AskStorage.getAskBounds(); + + // Calculate actual score from contract + const actualScore = await RandomSampling.calculateNodeScore( + publishingNodeIdentityId, + ); + + // Calculate expected score using the proper contract formula + const cappedStake = stake > maximumStake ? maximumStake : stake; + + // Stake factor: 2 * (stake / maxStake)^2 + const stakeRatio = Number(cappedStake) / Number(maximumStake); + const expectedStakeFactor = 2 * stakeRatio ** 2; + + // Ask factor: (stakeRatio) * ((upperBound - nodeAsk) / (upperBound - lowerBound))^2 + const nodeAskScaled = Number(nodeAsk) * Number(SCALING_FACTOR); + let expectedAskFactor = 0; + if ( + nodeAskScaled >= Number(askLowerBound) && + nodeAskScaled <= Number(askUpperBound) + ) { + const askDiffRatio = + (Number(askUpperBound) - nodeAskScaled) / + (Number(askUpperBound) - Number(askLowerBound)); + expectedAskFactor = stakeRatio * askDiffRatio ** 2; + } + + // Publishing factor is 0 for this test (no knowledge collections) + const expectedPublishingFactor = 0; + const expectedTotal = + expectedStakeFactor + expectedAskFactor + expectedPublishingFactor; + + // The precision difference should be very small which indicates that your calculation logic is essentially correct - it's just hitting the limits of floating-point precision in JavaScript. + expect(Number(actualScore) / Number(SCALING_FACTOR)).to.be.closeTo( + expectedTotal, + 1e-15, + ); + }); + + it('Should calculate accurate score for node with stake and ask', async () => { + // Setup: Create a realistic node scenario + const nodeStake = (await ParametersStorage.minimumStake()) * 5n; // 5x minimum stake + const askLowerBoundBefore = await AskStorage.getAskLowerBound(); + const nodeAsk = askLowerBoundBefore / SCALING_FACTOR + 10n; // Slightly above lower bound + const deps = { + accounts, + Profile, + Token, + Staking, + Ask, + KnowledgeCollection, + }; + + const { node: publishingNode, identityId: publishingNodeIdentityId } = + await setupNodeWithStakeAndAsk(nodeIdCounter, nodeStake, nodeAsk, deps); + nodeIdCounter += 2; // Account for both admin and operational accounts + + // Create a knowledge collection to set up publishing factor + const kcCreator = accounts[90]; // Use high index to avoid conflicts + const receivingNodes = []; + const receivingNodesIdentityIds = []; + for (let i = 0; i < 5; i++) { + const { node, identityId } = await setupNodeWithStakeAndAsk( + nodeIdCounter, + await ParametersStorage.minimumStake(), + nodeAsk, + deps, + ); + nodeIdCounter += 2; // Account for both admin and operational accounts + receivingNodes.push(node); + receivingNodesIdentityIds.push(identityId); + } + + await createKnowledgeCollection( + kcCreator, + publishingNode, + publishingNodeIdentityId, + receivingNodes, + receivingNodesIdentityIds, + deps, + merkleRoot, + ); + + // Calculate expected score using our helper function + const expectedScore = await calculateExpectedNodeScore( + BigInt(publishingNodeIdentityId), + nodeStake, + { + ParametersStorage, + ProfileStorage, + AskStorage, + EpochStorage, + }, + ); + + // Calculate actual score from contract + const actualScore = await RandomSampling.calculateNodeScore( + publishingNodeIdentityId, + ); + + // Verify they match exactly + expect(actualScore).to.equal(expectedScore); + }); + + it('Should return higher score for lower ask prices (competitive pricing)', async () => { + // Setup: Create two identical nodes with different ask prices + const nodeStake = (await ParametersStorage.minimumStake()) * 3n; + const deps = { + accounts, + Profile, + Token, + Staking, + Ask, + KnowledgeCollection, + }; + + // Get ask bounds to set competitive asks + const [askLowerBound, askUpperBound] = await AskStorage.getAskBounds(); + + expect(askUpperBound).to.be.greaterThan(askLowerBound); + expect(askLowerBound).to.be.greaterThan(0n); + + const lowAsk = askLowerBound / SCALING_FACTOR + 1n; // Just above lower bound (competitive) + const highAsk = askUpperBound / SCALING_FACTOR - 1n; // Just below upper bound (expensive) + + // Node 1: Low ask (competitive) + const { identityId: node1Id } = await setupNodeWithStakeAndAsk( + nodeIdCounter, + nodeStake, + lowAsk, + deps, + ); + nodeIdCounter += 2; // Account for both admin and operational accounts + + // Node 2: High ask (expensive) + const { identityId: node2Id } = await setupNodeWithStakeAndAsk( + nodeIdCounter, + nodeStake, + highAsk, + deps, + ); + nodeIdCounter += 2; // Account for both admin and operational accounts + + // Calculate scores + const score1 = await RandomSampling.calculateNodeScore(node1Id); + const score2 = await RandomSampling.calculateNodeScore(node2Id); + + // Lower ask should result in higher score (better competitiveness) + expect(score1).to.be.greaterThan(score2); + }); + + it('Should return higher score for higher stake amounts', async () => { + // Setup: Create two nodes with different stake amounts + const lowStake = await ParametersStorage.minimumStake(); + const highStake = lowStake * 4n; // 4x the minimum + const askLowerBoundBefore = await AskStorage.getAskLowerBound(); + const nodeAsk = askLowerBoundBefore / SCALING_FACTOR + 10n; // Slightly above lower bound + const deps = { + accounts, + Profile, + Token, + Staking, + Ask, + KnowledgeCollection, + }; + + // Node 1: Low stake + const { identityId: node1Id } = await setupNodeWithStakeAndAsk( + nodeIdCounter, + lowStake, + nodeAsk, + deps, + ); + nodeIdCounter += 2; // Account for both admin and operational accounts + + // Node 2: High stake + const { identityId: node2Id } = await setupNodeWithStakeAndAsk( + nodeIdCounter, + highStake, + nodeAsk, + deps, + ); + nodeIdCounter += 2; // Account for both admin and operational accounts + + // Calculate scores + const score1 = await RandomSampling.calculateNodeScore(node1Id); + const score2 = await RandomSampling.calculateNodeScore(node2Id); + + // Higher stake should result in higher score + expect(score2).to.be.greaterThan(score1); + }); + + it('Should demonstrate quadratic relationship in stake factor', async () => { + // Setup: Test that stake factor follows quadratic formula: 2 * (stake/maxStake)^2 + const minimumStake = await ParametersStorage.minimumStake(); + const testStakes = [ + minimumStake, + minimumStake * 2n, + minimumStake * 4n, + minimumStake * 8n, + ]; + const nodeAsk = 200000000000000000n; // 0.2 ETH + + const deps = { + accounts, + Profile, + Token, + Staking, + Ask, + KnowledgeCollection, + }; + + const scores = []; + for (const stake of testStakes) { + const { identityId } = await setupNodeWithStakeAndAsk( + nodeIdCounter, + stake, + nodeAsk, + deps, + ); + nodeIdCounter += 2; + + const score = await RandomSampling.calculateNodeScore(identityId); + scores.push(score); + } + + // Verify quadratic growth: doubling stake should roughly quadruple the stake component + // Since score = stakeFactor + askFactor + pubFactor, and askFactor depends on stake too, + // we expect significant but not exactly 4x growth + expect(scores[1]).to.be.greaterThan(scores[0] * 2n); // More than 2x + expect(scores[2]).to.be.greaterThan(scores[1] * 2n); // More than 2x again + expect(scores[3]).to.be.greaterThan(scores[2] * 2n); // More than 2x again + }); + + it('Should handle ask prices near bounds correctly', async () => { + // Setup: Test ask prices near lower and upper bounds + const nodeStake = (await ParametersStorage.minimumStake()) * 3n; + const deps = { + accounts, + Profile, + Token, + Staking, + Ask, + KnowledgeCollection, + }; + + const [askLowerBound, askUpperBound] = await AskStorage.getAskBounds(); + + expect(askUpperBound).to.be.greaterThan(askLowerBound); + expect(askLowerBound).to.be.greaterThan(0n); + + // Ensure asks are properly within bounds by adding/subtracting small amounts + const lowerBoundAsk = askLowerBound / SCALING_FACTOR + 1n; // Slightly above lower bound + const upperBoundAsk = askUpperBound / SCALING_FACTOR - 1n; // Slightly below upper bound + + // Node 1: Near lower bound (competitive pricing) + const { identityId: node1Id } = await setupNodeWithStakeAndAsk( + nodeIdCounter, + nodeStake, + lowerBoundAsk, + deps, + ); + nodeIdCounter += 2; + + // Node 2: Near upper bound (expensive pricing) + const { identityId: node2Id } = await setupNodeWithStakeAndAsk( + nodeIdCounter, + nodeStake, + upperBoundAsk, + deps, + ); + nodeIdCounter += 2; + + const score1 = await RandomSampling.calculateNodeScore(node1Id); + const expectedScore1 = await calculateExpectedNodeScore( + BigInt(node1Id), + nodeStake, + { + ParametersStorage, + ProfileStorage, + AskStorage, + EpochStorage, + }, + ); + const score2 = await RandomSampling.calculateNodeScore(node2Id); + const expectedScore2 = await calculateExpectedNodeScore( + BigInt(node2Id), + nodeStake, + { + ParametersStorage, + ProfileStorage, + AskStorage, + EpochStorage, + }, + ); + + // Verify that both scores are reasonable and within expected ranges + // The exact relationship depends on the ask factor implementation details + expect(score1).to.be.equal(expectedScore1); + expect(score2).to.be.equal(expectedScore2); + + // Verify node with lower ask has higher score + expect(score1).to.be.greaterThan(score2); + }); + + it('Should return zero ask factor for asks outside bounds', async () => { + // Setup: Test asks outside the valid bounds + const nodeStake = (await ParametersStorage.minimumStake()) * 2n; + const deps = { + accounts, + Profile, + Token, + Staking, + Ask, + KnowledgeCollection, + }; + + const [askLowerBound, askUpperBound] = await AskStorage.getAskBounds(); + + expect(askUpperBound).to.be.greaterThan(askLowerBound); + expect(askLowerBound).to.be.greaterThan(0n); + + // Test with ask below lower bound (if possible to set) + const belowBoundAsk = askLowerBound / SCALING_FACTOR / 2n; + if (belowBoundAsk > 0n) { + const { identityId: lowNodeId } = await setupNodeWithStakeAndAsk( + nodeIdCounter, + nodeStake, + belowBoundAsk, + deps, + ); + nodeIdCounter += 2; + + // Test with ask above upper bound + const aboveBoundAsk = (askUpperBound / SCALING_FACTOR) * 2n; + const { identityId: highNodeId } = await setupNodeWithStakeAndAsk( + nodeIdCounter, + nodeStake, + aboveBoundAsk, + deps, + ); + nodeIdCounter += 2; + + // Test with ask within bounds for comparison + const withinBoundAsk = askLowerBound / SCALING_FACTOR + 1n; + const { identityId: validNodeId } = await setupNodeWithStakeAndAsk( + nodeIdCounter, + nodeStake, + withinBoundAsk, + deps, + ); + nodeIdCounter += 2; + + const lowAskScore = await RandomSampling.calculateNodeScore(lowNodeId); + const highAskScore = + await RandomSampling.calculateNodeScore(highNodeId); + const validAskScore = + await RandomSampling.calculateNodeScore(validNodeId); + + // Nodes with asks outside bounds should have lower scores (no ask factor) + expect(validAskScore).to.be.greaterThan(lowAskScore); + expect(validAskScore).to.be.greaterThan(highAskScore); + expect(highAskScore).to.be.equal(lowAskScore); + } + }); + + it('Should demonstrate publishing factor impact on score', async () => { + // Setup: Create nodes and test publishing factor contribution + const nodeStake = (await ParametersStorage.minimumStake()) * 3n; + const askLowerBoundBefore = await AskStorage.getAskLowerBound(); + const nodeAsk = askLowerBoundBefore / SCALING_FACTOR + 10n; // Slightly above lower bound + const deps = { + accounts, + Profile, + Token, + Staking, + Ask, + KnowledgeCollection, + }; + + // Node 1: Will have publishing activity + const { node: publishingNode, identityId: publishingNodeId } = + await setupNodeWithStakeAndAsk(nodeIdCounter, nodeStake, nodeAsk, deps); + nodeIdCounter += 2; + + // Node 2: Will have no publishing activity + const { identityId: nonPublishingNodeId } = + await setupNodeWithStakeAndAsk(nodeIdCounter, nodeStake, nodeAsk, deps); + nodeIdCounter += 2; + + // Create receiving nodes + const receivingNodes = []; + const receivingNodesIdentityIds = []; + for (let i = 0; i < 3; i++) { + const { node, identityId } = await setupNodeWithStakeAndAsk( + nodeIdCounter, + await ParametersStorage.minimumStake(), + nodeAsk, + deps, + ); + nodeIdCounter += 2; + receivingNodes.push(node); + receivingNodesIdentityIds.push(identityId); + } + + // Create knowledge collection with publishing node (gives it publishing factor) + const kcCreator = accounts[95]; + await createKnowledgeCollection( + kcCreator, + publishingNode, + publishingNodeId, + receivingNodes, + receivingNodesIdentityIds, + deps, + merkleRoot, + ); + + // Calculate scores + const publishingScore = + await RandomSampling.calculateNodeScore(publishingNodeId); + const nonPublishingScore = + await RandomSampling.calculateNodeScore(nonPublishingNodeId); + + // Verify publishing factor + const publishingFactor = + await EpochStorage.getNodeCurrentEpochProducedKnowledgeValue( + publishingNodeId, + ); + expect(publishingFactor).to.be.greaterThan(0n); + + const nonPublishingFactor = + await EpochStorage.getNodeCurrentEpochProducedKnowledgeValue( + nonPublishingNodeId, + ); + expect(nonPublishingFactor).to.equal(0n); + expect(publishingFactor).to.be.greaterThan(nonPublishingFactor); + + // Node with publishing activity should have higher score + expect(publishingScore).to.be.greaterThan(nonPublishingScore); + }); + + it('Should handle edge case where maximum publishing value is zero', async () => { + // Move to a new epoch + await network.provider.send('evm_increaseTime', [ + Number(await Chronos.epochLength()) * 2, + ]); + await network.provider.send('evm_mine'); + + // Create a node with minimum stake and ask + const nodeStake = await ParametersStorage.minimumStake(); + const askLowerBoundBefore = await AskStorage.getAskLowerBound(); + const nodeAsk = askLowerBoundBefore / SCALING_FACTOR + 10n; // Slightly above lower bound + const deps = { + accounts, + Profile, + Token, + Staking, + Ask, + KnowledgeCollection, + }; + + const { identityId } = await setupNodeWithStakeAndAsk( + nodeIdCounter, + nodeStake, + nodeAsk, + deps, + ); + nodeIdCounter += 2; + + // Verify the max publishing value is indeed > 0 in our setup + const maxNodePub = + await EpochStorage.getCurrentEpochNodeMaxProducedKnowledgeValue(); + expect(maxNodePub).to.be.equal(0n); + + const actualNodeScore = + await RandomSampling.calculateNodeScore(identityId); + const expectedNodeScore = await calculateExpectedNodeScore( + BigInt(identityId), + nodeStake, + { + ParametersStorage, + ProfileStorage, + AskStorage, + EpochStorage, + }, + ); + expect(actualNodeScore).to.be.equal(expectedNodeScore); + }); + + it('Should handle identical nodes with identical scores', async () => { + // Setup: Create two identical nodes and verify they get identical scores + const nodeStake = (await ParametersStorage.minimumStake()) * 2n; + const askLowerBoundBefore = await AskStorage.getAskLowerBound(); + const nodeAsk = askLowerBoundBefore / SCALING_FACTOR + 10n; // Slightly above lower bound + const deps = { + accounts, + Profile, + Token, + Staking, + Ask, + KnowledgeCollection, + }; + + // Node 1 + const { identityId: node1Id } = await setupNodeWithStakeAndAsk( + nodeIdCounter, + nodeStake, + nodeAsk, + deps, + ); + nodeIdCounter += 2; + + // Node 2 (identical setup) + const { identityId: node2Id } = await setupNodeWithStakeAndAsk( + nodeIdCounter, + nodeStake, + nodeAsk, + deps, + ); + nodeIdCounter += 2; + + // Calculate scores + const score1 = await RandomSampling.calculateNodeScore(node1Id); + const score2 = await RandomSampling.calculateNodeScore(node2Id); + + // Scores should be identical for identical nodes + expect(score1).to.equal(score2); + }); + }); +}); diff --git a/test/integration/Staking.test.ts b/test/integration/Staking.test.ts new file mode 100644 index 00000000..a2ed3859 --- /dev/null +++ b/test/integration/Staking.test.ts @@ -0,0 +1,5966 @@ +import { SignerWithAddress } from '@nomicfoundation/hardhat-ethers/signers'; +import { time } from '@nomicfoundation/hardhat-network-helpers'; +// @ts-expect-error: No type definitions available for assertion-tools +import { kcTools } from 'assertion-tools'; +import { expect } from 'chai'; +import hre, { ethers } from 'hardhat'; + +import { + Hub, + Token, + Chronos, + StakingStorage, + RandomSamplingStorage, + ParametersStorage, + ProfileStorage, + EpochStorage, + DelegatorsInfo, + Ask, + Staking, + StakingKPI, + RandomSampling, + Profile, + KnowledgeCollection, + AskStorage, +} from '../../typechain'; +import { createKnowledgeCollection } from '../helpers/kc-helpers'; +import { createProfile } from '../helpers/profile-helpers'; + +// Sample data for KC +const quads = [ + ' "468.9 sq mi" .', + ' "New York" .', + ' "8,336,817" .', + ' "New York" .', + ' .', + ' "0xaac2a420672a1eb77506c544ff01beed2be58c0ee3576fe037c846f97481cefd" .', + ' .', + ' .', + ' .', + // Add more quads to ensure we have enough chunks + ...Array(1000).fill( + ' .', + ), +]; +const merkleRoot = kcTools.calculateMerkleRoot(quads, 32); + +const toTRAC = (x: string | number) => ethers.parseUnits(x.toString(), 18); + +// ================================================================================================================ +// HELPER FUNCTIONS: Extract common functionality for better readability and reusability +// ================================================================================================================ + +type TestContracts = { + hub: Hub; + token: Token; + chronos: Chronos; + stakingStorage: StakingStorage; + randomSamplingStorage: RandomSamplingStorage; + parametersStorage: ParametersStorage; + profileStorage: ProfileStorage; + epochStorage: EpochStorage; + delegatorsInfo: DelegatorsInfo; + staking: Staking; + stakingKPI: StakingKPI; + profile: Profile; + randomSampling: RandomSampling; + kc: KnowledgeCollection; + askStorage: AskStorage; + ask: Ask; +}; + +type TestAccounts = { + owner: SignerWithAddress; + node1: { operational: SignerWithAddress; admin: SignerWithAddress }; + node2: { operational: SignerWithAddress; admin: SignerWithAddress }; + delegator1: SignerWithAddress; + delegator2: SignerWithAddress; + delegator3: SignerWithAddress; + kcCreator: SignerWithAddress; + receiver1: { operational: SignerWithAddress; admin: SignerWithAddress }; + receiver2: { operational: SignerWithAddress; admin: SignerWithAddress }; + receiver3: { operational: SignerWithAddress; admin: SignerWithAddress }; +}; + +/** + * Calculate expected node score manually to verify contract calculation + * This implements the same logic as RandomSampling.calculateNodeScore() + */ +async function calculateExpectedNodeScore( + nodeId: bigint, + contracts: TestContracts, +): Promise { + const SCALE18 = ethers.parseUnits('1', 18); + + // 1. Node stake factor calculation + const maximumStake = await contracts.parametersStorage.maximumStake(); + let nodeStake = await contracts.stakingStorage.getNodeStake(nodeId); + nodeStake = nodeStake > maximumStake ? maximumStake : nodeStake; + + const stakeRatio18 = (nodeStake * SCALE18) / maximumStake; + const nodeStakeFactor18 = (2n * stakeRatio18 * stakeRatio18) / SCALE18; + + // 2. Node ask factor calculation + const nodeAsk18 = (await contracts.profileStorage.getAsk(nodeId)) * SCALE18; + const [askLowerBound18, askUpperBound18] = + await contracts.askStorage.getAskBounds(); + + let nodeAskFactor18 = 0n; + if ( + askUpperBound18 > askLowerBound18 && + nodeAsk18 >= askLowerBound18 && + nodeAsk18 <= askUpperBound18 + ) { + const askDiffRatio18 = + ((askUpperBound18 - nodeAsk18) * SCALE18) / + (askUpperBound18 - askLowerBound18); + nodeAskFactor18 = (stakeRatio18 * askDiffRatio18 ** 2n) / SCALE18 ** 2n; + } + + // 3. Node publishing factor calculation + const nodePub = + await contracts.epochStorage.getNodeCurrentEpochProducedKnowledgeValue( + nodeId, + ); + const maxNodePub = + await contracts.epochStorage.getCurrentEpochNodeMaxProducedKnowledgeValue(); + + let nodePublishingFactor18 = 0n; + if (maxNodePub > 0n) { + const pubRatio18 = (nodePub * SCALE18) / maxNodePub; + nodePublishingFactor18 = (nodeStakeFactor18 * pubRatio18) / SCALE18; + } + + return nodeStakeFactor18 + nodeAskFactor18 + nodePublishingFactor18; +} + +/** + * Calculate expected delegator score earned during a period + */ +function calculateExpectedDelegatorScore( + delegatorStake: bigint, + nodeScorePerStake: bigint, + delegatorLastSettledNodeScorePerStake: bigint, +): bigint { + const diff = nodeScorePerStake - delegatorLastSettledNodeScorePerStake; + const SCALE18 = ethers.parseUnits('1', 18); + return (delegatorStake * diff) / SCALE18; +} + +async function epochRewardsPoolPrecisionLoss( + contracts: TestContracts, + claimEpoch: bigint, + netNodeRewards: bigint, + expectedRewardsPool: bigint, +): Promise { + const epochRewardsPool = await contracts.epochStorage.getEpochPool( + 1, + claimEpoch, + ); + console.log( + ` ✅ Epoch rewards pool: ${ethers.formatUnits(epochRewardsPool, 18)} TRAC`, + ); + expect(epochRewardsPool).to.equal(netNodeRewards); + console.log( + ` ✅ Expected rewards pool: ${ethers.formatUnits(expectedRewardsPool, 18)} TRAC`, + ); + console.log( + ` ⚠️ [Epoch ${claimEpoch}] Precision loss: ${ethers.formatUnits( + epochRewardsPool - expectedRewardsPool, + 18, + )} TRAC`, + ); + expect(epochRewardsPool).to.be.closeTo( + expectedRewardsPool, + ethers.parseUnits('0.0000002', 18), + ); +} + +/** + * Submit a proof for a node and verify the score calculation + */ +async function submitProofAndVerifyScore( + nodeId: bigint, + node: { operational: SignerWithAddress; admin: SignerWithAddress }, + contracts: TestContracts, + epoch: bigint, + expectedTotalStake: bigint, +): Promise<{ nodeScore: bigint; nodeScorePerStake: bigint }> { + console.log(` 📋 Submitting proof for node ${nodeId}...`); + + // Get scores before proof submission + const nodeScoreBeforeProofSubmission = + await contracts.randomSamplingStorage.getNodeEpochScore(epoch, nodeId); + const nodeScorePerStakeBeforeProofSubmission = + await contracts.randomSamplingStorage.getNodeEpochScorePerStake( + epoch, + nodeId, + ); + + // Create challenge + await contracts.randomSampling.connect(node.operational).createChallenge(); + const challenge = + await contracts.randomSamplingStorage.getNodeChallenge(nodeId); + + // Generate and submit proof + const chunks = kcTools.splitIntoChunks(quads, 32); + const chunkId = Number(challenge[1]); + const { proof } = kcTools.calculateMerkleProof(quads, 32, chunkId); + await contracts.randomSampling + .connect(node.operational) + .submitProof(chunks[chunkId], proof); + + // Get actual score from contract + const nodeScoreAfterProofSubmission = + await contracts.randomSamplingStorage.getNodeEpochScore(epoch, nodeId); + const nodeScorePerStake = + await contracts.randomSamplingStorage.getNodeEpochScorePerStake( + epoch, + nodeId, + ); + + // Calculate expected scores + const nodeScoreIncrement = await calculateExpectedNodeScore( + nodeId, + contracts, + ); + console.log(` ✅ Node score expected increment: ${nodeScoreIncrement}`); + const expectedNodeScore = nodeScoreBeforeProofSubmission + nodeScoreIncrement; + console.log( + ` ✅ Expected node score: ${nodeScoreBeforeProofSubmission} + ${nodeScoreIncrement} = ${expectedNodeScore}, actual ${nodeScoreAfterProofSubmission}`, + ); + // Verify scores match + expect(nodeScoreAfterProofSubmission).to.be.gt( + 0, + 'Node score should be positive', + ); + expect(nodeScoreAfterProofSubmission).to.be.equal(expectedNodeScore); + + const nodeScorePerStakeIncrement = + (nodeScoreIncrement * ethers.parseUnits('1', 18)) / expectedTotalStake; + console.log( + ` ✅ Node score per stake expected increment: ${nodeScorePerStakeIncrement}`, + ); + const expectedNodeScorePerStake = + nodeScorePerStakeBeforeProofSubmission + nodeScorePerStakeIncrement; + console.log( + ` ✅ Node score per stake: expected ${nodeScorePerStakeBeforeProofSubmission} + ${nodeScorePerStakeIncrement} = ${expectedNodeScorePerStake}, actual ${nodeScorePerStake}`, + ); + expect(nodeScorePerStake).to.be.gt( + 0, + 'Node score per stake should be positive', + ); + expect(nodeScorePerStake).to.be.equal(expectedNodeScorePerStake); + + return { + nodeScore: nodeScoreAfterProofSubmission, + nodeScorePerStake: nodeScorePerStake, + }; +} + +/** + * Advance to next proofing period by mining blocks + */ +async function advanceToNextProofingPeriod( + contracts: TestContracts, +): Promise { + const proofingPeriodDuration = + await contracts.randomSamplingStorage.getLatestProofingPeriodDurationInBlocks(); + const activeProofPeriodStartBlock = + await contracts.randomSamplingStorage.getActiveProofPeriodStartBlock(); + + // Find out how many blocks are left in the current proofing period + const currentBlock = Number( + await hre.network.provider.send('eth_blockNumber'), + ); + const blocksLeft = + Number(activeProofPeriodStartBlock) + + Number(proofingPeriodDuration) - + currentBlock + + 1; + + for (let i = 0; i < blocksLeft; i++) { + await hre.network.provider.send('evm_mine'); + } + + await contracts.randomSampling.updateAndGetActiveProofPeriodStartBlock(); +} + +async function ensureNodeHasChunksThisEpoch( + nodeId: bigint, + node: { operational: SignerWithAddress; admin: SignerWithAddress }, + contracts: TestContracts, + accounts: TestAccounts, + receivingNodes: { + operational: SignerWithAddress; + admin: SignerWithAddress; + }[], + receivingNodesIdentityIds: number[], + chunkSize: number, +): Promise { + const produced = + await contracts.epochStorage.getNodeCurrentEpochProducedKnowledgeValue( + nodeId, + ); + + if (produced === 0n) { + if ( + !receivingNodes.some( + (r) => r.operational.address === node.operational.address, + ) + ) { + receivingNodes.unshift(node); + receivingNodesIdentityIds.unshift(Number(nodeId)); + } + + await createKnowledgeCollection( + node.operational, // signer = node.operational + node, // publisher-node + Number(nodeId), + receivingNodes, + receivingNodesIdentityIds, + { KnowledgeCollection: contracts.kc, Token: contracts.token }, + merkleRoot, + `ensure-chunks-${Date.now()}`, + 1, // holders + chunkSize, // byteSize - must be >= CHUNK_BYTE_SIZE to avoid division by zero + 1, // replicas + toTRAC(1), + ); + + await contracts.randomSampling.updateAndGetActiveProofPeriodStartBlock(); + } +} + +/** + * Setup initial test environment with accounts and contracts + */ +async function setupTestEnvironment(): Promise<{ + accounts: TestAccounts; + contracts: TestContracts; + nodeIds: { node1Id: bigint; node2Id: bigint }; + chunkSize: number; +}> { + await hre.deployments.fixture(); + + const signers = await hre.ethers.getSigners(); + const accounts: TestAccounts = { + owner: signers[0], + node1: { operational: signers[1], admin: signers[2] }, + node2: { operational: signers[3], admin: signers[4] }, + delegator1: signers[5], + delegator2: signers[6], + delegator3: signers[7], + kcCreator: signers[8], + receiver1: { operational: signers[9], admin: signers[10] }, + receiver2: { operational: signers[11], admin: signers[12] }, + receiver3: { operational: signers[13], admin: signers[14] }, + }; + + const contracts: TestContracts = { + hub: await hre.ethers.getContract('Hub'), + token: await hre.ethers.getContract('Token'), + chronos: await hre.ethers.getContract('Chronos'), + stakingStorage: + await hre.ethers.getContract('StakingStorage'), + randomSamplingStorage: await hre.ethers.getContract( + 'RandomSamplingStorage', + ), + parametersStorage: + await hre.ethers.getContract('ParametersStorage'), + profileStorage: + await hre.ethers.getContract('ProfileStorage'), + epochStorage: await hre.ethers.getContract('EpochStorageV8'), + delegatorsInfo: + await hre.ethers.getContract('DelegatorsInfo'), + staking: await hre.ethers.getContract('Staking'), + stakingKPI: await hre.ethers.getContract('StakingKPI'), + profile: await hre.ethers.getContract('Profile'), + randomSampling: + await hre.ethers.getContract('RandomSampling'), + kc: await hre.ethers.getContract( + 'KnowledgeCollection', + ), + askStorage: await hre.ethers.getContract('AskStorage'), + ask: await hre.ethers.getContract('Ask'), + }; + + // Get chunk size to avoid division by zero in challenge generation + const chunkSize = Number( + await contracts.randomSamplingStorage.CHUNK_BYTE_SIZE(), + ); + + await contracts.hub.setContractAddress('HubOwner', accounts.owner.address); + + // Mint tokens for all participants + for (const delegator of [ + accounts.delegator1, + accounts.delegator2, + accounts.delegator3, + ]) { + await contracts.token.mint(delegator.address, toTRAC(100_000)); + } + // const d2Balance = await contracts.token.balanceOf( + // accounts.delegator2.address, + // ); + /* console.log( + `\n💰💰💰 INITIAL BALANCE 💰💰💰 Delegator2 balance after minting: ${ethers.formatUnits( + d2Balance, + await contracts.token.decimals(), + )} TRAC\n`, + ); */ + await contracts.token.mint(accounts.owner.address, toTRAC(1_000_000)); + await contracts.token.mint( + accounts.node1.operational.address, + toTRAC(1_000_000), + ); + await contracts.token.mint(accounts.kcCreator.address, toTRAC(1_000_000)); + + await contracts.parametersStorage + .connect(accounts.owner) // HubOwner + .setOperatorFeeUpdateDelay(0); + + // Create node profiles + const { identityId: node1Id } = await createProfile( + contracts.profile, + accounts.node1, + ); + const { identityId: node2Id } = await createProfile( + contracts.profile, + accounts.node2, + ); + console.log(`\n📚 Node1 ID = ${node1Id}, operator fee=0`); + await contracts.profile + .connect(accounts.node1.admin) + .updateOperatorFee(node1Id, 0); // 0 % + + expect(await contracts.profileStorage.getOperatorFee(node1Id)).to.equal(0); + + console.log(`\n📚 Node2 ID = ${node2Id}, operator fee=0`); + await contracts.profile + .connect(accounts.node2.admin) + .updateOperatorFee(node2Id, 0); // 0 % + + expect(await contracts.profileStorage.getOperatorFee(node2Id)).to.equal(0); + // Initialize ask system (required to prevent division by zero in RandomSampling) + await contracts.parametersStorage.setMinimumStake(toTRAC(100)); + + // Jump to clean epoch start + const timeUntilNextEpoch = await contracts.chronos.timeUntilNextEpoch(); + await time.increase(timeUntilNextEpoch + 1n); + + return { + accounts, + contracts, + nodeIds: { node1Id: BigInt(node1Id), node2Id: BigInt(node2Id) }, + chunkSize, + }; +} + +describe(`Full complex scenario`, function () { + let accounts: TestAccounts; + let contracts: TestContracts; + let nodeIds: { node1Id: bigint; node2Id: bigint }; + let node1Id: bigint; + let d1Key: string, d2Key: string, d3Key: string; + let epoch1: bigint; + let receivingNodes: { + operational: SignerWithAddress; + admin: SignerWithAddress; + }[]; + let receivingNodesIdentityIds: number[]; + let TOKEN_DECIMALS = 18; + let chunkSize: number; + + it('Should execute steps 1-7 with detailed score calculations and verification', async function () { + // ================================================================================================================ + // SETUP: Initialize test environment + // ================================================================================================================ + const setup = await setupTestEnvironment(); + accounts = setup.accounts; + contracts = setup.contracts; + nodeIds = setup.nodeIds; + chunkSize = setup.chunkSize; + node1Id = nodeIds.node1Id; + + TOKEN_DECIMALS = Number(await contracts.token.decimals()); + + epoch1 = await contracts.chronos.getCurrentEpoch(); + const epochLength = await contracts.chronos.epochLength(); + const leftUntilNextEpoch = await contracts.chronos.timeUntilNextEpoch(); + console.log(`\n🏁 Starting test in epoch ${epoch1}`); + console.log(`\n🏁 Epoch length ${epochLength}`); + console.log(`\n🏁 Time until next epoch ${leftUntilNextEpoch}`); + console.log( + `\n🏁 Remaining percentage of time until next epoch ${leftUntilNextEpoch / epochLength}`, + ); + // Create delegator keys for state verification + d1Key = ethers.keccak256( + ethers.solidityPacked(['address'], [accounts.delegator1.address]), + ); + d2Key = ethers.keccak256( + ethers.solidityPacked(['address'], [accounts.delegator2.address]), + ); + d3Key = ethers.keccak256( + ethers.solidityPacked(['address'], [accounts.delegator3.address]), + ); + + // ================================================================================================================ + // SETUP: Create Knowledge Collection for reward pool + // ================================================================================================================ + console.log(`\n📚 Creating Knowledge Collection for reward pool...`); + + receivingNodes = [ + accounts.receiver1, + accounts.receiver2, + accounts.receiver3, + ]; + receivingNodesIdentityIds = []; + for (const recNode of receivingNodes) { + const { identityId } = await createProfile(contracts.profile, recNode); + receivingNodesIdentityIds.push(Number(identityId)); + } + + const kcTokenAmount = toTRAC(48_000); + const numberOfEpochs = 10; + console.log( + `\n📚 Reward pool = ${ethers.formatUnits(kcTokenAmount, 18)} TRAC, for ${numberOfEpochs} epochs = ${kcTokenAmount / BigInt(numberOfEpochs)} per epoch`, + ); + await createKnowledgeCollection( + accounts.kcCreator, + accounts.node1, + Number(node1Id), + receivingNodes, + receivingNodesIdentityIds, + { KnowledgeCollection: contracts.kc, Token: contracts.token }, + merkleRoot, + 'test-op-id', + 10, + chunkSize * 10, // byteSize - use multiple of chunkSize for proper chunk generation + numberOfEpochs, + kcTokenAmount, + ); + + // we're sure tokens are well distributed to epochs + + // ================================================================================================================ + // STEP 1: Delegator1 stakes 10,000 TRAC + // ================================================================================================================ + console.log(`\n📊 STEP 1: Delegator1 stakes 10,000 TRAC`); + + const epochBeforeStake = await contracts.chronos.getCurrentEpoch(); + console.log(` ℹ️ Current epoch before staking: ${epochBeforeStake}`); + + await contracts.token + .connect(accounts.delegator1) + .approve(await contracts.staking.getAddress(), toTRAC(10_000)); + await contracts.staking + .connect(accounts.delegator1) + .stake(node1Id, toTRAC(10_000)); + + // Verify state + const totalStakeAfterStep1 = + await contracts.stakingStorage.getNodeStake(node1Id); + console.log( + ` ✅ Node1 total stake: ${ethers.formatUnits(totalStakeAfterStep1, 18)} TRAC`, + ); + expect(totalStakeAfterStep1).to.equal(toTRAC(10_000)); + const totalDelegatorStakeAfterStep1 = + await contracts.stakingStorage.getDelegatorStakeBase(node1Id, d1Key); + console.log( + ` ✅ Delegator1 total stake: ${ethers.formatUnits(totalDelegatorStakeAfterStep1, 18)} TRAC`, + ); + expect(totalDelegatorStakeAfterStep1).to.equal(toTRAC(10_000)); + + // ================================================================================================================ + // STEP 2: Delegator2 stakes 20,000 TRAC + // ================================================================================================================ + console.log(`\n📊 STEP 2: Delegator2 stakes 20,000 TRAC`); + + await contracts.token + .connect(accounts.delegator2) + .approve(await contracts.staking.getAddress(), toTRAC(20_000)); + await contracts.staking + .connect(accounts.delegator2) + .stake(node1Id, toTRAC(20_000)); + + const totalStakeAfterStep2 = + await contracts.stakingStorage.getNodeStake(node1Id); + console.log( + ` ✅ Node1 total stake: ${ethers.formatUnits(totalStakeAfterStep2, 18)} TRAC`, + ); + expect(totalStakeAfterStep2).to.equal(toTRAC(30_000)); + const totalDelegatorStakeAfterStep2 = + await contracts.stakingStorage.getDelegatorStakeBase(node1Id, d2Key); + console.log( + ` ✅ Delegator2 total stake: ${ethers.formatUnits(totalDelegatorStakeAfterStep2, 18)} TRAC`, + ); + expect(totalDelegatorStakeAfterStep2).to.equal(toTRAC(20_000)); + + // ================================================================================================================ + // STEP 3: Delegator3 stakes 30,000 TRAC + // ================================================================================================================ + console.log(`\n📊 STEP 3: Delegator3 stakes 30,000 TRAC`); + + await contracts.token + .connect(accounts.delegator3) + .approve(await contracts.staking.getAddress(), toTRAC(30_000)); + await contracts.staking + .connect(accounts.delegator3) + .stake(node1Id, toTRAC(30_000)); + + const totalStakeAfterStep3 = + await contracts.stakingStorage.getNodeStake(node1Id); + console.log( + ` ✅ Node1 total stake: ${ethers.formatUnits(totalStakeAfterStep3, 18)} TRAC`, + ); + expect(totalStakeAfterStep3).to.equal(toTRAC(60_000)); + const totalDelegatorStakeAfterStep3 = + await contracts.stakingStorage.getDelegatorStakeBase(node1Id, d3Key); + console.log( + ` ✅ Delegator3 total stake: ${ethers.formatUnits(totalDelegatorStakeAfterStep3, 18)} TRAC`, + ); + expect(totalDelegatorStakeAfterStep3).to.equal(toTRAC(30_000)); + + // ================================================================================================================ + // STEP 4: Node1 submits first proof with score verification + // ================================================================================================================ + console.log(`\n🔬 STEP 4: Node1 submits first proof`); + + await contracts.randomSampling.updateAndGetActiveProofPeriodStartBlock(); + const { + nodeScore: scoreAfter1, + nodeScorePerStake: nodeScorePerStakeAfter1, + } = await submitProofAndVerifyScore( + node1Id, + accounts.node1, + contracts, + epoch1, + totalStakeAfterStep3, + ); + + // ================================================================================================================ + // STEP 5: Delegator1 stakes additional 10,000 TRAC with score settlement verification + // ================================================================================================================ + console.log(`\n📊 STEP 5: Delegator1 stakes additional 10,000 TRAC`); + + // Get delegator1's score before staking + const d1ScoreBeforeStake = + await contracts.randomSamplingStorage.getEpochNodeDelegatorScore( + epoch1, + node1Id, + d1Key, + ); + + // Get delegator1's last settled node score per stake + const d1LastSettledNodeScorePerStake = + await contracts.randomSamplingStorage.getDelegatorLastSettledNodeEpochScorePerStake( + epoch1, + node1Id, + d1Key, + ); + + // Stake additional 10,000 TRAC + await contracts.token + .connect(accounts.delegator1) + .approve(await contracts.staking.getAddress(), toTRAC(10_000)); + await contracts.staking + .connect(accounts.delegator1) + .stake(node1Id, toTRAC(10_000)); + + // Verify node1's total stake + const totalStakeAfterStep5 = + await contracts.stakingStorage.getNodeStake(node1Id); + console.log( + ` ✅ Node1 total stake: ${ethers.formatUnits(totalStakeAfterStep5, 18)} TRAC`, + ); + expect(totalStakeAfterStep5).to.equal(toTRAC(70_000)); + const totalDelegator1StakeAfterStep5 = + await contracts.stakingStorage.getDelegatorStakeBase(node1Id, d1Key); + console.log( + ` ✅ Delegator1 total stake: ${ethers.formatUnits(totalDelegator1StakeAfterStep5, 18)} TRAC`, + ); + expect(totalDelegator1StakeAfterStep5).to.equal(toTRAC(20_000)); + + // Verify delegator1's score settlement from first proof period + const d1ScoreAfterStake = + await contracts.randomSamplingStorage.getEpochNodeDelegatorScore( + epoch1, + node1Id, + d1Key, + ); + const expectedD1ScoreIncrement = calculateExpectedDelegatorScore( + toTRAC(10_000), + nodeScorePerStakeAfter1, + d1LastSettledNodeScorePerStake, + ); + const expectedD1Score = d1ScoreBeforeStake + expectedD1ScoreIncrement; + + console.log(` 🧮 Delegator1 score settlement verification:`); + console.log( + ` ✅ Expected: ${expectedD1Score}, Actual: ${d1ScoreAfterStake}`, + ); + expect(d1ScoreAfterStake).to.equal( + expectedD1Score, + 'Delegator1 score settlement mismatch', + ); + + // ================================================================================================================ + // STEP 6: Node1 submits second proof + // ================================================================================================================ + console.log(`\n🔬 STEP 6: Node1 submits second proof`); + + await advanceToNextProofingPeriod(contracts); + const { + nodeScore: scoreAfter2, + nodeScorePerStake: nodeScorePerStakeAfter2, + } = await submitProofAndVerifyScore( + node1Id, + accounts.node1, + contracts, + epoch1, + totalStakeAfterStep5, + ); + + expect(scoreAfter2).to.be.gt( + scoreAfter1, + 'Second proof should increase total score', + ); + expect(nodeScorePerStakeAfter2).to.be.gt( + nodeScorePerStakeAfter1, + 'Score per stake should increase', + ); + + // ================================================================================================================ + // ADVANCE TO NEXT EPOCH AND FINALIZE + // ================================================================================================================ + console.log(`\n⏭️ Advancing to next epoch and finalizing...`); + + const timeUntilNextEpoch = await contracts.chronos.timeUntilNextEpoch(); + await time.increase(timeUntilNextEpoch + 1n); + const epoch2 = await contracts.chronos.getCurrentEpoch(); + console.log(` ✅ Advanced to epoch ${epoch2}`); + + // Create another KC to trigger epoch finalization + await createKnowledgeCollection( + accounts.kcCreator, + accounts.node1, + Number(node1Id), + receivingNodes, + receivingNodesIdentityIds, + { KnowledgeCollection: contracts.kc, Token: contracts.token }, + merkleRoot, + 'dummy-op-id-2', + 1, // holders + chunkSize * 5, // byteSize - use multiple of chunkSize + 1, // replicas + toTRAC(10), // small fee for finalization + ); + + expect(await contracts.epochStorage.lastFinalizedEpoch(1)).to.be.gte( + epoch1, + ); + console.log(` ✅ Epoch ${epoch1} finalized`); + + // ================================================================================================================ + // STEP 7: Delegator1 claims rewards with detailed verification + // ================================================================================================================ + console.log(`\n💰 STEP 7: Delegator1 claims rewards for epoch ${epoch1}`); + + const d1StakeBaseBefore = + await contracts.stakingStorage.getDelegatorStakeBase(node1Id, d1Key); + + // Get node score + const nodeFinalScore = + await contracts.randomSamplingStorage.getNodeEpochScore(epoch1, node1Id); + const netNodeRewards = await contracts.stakingKPI.getNetNodeRewards( + node1Id, + epoch1, + ); + + const epocRewardsPool = await contracts.epochStorage.getEpochPool( + 1, + epoch1, + ); + expect(netNodeRewards).to.equal(epocRewardsPool); + + console.log(` 🧮 Reward calculation verification:`); + console.log(` 📊 Node1 final score: ${nodeFinalScore}`); + console.log( + ` 💎 Net delegator rewards: ${ethers.formatUnits(netNodeRewards, 18)} TRAC should be equal to epoch rewards pool: ${ethers.formatUnits(epocRewardsPool, 18)} TRAC`, + ); + + // Claim rewards + await contracts.staking + .connect(accounts.delegator1) + .claimDelegatorRewards(node1Id, epoch1, accounts.delegator1.address); + + const d1FinalScore = + await contracts.randomSamplingStorage.getEpochNodeDelegatorScore( + epoch1, + node1Id, + d1Key, + ); + + // Calculate expected reward: (delegator_score / node_score) * available_rewards + const expectedReward = (d1FinalScore * netNodeRewards) / nodeFinalScore; + + console.log(` 📊 Delegator1 final score: ${d1FinalScore}`); + console.log( + ` 💰 Expected reward for Delegator1: ${ethers.formatUnits(expectedReward, 18)} TRAC`, + ); + + const d1StakeBaseAfter = + await contracts.stakingStorage.getDelegatorStakeBase(node1Id, d1Key); + const d1LastClaimedEpoch = + await contracts.delegatorsInfo.getLastClaimedEpoch( + node1Id, + accounts.delegator1.address, + ); + + // Verify reward was restaked (since gap is only 1 epoch) + const actualReward = d1StakeBaseAfter - d1StakeBaseBefore; + console.log( + ` ✅ Actual reward for Delegator1: ${ethers.formatUnits(actualReward, 18)} TRAC`, + ); + + // TODO: Fix manual reward calculation - delegator accumulates score across multiple proof periods + // The actual reward is higher because delegator1 earned score in both periods: + // Period 1: 10k stake * score_per_stake_1 + // Period 2: 20k stake * (score_per_stake_2 - score_per_stake_1) + console.log( + ` 📝 Note: Manual calculation needs to account for multi-period accumulation`, + ); + expect(actualReward).to.equal( + expectedReward, + 'Reward should equal expected calculation', + ); + expect(d1LastClaimedEpoch).to.equal( + epoch1, + 'Last claimed epoch not updated', + ); + + // Verify other delegators haven't claimed yet + expect( + await contracts.delegatorsInfo.getLastClaimedEpoch( + node1Id, + accounts.delegator2.address, + ), + ).to.equal(epoch1 - 1n); + expect( + await contracts.delegatorsInfo.getLastClaimedEpoch( + node1Id, + accounts.delegator3.address, + ), + ).to.equal(epoch1 - 1n); + + // ================================================================================================================ + // FINAL VERIFICATION: Test completed successfully + // ================================================================================================================ + console.log( + `\n✨ STEPS 1-7 COMPLETED SUCCESSFULLY WITH FULL VERIFICATION ✨`, + ); + console.log( + `📈 Final Node1 total stake: ${ethers.formatUnits(await contracts.stakingStorage.getNodeStake(node1Id), 18)} TRAC`, + ); + console.log( + `👤 Final Delegator1 stake: ${ethers.formatUnits(await contracts.stakingStorage.getDelegatorStakeBase(node1Id, d1Key), 18)} TRAC`, + ); + console.log( + `👤 Final Delegator2 stake: ${ethers.formatUnits(await contracts.stakingStorage.getDelegatorStakeBase(node1Id, d2Key), 18)} TRAC`, + ); + console.log( + `👤 Final Delegator3 stake: ${ethers.formatUnits(await contracts.stakingStorage.getDelegatorStakeBase(node1Id, d3Key), 18)} TRAC`, + ); + + // Key verifications completed: + // ✅ 1. Delegators can stake on a node + // ✅ 2. Node can submit proofs and accumulate score (with manual verification) + // ✅ 3. Delegator scores are properly settled when additional stakes are made (with manual verification) + // ✅ 4. Epochs can be finalized + // ✅ 5. Delegators can claim rewards based on their proportional score (with manual verification) + // ✅ 6. Rewards are auto-staked when epoch gap ≤ 1 + // ✅ 7. All score calculations match manual computations + }); + + /****************************************************************************************** + * Steps 8 → 14 (continues from the chain state left after Step 7) * + ******************************************************************************************/ + + it('Should execute steps 8-14 with detailed score calculations and verification', async function () { + /* Epoch markers */ + const currentEpoch = await contracts.chronos.getCurrentEpoch(); // == 2 + const previousEpoch = currentEpoch - 1n; // == 1 + + /********************************************************************** + * STEP 8 – Delegator2 claims rewards for previousEpoch * + **********************************************************************/ + console.log( + `\n💰 STEP 8: Delegator2 claims rewards for epoch ${previousEpoch}`, + ); + + const d2BaseBefore = await contracts.stakingStorage.getDelegatorStakeBase( + node1Id, + d2Key, + ); + + const nodeScorePrev = + await contracts.randomSamplingStorage.getNodeEpochScore( + previousEpoch, + node1Id, + ); + const netRewardsPrev = await contracts.stakingKPI.getNetNodeRewards( + node1Id, + previousEpoch, + ); + + await contracts.staking + .connect(accounts.delegator2) + .claimDelegatorRewards( + node1Id, + previousEpoch, + accounts.delegator2.address, + ); + + const d2ScorePrev = + await contracts.randomSamplingStorage.getEpochNodeDelegatorScore( + previousEpoch, + node1Id, + d2Key, + ); + const d2ExpectedReward = (d2ScorePrev * netRewardsPrev) / nodeScorePrev; + + const d2BaseAfter = await contracts.stakingStorage.getDelegatorStakeBase( + node1Id, + d2Key, + ); + const d2ActualReward = d2BaseAfter - d2BaseBefore; + + console.log( + ` ✅ D2 staked reward ${ethers.formatUnits(d2ActualReward, 18)} TRAC (expected ${ethers.formatUnits( + d2ExpectedReward, + 18, + )})`, + ); + expect(d2ActualReward).to.equal(d2ExpectedReward); + + const expectedDelegatorRewards = + await contracts.stakingKPI.getDelegatorReward( + node1Id, + previousEpoch, + accounts.delegator2.address, + ); + console.log( + ` ✅ Expected delegator rewards from StakingKPI: ${ethers.formatUnits(expectedDelegatorRewards, 18)} TRAC`, + ); + expect(d2ActualReward).to.equal(expectedDelegatorRewards); + + await epochRewardsPoolPrecisionLoss( + contracts, + previousEpoch, + netRewardsPrev, + (await contracts.stakingKPI.getDelegatorReward( + node1Id, + previousEpoch, + accounts.delegator1.address, + )) + + d2ActualReward + + (await contracts.stakingKPI.getDelegatorReward( + node1Id, + previousEpoch, + accounts.delegator3.address, + )), + ); + + /********************************************************************** + * STEP 9 – Delegator3 attempts withdrawal before claim → revert * + **********************************************************************/ + console.log( + '\n⛔ STEP 9: Delegator3 withdrawal should revert because they did not claim rewards for all previous epochs', + ); + + await expect( + contracts.staking + .connect(accounts.delegator3) + .requestWithdrawal(node1Id, ethers.parseUnits('5000', 18)), + ).to.be.revertedWith( + 'Must claim the previous epoch rewards before changing stake', + ); + console.log(' ✅ revert received as expected'); + + /********************************************************************** + * STEP 10 – Node1 submits first proof in currentEpoch * + **********************************************************************/ + console.log( + `\n🔬 STEP 10: Node1 submits first proof in epoch ${currentEpoch}`, + ); + + /* move to the next proof-period so the challenge is fresh */ + await advanceToNextProofingPeriod(contracts); + + /* --- BEFORE snapshot ------------------------------------------------ */ + const stakeBeforeProof = + await contracts.stakingStorage.getNodeStake(node1Id); + const scoreBeforeProof = + await contracts.randomSamplingStorage.getNodeEpochScore( + currentEpoch, + node1Id, + ); + const perStakeBefore = + await contracts.randomSamplingStorage.getNodeEpochScorePerStake( + currentEpoch, + node1Id, + ); + + console.log( + ` ℹ️ before-proof: score=${scoreBeforeProof}, nodeScorePerStake=${perStakeBefore}, stake=${ethers.formatUnits(stakeBeforeProof, 18)} TRAC`, + ); + + /* --- Submit proof & verify internal math --------------------------- */ + await submitProofAndVerifyScore( + node1Id, + accounts.node1, + contracts, + currentEpoch, + stakeBeforeProof, + ); + + /* --- AFTER snapshot ------------------------------------------------- */ + const scoreAfterProof = + await contracts.randomSamplingStorage.getNodeEpochScore( + currentEpoch, + node1Id, + ); + const perStakeAfter = + await contracts.randomSamplingStorage.getNodeEpochScorePerStake( + currentEpoch, + node1Id, + ); + + /* --- Assertions ----------------------------------------------------- */ + expect(scoreAfterProof).to.be.gt( + scoreBeforeProof, + 'Node epoch score must increase after proof', + ); + expect(perStakeAfter).to.be.gt( + perStakeBefore, + 'Score-per-stake must increase after proof', + ); + + console.log( + ` ✅ score increased: ${scoreBeforeProof} → ${scoreAfterProof}; ` + + `nodeScorePerStake increased: ${perStakeBefore} → ${perStakeAfter}`, + ); + + /********************************************************************** + * STEP 11 – Delegator 2 requests withdrawal of 10 000 TRAC * + **********************************************************************/ + console.log('\n📤 STEP 11: Delegator2 requests withdrawal of 10 000 TRAC'); + + /* ---------- BEFORE snapshot -------------------------------------- */ + const d2StakeBaseBefore = + await contracts.stakingStorage.getDelegatorStakeBase(node1Id, d2Key); + const nodeStakeBefore11 = + await contracts.stakingStorage.getNodeStake(node1Id); + + const scorePerStakeCur = + await contracts.randomSamplingStorage.getNodeEpochScorePerStake( + currentEpoch, + node1Id, + ); + const d2LastSettledBefore = + await contracts.randomSamplingStorage.getDelegatorLastSettledNodeEpochScorePerStake( + currentEpoch, + node1Id, + d2Key, + ); + const d2ScoreBefore = + await contracts.randomSamplingStorage.getEpochNodeDelegatorScore( + currentEpoch, + node1Id, + d2Key, + ); + + /* how much score should be settled by _prepareForStakeChange() */ + const expectedScoreIncrement = calculateExpectedDelegatorScore( + d2StakeBaseBefore, // stake before withdrawal + scorePerStakeCur, + d2LastSettledBefore, + ); + + /* ---------- perform withdrawal request --------------------------- */ + await contracts.staking + .connect(accounts.delegator2) + .requestWithdrawal(node1Id, ethers.parseUnits('10000', 18)); + + /* ---------- AFTER snapshot --------------------------------------- */ + const d2StakeBaseAfter = + await contracts.stakingStorage.getDelegatorStakeBase(node1Id, d2Key); + const nodeStakeAfter11 = + await contracts.stakingStorage.getNodeStake(node1Id); + + const d2ScoreAfter = + await contracts.randomSamplingStorage.getEpochNodeDelegatorScore( + currentEpoch, + node1Id, + d2Key, + ); + const d2LastSettledAfter = + await contracts.randomSamplingStorage.getDelegatorLastSettledNodeEpochScorePerStake( + currentEpoch, + node1Id, + d2Key, + ); + + const [withdrawAmount] = + await contracts.stakingStorage.getDelegatorWithdrawalRequest( + node1Id, + d2Key, + ); + + /* ---------- Assertions ------------------------------------------- */ + expect(withdrawAmount).to.equal( + ethers.parseUnits('10000', 18), + 'withdrawal request amount', + ); + expect(nodeStakeAfter11).to.equal( + nodeStakeBefore11 - ethers.parseUnits('10000', 18), + 'node total stake should fall by 10 000 TRAC', + ); + expect(d2StakeBaseAfter).to.equal( + d2StakeBaseBefore - ethers.parseUnits('10000', 18), + 'delegator base stake should fall by 10 000 TRAC', + ); + expect(d2ScoreAfter).to.equal( + d2ScoreBefore + expectedScoreIncrement, + 'delegator score must be lazily settled before stake change', + ); + expect(d2LastSettledAfter).to.equal( + scorePerStakeCur, + 'lastSettled index must be bumped to current nodeScorePerStake', + ); + + console.log( + ` ✅ withdrawal request stored (${ethers.formatUnits(withdrawAmount, 18)} TRAC)`, + ); + console.log( + ` ✅ node stake decreased: ${ethers.formatUnits(nodeStakeBefore11, 18)} → ${ethers.formatUnits(nodeStakeAfter11, 18)} TRAC`, + ); + console.log( + ` ✅ D2 stakeBase decreased: ${ethers.formatUnits(d2StakeBaseBefore, 18)} → ${ethers.formatUnits(d2StakeBaseAfter, 18)} TRAC`, + ); + console.log( + ` ✅ D2 epochScore increased: ${d2ScoreBefore} → ${d2ScoreAfter} (settled +${expectedScoreIncrement})`, + ); + + /********************************************************************** + * STEP 12 – Node1 submits **second** proof in currentEpoch * + **********************************************************************/ + console.log( + `\n🔬 STEP 12: Node1 submits second proof in epoch ${currentEpoch}`, + ); + + /* --------------------------------------------------------------- + * 1️⃣ Shift to new proof-period so challenge is valid + * ------------------------------------------------------------- */ + await advanceToNextProofingPeriod(contracts); + + /* --------------------------------------------------------------- + * 2️⃣ BEFORE snapshot + * ------------------------------------------------------------- */ + const nodeStakeBefore12 = + await contracts.stakingStorage.getNodeStake(node1Id); // ≈ 62 100 TRAC + const nodeScoreBefore12 = + await contracts.randomSamplingStorage.getNodeEpochScore( + currentEpoch, + node1Id, + ); + const perStakeBefore12 = + await contracts.randomSamplingStorage.getNodeEpochScorePerStake( + currentEpoch, + node1Id, + ); + const allNodesScoreBefore12 = + await contracts.randomSamplingStorage.getAllNodesEpochScore(currentEpoch); + + console.log( + ` ℹ️ before-proof: nodeScore=${nodeScoreBefore12}, nodeScorePerStake=${perStakeBefore12}, ` + + `allNodesScore=${allNodesScoreBefore12}, nodeStake=${ethers.formatUnits(nodeStakeBefore12, 18)} TRAC`, + ); + + /* --------------------------------------------------------------- + * 3️⃣ Perform proof + builtin math-check + * ------------------------------------------------------------- */ + await submitProofAndVerifyScore( + node1Id, + accounts.node1, + contracts, + currentEpoch, + nodeStakeBefore12, + ); + + /* --------------------------------------------------------------- + * 4️⃣ AFTER snapshot + * ------------------------------------------------------------- */ + const nodeStakeAfter12 = + await contracts.stakingStorage.getNodeStake(node1Id); + const nodeScoreAfter12 = + await contracts.randomSamplingStorage.getNodeEpochScore( + currentEpoch, + node1Id, + ); + const perStakeAfter12 = + await contracts.randomSamplingStorage.getNodeEpochScorePerStake( + currentEpoch, + node1Id, + ); + const allNodesScoreAfter12 = + await contracts.randomSamplingStorage.getAllNodesEpochScore(currentEpoch); + + /* --------------------------------------------------------------- + * 5️⃣ Assertions – strict before/after checks + * ------------------------------------------------------------- */ + expect(nodeStakeAfter12).to.equal( + nodeStakeBefore12, + 'Node stake must not change when only submitting a proof', + ); + + expect(nodeScoreAfter12).to.be.gt( + nodeScoreBefore12, + 'Node epoch score must increase after second proof', + ); + + expect(perStakeAfter12).to.be.gt( + perStakeBefore12, + 'Score-per-stake must increase after second proof', + ); + + expect(allNodesScoreAfter12).to.be.gt( + allNodesScoreBefore12, + 'Global all-nodes score must increase after proof', + ); + + console.log( + ` ✅ nodeScore: ${nodeScoreBefore12} → ${nodeScoreAfter12}\n` + + ` ✅ scorePerStake: ${perStakeBefore12} → ${perStakeAfter12}\n`, + ); + + /********************************************************************** + * STEP 13 – Delegator 1 claims rewards for epoch `claimEpoch` + * (diagram "Delegator1 claims reward for epoch 2") + **********************************************************************/ + + console.log('\n💰 STEP 13: Delegator1 claims rewards for previous epoch'); + + /* --------------------------------------------------------------- + * 1️⃣ Finalise currentEpoch so rewards become claimable + * – we need to be in epoch 3 and claim for epoch 2 + * ------------------------------------------------------------- */ + const timeUntilNextEpoch = await contracts.chronos.timeUntilNextEpoch(); + await time.increase(timeUntilNextEpoch + 1n); + + const epochAfterFinalize = await contracts.chronos.getCurrentEpoch(); // == currentEpoch + 1 + const claimEpoch = epochAfterFinalize - 1n; // epoch we are claiming for + + /* one more dummy KC → triggers epoch finalisation */ + await createKnowledgeCollection( + accounts.kcCreator, + accounts.node1, + Number(node1Id), + receivingNodes, + receivingNodesIdentityIds, + { KnowledgeCollection: contracts.kc, Token: contracts.token }, + merkleRoot, + 'finalise-epoch', + 10, // holders + chunkSize * 15, // byteSize - use multiple of chunkSize for proper chunk generation + 10, // replicas + toTRAC(50_000), // <-- epoch fee identical to the diagram + ); + + /* epoch really finalised? */ + expect(await contracts.epochStorage.lastFinalizedEpoch(1)).to.be.gte( + claimEpoch, + 'Epoch must be finalised before claiming', + ); + + /* --------------------------------------------------------------- + * 2️⃣ BEFORE snapshot – **manual** reward calculation + * ------------------------------------------------------------- */ + const SCALE18 = ethers.parseUnits('1', 18); + + const d1BaseBefore = await contracts.stakingStorage.getDelegatorStakeBase( + node1Id, + d1Key, + ); + const nodeScore = await contracts.randomSamplingStorage.getNodeEpochScore( + claimEpoch, + node1Id, + ); + const perStake = + await contracts.randomSamplingStorage.getNodeEpochScorePerStake( + claimEpoch, + node1Id, + ); + const d1LastSettled = + await contracts.randomSamplingStorage.getDelegatorLastSettledNodeEpochScorePerStake( + claimEpoch, + node1Id, + d1Key, + ); + const d1StoredScore = + await contracts.randomSamplingStorage.getEpochNodeDelegatorScore( + claimEpoch, + node1Id, + d1Key, + ); + + /* "lazy-settle" delta that _will_ be written inside claim() */ + const d1SettleDiff = perStake - d1LastSettled; + const earnedScore = (BigInt(d1BaseBefore) * d1SettleDiff) / SCALE18; + + /* total score that delegator should have after settle */ + const d1TotalScore = d1StoredScore + earnedScore; + + /* net pool for delegators that epoch */ + const netDelegatorRewards13 = await contracts.stakingKPI.getNetNodeRewards( + node1Id, + claimEpoch, + ); + + /* expected TRAC reward (18 decimals) */ + const expectedReward13 = + nodeScore === 0n + ? 0n + : (d1TotalScore * netDelegatorRewards13) / nodeScore; + + console.log( + ` ℹ️ claimEpoch=${claimEpoch}, nodeScore=${nodeScore}, d1Score(before)=${d1StoredScore}, earned score=${earnedScore}, pool=${ethers.formatUnits(netDelegatorRewards13, 18)} TRAC`, + ); + console.log( + ` 🔢 nodeScore = ${nodeScore}`, + `\n 🔢 d1StoredScore = ${d1StoredScore}`, + `\n 🔢 d1EarnedScore = ${earnedScore}`, + ); + + /* --------------------------------------------------------------- + * 3️⃣ Perform claim + * ------------------------------------------------------------- */ + await contracts.staking + .connect(accounts.delegator1) + .claimDelegatorRewards(node1Id, claimEpoch, accounts.delegator1.address); + + /* --------------------------------------------------------------- + * 4️⃣ AFTER snapshot + * ------------------------------------------------------------- */ + const d1BaseAfter = await contracts.stakingStorage.getDelegatorStakeBase( + node1Id, + d1Key, + ); + const nodeStakeAfter13 = + await contracts.stakingStorage.getNodeStake(node1Id); + const d1LastClaimed13 = await contracts.delegatorsInfo.getLastClaimedEpoch( + node1Id, + accounts.delegator1.address, + ); + + /* --------------------------------------------------------------- + * 5️⃣ Assertions + * ------------------------------------------------------------- */ + const actualReward13 = d1BaseAfter - d1BaseBefore; + const expectedDelegatorRewardKPI = + await contracts.stakingKPI.getDelegatorReward( + node1Id, + claimEpoch, + accounts.delegator1.address, + ); + + expect(actualReward13, 'restaked reward amount').to.equal(expectedReward13); + expect(expectedDelegatorRewardKPI).to.equal(actualReward13); + expect(d1LastClaimed13, 'lastClaimedEpoch update').to.equal(claimEpoch); + expect(nodeStakeAfter13).to.equal( + nodeStakeAfter12 + actualReward13, + 'node total stake must include newly auto-staked reward', + ); + console.log( + ` 🧮 EXPECTED reward = ${ethers.formatUnits(expectedReward13, 18)} TRAC`, + `\n ✅ ACTUAL reward = ${ethers.formatUnits(actualReward13, 18)} TRAC`, + ); + + /* nice console output */ + console.log( + ` ✅ D1 reward ${ethers.formatUnits(actualReward13, 18)} TRAC ` + + `staked → new base ${ethers.formatUnits(d1BaseAfter, 18)} TRAC`, + ); + console.log(` ✅ lastClaimedEpoch set to ${d1LastClaimed13}\n`); + + /********************************************************************** + * STEP 14 – Delegator 2 claims rewards for epoch `claimEpoch` (= 2) + **********************************************************************/ + + console.log( + '\n💰 STEP 14: Delegator2 claims rewards for epoch', + claimEpoch, + ); + + /* --------------------------------------------------------------- + * 1️⃣ Pre-claim snapshot + * ------------------------------------------------------------- */ + const d2BaseBefore14 = await contracts.stakingStorage.getDelegatorStakeBase( + node1Id, + d2Key, + ); + const d2LastClaimed14 = await contracts.delegatorsInfo.getLastClaimedEpoch( + node1Id, + accounts.delegator2.address, + ); + + // Must be claiming the next unclaimed epoch (1 → 2) + expect(d2LastClaimed14).to.equal( + claimEpoch - 1n, + 'Delegator2 is not claiming the oldest pending epoch', + ); + + /* --------------------------------------------------------------- + * 2️⃣ Manual reward calculation + * ------------------------------------------------------------- */ + const nodeScoreClaim = + await contracts.randomSamplingStorage.getNodeEpochScore( + claimEpoch, + node1Id, + ); + const perStakeClaim = + await contracts.randomSamplingStorage.getNodeEpochScorePerStake( + claimEpoch, + node1Id, + ); + const d2LastSettledClaim = + await contracts.randomSamplingStorage.getDelegatorLastSettledNodeEpochScorePerStake( + claimEpoch, + node1Id, + d2Key, + ); + const d2StoredScore = + await contracts.randomSamplingStorage.getEpochNodeDelegatorScore( + claimEpoch, + node1Id, + d2Key, + ); + + /* "lazy-settle" part to be added inside claim() */ + const d2SettleDiff = perStakeClaim - d2LastSettledClaim; + const d2EarnedScore = (d2BaseBefore14 * d2SettleDiff) / SCALE18; + const d2TotalScore = d2StoredScore + d2EarnedScore; + + const netDelegatorRewards14 = await contracts.stakingKPI.getNetNodeRewards( + node1Id, + claimEpoch, + ); + + const expectedReward14 = + nodeScoreClaim === 0n + ? 0n + : (d2TotalScore * netDelegatorRewards14) / nodeScoreClaim; + + console.log( + ` 🔢 nodeScore = ${nodeScoreClaim}`, + `\n 🔢 d2StoredScore = ${d2StoredScore}`, + `\n 🔢 d2EarnedScore = ${d2EarnedScore}`, + `pool=${ethers.formatUnits(netDelegatorRewards14, 18)} TRAC`, + ); + + /* --------------------------------------------------------------- + * 3️⃣ Claim transaction + * ------------------------------------------------------------- */ + await contracts.staking + .connect(accounts.delegator2) + .claimDelegatorRewards(node1Id, claimEpoch, accounts.delegator2.address); + + /* --------------------------------------------------------------- + * 4️⃣ Post-claim snapshot + * ------------------------------------------------------------- */ + const d2BaseAfter14 = await contracts.stakingStorage.getDelegatorStakeBase( + node1Id, + d2Key, + ); + const d2LastClaimedAfter = + await contracts.delegatorsInfo.getLastClaimedEpoch( + node1Id, + accounts.delegator2.address, + ); + const actualReward14 = d2BaseAfter14 - d2BaseBefore14; + const expectedDelegatorRewardKPI14 = + await contracts.stakingKPI.getDelegatorReward( + node1Id, + claimEpoch, + accounts.delegator2.address, + ); + + console.log( + ` 🧮 EXPECTED reward = ${ethers.formatUnits(expectedReward14, 18)} TRAC`, + `\n ✅ ACTUAL reward = ${ethers.formatUnits(actualReward14, 18)} TRAC`, + ); + + /* --------------------------------------------------------------- + * 5️⃣ Assertions + * ------------------------------------------------------------- */ + expect(actualReward14, 'staked reward mismatch').to.equal(expectedReward14); + expect(expectedDelegatorRewardKPI14).to.equal(actualReward14); + expect(d2LastClaimedAfter, 'lastClaimedEpoch not updated').to.equal( + claimEpoch, + ); + + // Node stake should grow by the auto-staked reward + const nodeStakeAfter14 = + await contracts.stakingStorage.getNodeStake(node1Id); + expect(nodeStakeAfter14).to.equal( + nodeStakeAfter13 + actualReward14, + 'Node total stake did not include Delegator2 reward', + ); + + // Pending withdrawal request must stay untouched + const [withdrawPending] = + await contracts.stakingStorage.getDelegatorWithdrawalRequest( + node1Id, + d2Key, + ); + expect(withdrawPending).to.equal( + ethers.parseUnits('10000', 18), + 'Withdrawal request amount changed after claim', + ); + + console.log( + ` ✅ D2 reward ${ethers.formatUnits(actualReward14, 18)} TRAC ` + + `restaked → new base ${ethers.formatUnits(d2BaseAfter14, 18)} TRAC`, + ); + console.log(` ✅ lastClaimedEpoch set to ${d2LastClaimedAfter}\n`); + console.log('\n✨ Steps 8-14 completed – ready for next tests ✨\n'); + + await epochRewardsPoolPrecisionLoss( + contracts, + claimEpoch, + netDelegatorRewards14, + actualReward13 + + actualReward14 + + (await contracts.stakingKPI.getDelegatorReward( + node1Id, + claimEpoch, + accounts.delegator3.address, + )), + ); + }); + + /****************************************************************************************** + * Steps 15 – 21 (continue from the chain-state left after Step 14) * + ******************************************************************************************/ + it('Should execute steps 15-23 with detailed score calculations and verification', async function () { + /* helpers already in scope from previous tests */ + const toTRAC18 = (x: number | string) => + ethers.parseUnits(x.toString(), 18); + + const TEN_K = ethers.parseUnits('10000', TOKEN_DECIMALS); + + /********************************************************************** + * STEP 15 – Delegator 2 finalises withdrawal of 10 000 TRAC + **********************************************************************/ + console.log('\n📤 STEP 15: Delegator2 finalises withdrawal of 10 000 TRAC'); + + /* 1️⃣ Make sure the request exists and the delay has passed */ + const [pending, , releaseTs] = + await contracts.stakingStorage.getDelegatorWithdrawalRequest( + node1Id, + d2Key, + ); + + expect(pending, 'pending amount mismatch').to.equal(TEN_K); + + const now = BigInt(await time.latest()); + if (now < releaseTs) await time.increase(releaseTs - now + 1n); + + /* 2️⃣ Snapshot BEFORE */ + const balBefore = await contracts.token.balanceOf(accounts.delegator2); + const nodeStakeBefore15 = + await contracts.stakingStorage.getNodeStake(node1Id); + + console.log( + ` 🪙 Wallet BEFORE: ${ethers.formatUnits(balBefore, TOKEN_DECIMALS)} TRAC`, + ); + + /* 3️⃣ Finalise */ + await contracts.staking + .connect(accounts.delegator2) + .finalizeWithdrawal(node1Id); + + /* 4️⃣ Snapshot AFTER */ + const balAfter = await contracts.token.balanceOf(accounts.delegator2); + const nodeStakeAfter15 = + await contracts.stakingStorage.getNodeStake(node1Id); + const [reqAfter] = + await contracts.stakingStorage.getDelegatorWithdrawalRequest( + node1Id, + d2Key, + ); + + /* 5️⃣ Assertions */ + expect(balAfter - balBefore, 'wallet diff').to.equal(TEN_K); // ← BigInt diff + expect(nodeStakeAfter15, 'node stake already reduced in step 11').to.equal( + nodeStakeBefore15, + ); + expect(reqAfter, 'withdrawal request should be cleared').to.equal(0n); + + console.log( + ` 🪙 Wallet AFTER : ${ethers.formatUnits(balAfter, TOKEN_DECIMALS)} TRAC`, + `\n ✅ 10 000 TRAC transferred successfully`, + ); + + /********************************************************************** + * STEP 16 – Delegator 3 tries to stake extra 5 000 TRAC (must revert) * + **********************************************************************/ + console.log( + '\n⛔ STEP 16: Delegator3 attempts to stake 5 000 TRAC – should revert', + ); + + await contracts.token + .connect(accounts.delegator3) + .approve(await contracts.staking.getAddress(), toTRAC18(5_000)); + + await expect( + contracts.staking + .connect(accounts.delegator3) + .stake(node1Id, toTRAC18(5_000)), + ).to.be.revertedWith( + 'Must claim all previous epoch rewards before changing stake', + ); + + console.log( + ' ✅ Revert received as expected – Delegator3 must claim epochs 2 & 3 first', + ); + + /********************************************************************** + * STEP 17 – Delegator 3 claims rewards for epoch 1 + **********************************************************************/ + console.log('\n💰 STEP 17: Delegator3 claims rewards for epoch 2'); + + const claimEpoch17 = 2n; + + const SCALE18 = ethers.parseUnits('1', 18); + + /* ── 1. Preconditions ────────────────────────────────────────────── */ + const lastClaimedBefore = + await contracts.delegatorsInfo.getLastClaimedEpoch( + node1Id, + accounts.delegator3.address, + ); + + /** + * 0 – sentinel "never claimed" (default) + * n–1 – standard "oldest un-claimed epoch" + */ + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + expect( + lastClaimedBefore === 0n || lastClaimedBefore === claimEpoch17 - 1n, + 'Delegator-3 must claim the oldest pending epoch first', + ).to.be.true; + + /* ── 2. Manual reward calculation (for assertions) ───────────────── */ + const stakeBaseBefore = + await contracts.stakingStorage.getDelegatorStakeBase(node1Id, d3Key); + + const nodeScore17 = await contracts.randomSamplingStorage.getNodeEpochScore( + claimEpoch17, + node1Id, + ); + const perStake17 = + await contracts.randomSamplingStorage.getNodeEpochScorePerStake( + claimEpoch17, + node1Id, + ); + + const lastSettled17 = + await contracts.randomSamplingStorage.getDelegatorLastSettledNodeEpochScorePerStake( + claimEpoch17, + node1Id, + d3Key, + ); + const storedScore17 = + await contracts.randomSamplingStorage.getEpochNodeDelegatorScore( + claimEpoch17, + node1Id, + d3Key, + ); + + const earnedScore17 = + (stakeBaseBefore * (perStake17 - lastSettled17)) / SCALE18; + const totalScore17 = storedScore17 + earnedScore17; + + const rewardsPool17 = await contracts.stakingKPI.getNetNodeRewards( + node1Id, + claimEpoch17, + ); + + const expectedReward17 = + nodeScore17 === 0n ? 0n : (totalScore17 * rewardsPool17) / nodeScore17; + + /* ── 3. Claim transaction ────────────────────────────────────────── */ + await contracts.staking + .connect(accounts.delegator3) + .claimDelegatorRewards( + node1Id, + claimEpoch17, + accounts.delegator3.address, + ); + + /* ── 4. Post-claim checks ────────────────────────────────────────── */ + const stakeBaseAfter = await contracts.stakingStorage.getDelegatorStakeBase( + node1Id, + d3Key, + ); // must stay 30 000 + const rollingRewards = + await contracts.delegatorsInfo.getDelegatorRollingRewards( + node1Id, + accounts.delegator3.address, + ); + const lastClaimedAfter = await contracts.delegatorsInfo.getLastClaimedEpoch( + node1Id, + accounts.delegator3.address, + ); + + expect( + stakeBaseAfter, + 'stakeBase unchanged while older epochs remain', + ).to.equal(stakeBaseBefore); + expect(rollingRewards, 'rollingRewards incorrect').to.equal( + expectedReward17, + ); + expect(lastClaimedAfter, 'lastClaimedEpoch not updated').to.equal( + claimEpoch17, + ); + + console.log( + ` ✅ rollingRewards = ${ethers.formatUnits(rollingRewards, 18)} TRAC`, + `\n ✅ lastClaimedEpoch = ${lastClaimedAfter}\n`, + ); + + /********************************************************************** + * STEP 18 – Delegator 3 claims rewards for epoch 2 + * -------------------------------------------------------------------- + **********************************************************************/ + console.log('\n💰 STEP 18: Delegator3 claims rewards for epoch 3'); + + const claimEpoch18 = 3n; + + /* ── 1. PRE-CONDITIONS ──────────────────────────────────────────────── */ + const d3LastClaimedBefore18 = + await contracts.delegatorsInfo.getLastClaimedEpoch( + node1Id, + accounts.delegator3.address, + ); + + // Must be claiming the oldest pending epoch (1 → 2) + expect(d3LastClaimedBefore18).to.equal( + claimEpoch18 - 1n, + 'Delegator-3 is skipping an older unclaimed epoch', + ); + + /* ── 2. MANUAL REWARD CALCULATION ───────────────────────────────────── */ + const d3BaseBefore18 = await contracts.stakingStorage.getDelegatorStakeBase( + node1Id, + d3Key, + ); + const d3RollingBefore18 = + await contracts.delegatorsInfo.getDelegatorRollingRewards( + node1Id, + accounts.delegator3.address, + ); + + const nodeScoreEp2 = + await contracts.randomSamplingStorage.getNodeEpochScore( + claimEpoch18, + node1Id, + ); + const perStakeEp2 = + await contracts.randomSamplingStorage.getNodeEpochScorePerStake( + claimEpoch18, + node1Id, + ); + + const d3LastSettledEp2 = + await contracts.randomSamplingStorage.getDelegatorLastSettledNodeEpochScorePerStake( + claimEpoch18, + node1Id, + d3Key, + ); + const d3StoredScoreEp2 = + await contracts.randomSamplingStorage.getEpochNodeDelegatorScore( + claimEpoch18, + node1Id, + d3Key, + ); + + /* "lazy-settle" part that will be written inside claim() */ + const d3EarnedScore = + (d3BaseBefore18 * (perStakeEp2 - d3LastSettledEp2)) / SCALE18; + const d3TotalScore = d3StoredScoreEp2 + d3EarnedScore; + + const netDelegatorRewardsEp2 = await contracts.stakingKPI.getNetNodeRewards( + node1Id, + claimEpoch18, + ); + + // New reward for epoch 2 + const rewardEp2 = + nodeScoreEp2 === 0n + ? 0n + : (d3TotalScore * netDelegatorRewardsEp2) / nodeScoreEp2; + + // ► what will actually be auto-staked: + const expectedStakeIncrease18 = d3RollingBefore18 + rewardEp2; + + /* ── 3. CLAIM TRANSACTION ───────────────────────────────────────────── */ + await contracts.staking + .connect(accounts.delegator3) + .claimDelegatorRewards( + node1Id, + claimEpoch18, + accounts.delegator3.address, + ); + + /* ── 4. POST-CLAIM SNAPSHOT ─────────────────────────────────────────── */ + const d3BaseAfter18 = await contracts.stakingStorage.getDelegatorStakeBase( + node1Id, + d3Key, + ); + const d3RollingAfter18 = + await contracts.delegatorsInfo.getDelegatorRollingRewards( + node1Id, + accounts.delegator3.address, + ); + const d3LastClaimedAfter18 = + await contracts.delegatorsInfo.getLastClaimedEpoch( + node1Id, + accounts.delegator3.address, + ); + const nodeStakeAfter18 = + await contracts.stakingStorage.getNodeStake(node1Id); + + /* ── 5. ASSERTIONS ──────────────────────────────────────────────────── */ + expect( + d3BaseAfter18 - d3BaseBefore18, + 'auto-staked amount mismatch', + ).to.equal(expectedStakeIncrease18); + + expect(d3RollingAfter18, 'rollingRewards should now be 0').to.equal(0n); + + expect(d3LastClaimedAfter18, 'lastClaimedEpoch not updated').to.equal( + claimEpoch18, + ); + + // nodeStakeAfter14 must be in scope from previous step + expect(nodeStakeAfter18).to.equal( + nodeStakeAfter15 + expectedStakeIncrease18, + 'Node total stake should include D3 reward', + ); + + console.log( + ` 🧮 reward(epoch3) = ${ethers.formatUnits(rewardEp2, 18)} TRAC`, + `\n 🧮 rolling(before) = ${ethers.formatUnits(d3RollingBefore18, 18)} TRAC`, + `\n ✅ total reward = ${ethers.formatUnits(expectedStakeIncrease18, 18)} TRAC`, + ); + console.log( + ` ✅ new D3 stakeBase = ${ethers.formatUnits(d3BaseAfter18, 18)} TRAC`, + `\n ✅ rolling(after) = ${ethers.formatUnits(d3RollingAfter18, 18)} TRAC`, + `\n ✅ lastClaimedEpoch = ${d3LastClaimedAfter18}\n`, + ); + + /********************************************************************** + * STEP 19 – Delegator 3 requests withdrawal of 10 000 TRAC * + **********************************************************************/ + console.log('\n📤 STEP 19: Delegator3 requests withdrawal of 10 000 TRAC'); + + /* ---------- BEFORE snapshot -------------------------------------- */ + const d3StakeBaseBefore19 = + await contracts.stakingStorage.getDelegatorStakeBase(node1Id, d3Key); + const nodeStakeBefore19 = + await contracts.stakingStorage.getNodeStake(node1Id); + + // latest epoch (== 4) + const currentEpoch19 = await contracts.chronos.getCurrentEpoch(); + console.log(` ℹ️ current epoch = ${currentEpoch19}`); + + const scorePerStakeCur19 = + await contracts.randomSamplingStorage.getNodeEpochScorePerStake( + currentEpoch19, + node1Id, + ); + const d3LastSettledBefore19 = + await contracts.randomSamplingStorage.getDelegatorLastSettledNodeEpochScorePerStake( + currentEpoch19, + node1Id, + d3Key, + ); + const d3ScoreBefore19 = + await contracts.randomSamplingStorage.getEpochNodeDelegatorScore( + currentEpoch19, + node1Id, + d3Key, + ); + + /* how much score will be lazily settled by _prepareForStakeChange() */ + const expectedScoreInc19 = calculateExpectedDelegatorScore( + d3StakeBaseBefore19, + scorePerStakeCur19, + d3LastSettledBefore19, + ); + + /* ---------- perform withdrawal request --------------------------- */ + await contracts.staking + .connect(accounts.delegator3) + .requestWithdrawal(node1Id, TEN_K); // TEN_K = 10 000 TRAC + + /* ---------- AFTER snapshot --------------------------------------- */ + const d3StakeBaseAfter19 = + await contracts.stakingStorage.getDelegatorStakeBase(node1Id, d3Key); + const nodeStakeAfter19 = + await contracts.stakingStorage.getNodeStake(node1Id); + + const d3ScoreAfter19 = + await contracts.randomSamplingStorage.getEpochNodeDelegatorScore( + currentEpoch19, + node1Id, + d3Key, + ); + const d3LastSettledAfter19 = + await contracts.randomSamplingStorage.getDelegatorLastSettledNodeEpochScorePerStake( + currentEpoch19, + node1Id, + d3Key, + ); + + const [withdrawAmount19] = + await contracts.stakingStorage.getDelegatorWithdrawalRequest( + node1Id, + d3Key, + ); + + /* ---------- Assertions ------------------------------------------- */ + expect(withdrawAmount19).to.equal( + TEN_K, + 'withdrawal request amount mismatch', + ); + + expect(nodeStakeAfter19).to.equal( + nodeStakeBefore19 - TEN_K, + 'node total stake should fall by 10 000 TRAC', + ); + expect(d3StakeBaseAfter19).to.equal( + d3StakeBaseBefore19 - TEN_K, + 'delegator base stake should fall by 10 000 TRAC', + ); + + expect(d3ScoreAfter19).to.equal( + d3ScoreBefore19 + expectedScoreInc19, + 'delegator score must be lazily settled before stake change', + ); + expect(d3LastSettledAfter19).to.equal( + scorePerStakeCur19, + 'lastSettled index must be bumped to current nodeScorePerStake', + ); + + /* ---------- Console summary -------------------------------------- */ + console.log( + ` ✅ withdrawal request stored (${ethers.formatUnits(withdrawAmount19, 18)} TRAC)`, + ); + console.log( + ` ✅ node stake ${ethers.formatUnits(nodeStakeBefore19, 18)} → ${ethers.formatUnits(nodeStakeAfter19, 18)} TRAC`, + ); + console.log( + ` ✅ D3 stakeBase ${ethers.formatUnits(d3StakeBaseBefore19, 18)} → ${ethers.formatUnits(d3StakeBaseAfter19, 18)} TRAC`, + ); + console.log( + ` ✅ D3 epoch-score ${d3ScoreBefore19} → ${d3ScoreAfter19} (settled +${expectedScoreInc19})`, + ); + + /********************************************************************** + * STEP 20 – Jump to epoch-5 ➜ finalise withdrawal of 10 000 TRAC + **********************************************************************/ + console.log( + '\n⏭️ STEP 20: Node 1 Submit Proof for epoch-4, Jump to epoch-5 so epoch-4 is finalised and D3 finalises withdrawal', + ); + + await advanceToNextProofingPeriod(contracts); + + // 2. take a stake snapshot (needed by the helper that double-checks maths) + const stakeSnapshot = await contracts.stakingStorage.getNodeStake(node1Id); + + // 3. have node-1 submit one more proof for *epoch-4* + await submitProofAndVerifyScore( + node1Id, + accounts.node1, + contracts, + currentEpoch19, // <- epoch-4 + stakeSnapshot, + ); + + /* 1️⃣ → epoch-5 */ + const ttn = await contracts.chronos.timeUntilNextEpoch(); + await time.increase(ttn + 1n); // epoch 5 + + await createKnowledgeCollection( + accounts.kcCreator, + accounts.node1, + Number(node1Id), + receivingNodes, + receivingNodesIdentityIds, + { KnowledgeCollection: contracts.kc, Token: contracts.token }, + merkleRoot, + 'finalise-epoch4', + 1, // holders + chunkSize * 2, // byteSize - use multiple of chunkSize for proper chunk generation + 1, // replicas + toTRAC(1), // + ); + + expect(await contracts.epochStorage.lastFinalizedEpoch(1)).to.equal( + 4n, + 'Epoch-4 should now be finalised', + ); + + const epoch5 = await contracts.chronos.getCurrentEpoch(); // == 5 + console.log(` ✅ Now in epoch ${epoch5} (epoch-4 finalised)`); + expect(epoch5).to.equal(5n); + + const epoc4 = 4n; + + const netNodeRewards = await contracts.stakingKPI.getNetNodeRewards( + node1Id, + epoc4, + ); + const allDelegatorsRewards = + (await contracts.stakingKPI.getDelegatorReward( + node1Id, + epoc4, + accounts.delegator1.address, + )) + + (await contracts.stakingKPI.getDelegatorReward( + node1Id, + epoc4, + accounts.delegator2.address, + )) + + (await contracts.stakingKPI.getDelegatorReward( + node1Id, + epoc4, + accounts.delegator3.address, + )); + + await epochRewardsPoolPrecisionLoss( + contracts, + epoc4, + netNodeRewards, + allDelegatorsRewards, + ); + + /* 3️⃣ Make sure the withdrawal delay elapsed */ + const [pending20, , releaseTs20] = + await contracts.stakingStorage.getDelegatorWithdrawalRequest( + node1Id, + d3Key, + ); + + expect(pending20).to.equal(TEN_K, 'pending amount mismatch'); + + const now20 = BigInt(await time.latest()); + if (now20 < releaseTs20) await time.increase(releaseTs20 - now20 + 1n); + + /* 4️⃣ BEFORE snapshot */ + const balBefore20 = await contracts.token.balanceOf(accounts.delegator3); + const nodeStakeBefore20 = + await contracts.stakingStorage.getNodeStake(node1Id); + + /* 5️⃣ Finalise withdrawal */ + await contracts.staking + .connect(accounts.delegator3) + .finalizeWithdrawal(node1Id); + + /* 6️⃣ AFTER snapshot & asserts */ + const balAfter20 = await contracts.token.balanceOf(accounts.delegator3); + const nodeStakeAfter20 = + await contracts.stakingStorage.getNodeStake(node1Id); + const [reqAfter20] = + await contracts.stakingStorage.getDelegatorWithdrawalRequest( + node1Id, + d3Key, + ); + + expect(balAfter20 - balBefore20).to.equal(TEN_K, 'wallet diff'); + expect(nodeStakeAfter20).to.equal( + nodeStakeBefore20, + 'node stake invariant', + ); + expect(reqAfter20).to.equal(0n, 'request must be cleared'); + + console.log( + ` 🪙 +${ethers.formatUnits(TEN_K, 18)} TRAC to Delegator3 – withdrawal finalised`, + ); + + /********************************************************************** + * STEP 21 – Delegator 1 tries to stake extra 5 000 TRAC (★ must revert) + **********************************************************************/ + console.log( + '\n⛔ STEP 21: Delegator1 attempts to stake 5 000 TRAC – should revert', + ); + + /* ---------- context info ---------------------------------------- */ + const currentEpoch21 = await contracts.chronos.getCurrentEpoch(); // == epoch5 + const d1LastClaimed21 = await contracts.delegatorsInfo.getLastClaimedEpoch( + node1Id, + accounts.delegator1.address, + ); + console.log( + ` ℹ️ currentEpoch = ${currentEpoch21}, D1.lastClaimedEpoch = ${d1LastClaimed21}`, + ); + + // D1 has NOT yet claimed epoch 3 (and 4) → stake change must fail + + /* ---------- BEFORE snapshot ------------------------------------- */ + const d1StakeBaseBefore21 = + await contracts.stakingStorage.getDelegatorStakeBase(node1Id, d1Key); + const nodeStakeBefore21 = + await contracts.stakingStorage.getNodeStake(node1Id); + + /* ---------- token approval -------------------------------------- */ + await contracts.token + .connect(accounts.delegator1) + .approve(await contracts.staking.getAddress(), toTRAC18(5_000)); + + /* ---------- stake tx (expect revert) ---------------------------- */ + await expect( + contracts.staking + .connect(accounts.delegator1) + .stake(node1Id, toTRAC18(5_000)), + ).to.be.revertedWith( + 'Must claim the previous epoch rewards before changing stake', + ); + + console.log( + ' ✅ Revert received – Delegator1 must first claim epoch 4 rewards', + ); + + /* ---------- AFTER snapshot -------------------------------------- */ + const d1StakeBaseAfter21 = + await contracts.stakingStorage.getDelegatorStakeBase(node1Id, d1Key); + const nodeStakeAfter21 = + await contracts.stakingStorage.getNodeStake(node1Id); + + /* ---------- invariants ----------------------------------------- */ + expect(d1StakeBaseAfter21, 'D1.stakeBase should stay unchanged').to.equal( + d1StakeBaseBefore21, + ); + expect(nodeStakeAfter21, 'Node total stake should stay unchanged').to.equal( + nodeStakeBefore21, + ); + + /* ---------- console summary ------------------------------------ */ + console.log( + ` ❌ Stake blocked – D1 must claim rewards first`, + `\n ✅ D1.stakeBase remains ${ethers.formatUnits(d1StakeBaseAfter21, 18)} TRAC`, + `\n ✅ Node1.totalStake remains ${ethers.formatUnits(nodeStakeAfter21, 18)} TRAC\n`, + ); + }); + + /* ------------------------------------------------------------------ + * STEP A (Claim, Redelegate, Proof) + * ------------------------------------------------------------------ */ + it('Redelegate steps – Step A (D1 claims, redelegates N1->N2, then N1 submits proof)', async function () { + /* ------------------------------------------------------------------ + * 1. PRE-CONDITION: CLAIM PENDING REWARDS + * ------------------------------------------------------------------ */ + console.log( + '\n⏳ STEP A.1: Delegator1 claiming pending rewards for epoch 4...', + ); + + // From previous tests, we know epoch 4 is the last finalized one, + // and D1's last claim was for epoch 2. So, epochs 3 and 4 are pending. + + await contracts.staking + .connect(accounts.delegator1) + .claimDelegatorRewards(node1Id, 4n, accounts.delegator1.address); + + const d1LastClaimed = await contracts.delegatorsInfo.getLastClaimedEpoch( + node1Id, + accounts.delegator1.address, + ); + expect(d1LastClaimed).to.be.gte( + 4n, + 'Delegator1 should have claimed all pending rewards up to epoch 4', + ); + console.log( + ` ✅ Pending rewards claimed. D1 last claimed epoch is now ${d1LastClaimed}.`, + ); + + /* ------------------------------------------------------------------ + * 2. REDELEGATE N1 -> N2 (with checks and logs) + * ------------------------------------------------------------------ */ + console.log( + '\n✈️ STEP A.2: Delegator1 redelegating from Node1 to Node2...', + ); + + // Snapshot BEFORE + const stakeToMove = await contracts.stakingStorage.getDelegatorStakeBase( + node1Id, + d1Key, + ); + const n1StakeBefore = await contracts.stakingStorage.getNodeStake(node1Id); + const n2StakeBefore = await contracts.stakingStorage.getNodeStake( + nodeIds.node2Id, + ); + console.log( + ` [BEFORE] N1.total=${ethers.formatUnits( + n1StakeBefore, + 18, + )} | N2.total=${ethers.formatUnits( + n2StakeBefore, + 18, + )} | D1.stake=${ethers.formatUnits(stakeToMove, 18)}`, + ); + + // Perform Redelegate + await contracts.staking + .connect(accounts.delegator1) + .redelegate(node1Id, nodeIds.node2Id, stakeToMove); + + // Snapshot AFTER + const n1StakeAfter = await contracts.stakingStorage.getNodeStake(node1Id); + const n2StakeAfter = await contracts.stakingStorage.getNodeStake( + nodeIds.node2Id, + ); + const d1BaseN1 = await contracts.stakingStorage.getDelegatorStakeBase( + node1Id, + d1Key, + ); + const d1BaseN2 = await contracts.stakingStorage.getDelegatorStakeBase( + nodeIds.node2Id, + d1Key, + ); + const d1StillOnN1 = await contracts.delegatorsInfo.isNodeDelegator( + node1Id, + accounts.delegator1.address, + ); + const d1OnN2 = await contracts.delegatorsInfo.isNodeDelegator( + nodeIds.node2Id, + accounts.delegator1.address, + ); + + console.log( + ` [AFTER] N1.total=${ethers.formatUnits( + n1StakeAfter, + 18, + )} | N2.total=${ethers.formatUnits( + n2StakeAfter, + 18, + )} | D1.base(N1)=${d1BaseN1} | D1.base(N2)=${d1BaseN2}`, + ); + + // Assertions + expect(d1BaseN1).to.equal(0n, 'D1 should have 0 stake on N1'); + expect(d1BaseN2).to.equal(stakeToMove, 'Stake should be moved to N2'); + expect(n1StakeAfter).to.equal(n1StakeBefore - stakeToMove); + expect(n2StakeAfter).to.equal(n2StakeBefore + stakeToMove); + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + expect(d1StillOnN1).to.be.false; + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + expect(d1OnN2).to.be.true; + + // Log the crucial state for debugging Step B + const lastStakeHeldEpochN1 = + await contracts.delegatorsInfo.getLastStakeHeldEpoch( + node1Id, + accounts.delegator1.address, + ); + console.log( + ` [DEBUG] D1 on N1: isDelegator=${d1StillOnN1}, lastStakeHeldEpoch=${lastStakeHeldEpochN1}`, + ); + + console.log(' ✅ Redelegation successful.'); + + /* ------------------------------------------------------------------ + * 3. NODE 1 SUBMITS PROOF + * ------------------------------------------------------------------ */ + console.log('\n🔬 STEP A.3: Node1 submitting proof for current epoch...'); + const curEpoch = await contracts.chronos.getCurrentEpoch(); // Should be epoch 5 + expect(curEpoch).to.equal(5n); + + await advanceToNextProofingPeriod(contracts); + + await ensureNodeHasChunksThisEpoch( + node1Id, + accounts.node1, + contracts, + accounts, + receivingNodes, + receivingNodesIdentityIds, + chunkSize, + ); + + const n1StakeNow = await contracts.stakingStorage.getNodeStake(node1Id); + await submitProofAndVerifyScore( + node1Id, + accounts.node1, + contracts, + curEpoch, + n1StakeNow, + ); + console.log(' ✅ Node1 proof submitted.'); + + console.log( + ` [DEBUG2] D1 on N1: isDelegator=${d1StillOnN1}, lastStakeHeldEpoch=${lastStakeHeldEpochN1}`, + ); + + /* ------------------------------------------------------------------ + * 4. ADVANCE TO NEXT EPOCH + * ------------------------------------------------------------------ */ + console.log('\n⏭️ STEP A.4: Advancing to the next epoch...'); + const ttn5 = await contracts.chronos.timeUntilNextEpoch(); + await time.increase(ttn5 + 1n); // → epoch-6 + const epoch6 = await contracts.chronos.getCurrentEpoch(); + + await createKnowledgeCollection( + accounts.kcCreator, + accounts.node2, + Number(nodeIds.node2Id), + receivingNodes, + receivingNodesIdentityIds, + { KnowledgeCollection: contracts.kc, Token: contracts.token }, + merkleRoot, + 'test-op-id-node2-proof-stepA4', + 10, + chunkSize * 8, // byteSize - use multiple of chunkSize for proper chunk generation + 10, + toTRAC(1000), + ); + + /* Verify epoch-5 is now finalised so its rewards can be claimed */ + expect( + await contracts.epochStorage.lastFinalizedEpoch(1), + 'epoch-5 should now be finalised', + ).to.equal(5n); + + expect(epoch6).to.equal(6n); + console.log(` ✅ Advanced to epoch ${epoch6}.`); + }); + + /* ------------------------------------------------------------------ + * STEP B – redelegate all stake N2 → N1 + * ------------------------------------------------------------------ */ + it('Redelegate steps – Step B (N2 → N1)', async function () { + /* ──────────────── 1. PREPARATION & INITIAL STATE ───────────────── */ + const epoch = await contracts.chronos.getCurrentEpoch(); + console.log(`\n\n--- STEP B: Redelegate N2 -> N1 (Epoch ${epoch}) ---`); + + const d1isDelegatorN2_before = + await contracts.delegatorsInfo.isNodeDelegator( + nodeIds.node2Id, + accounts.delegator1.address, + ); + const d1LastStakeHeldN2_before = + await contracts.delegatorsInfo.getLastStakeHeldEpoch( + nodeIds.node2Id, + accounts.delegator1.address, + ); + console.log( + `🔎 [B.1] Initial D1 on N2: isDelegator=${d1isDelegatorN2_before}, lastStakeHeldEpoch=${d1LastStakeHeldN2_before}`, + ); + + const d1BaseN2_before = + await contracts.stakingStorage.getDelegatorStakeBase( + nodeIds.node2Id, + d1Key, + ); + expect( + d1BaseN2_before, + 'D1 must have stake on N2 to start Step B', + ).to.be.gt(0n); + + /* ──────────────── 2. NODE-2 SUBMITS PROOF ───────── */ + console.log(`🔬 [B.2] Node2 submitting proof...`); + + await advanceToNextProofingPeriod(contracts); + + await ensureNodeHasChunksThisEpoch( + nodeIds.node2Id, + accounts.node2, + contracts, + accounts, + receivingNodes, + receivingNodesIdentityIds, + chunkSize, + ); + + const n2Stake_beforeProof = await contracts.stakingStorage.getNodeStake( + nodeIds.node2Id, + ); + await submitProofAndVerifyScore( + nodeIds.node2Id, + accounts.node2, + contracts, + epoch, + n2Stake_beforeProof, + ); + console.log(` ✅ Node2 proof submitted.`); + + /* ──────────────── 3. REDELEGATE N2 → N1 ─────────── */ + console.log(`✈️ [B.3] D1 redelegating all stake from N2 to N1...`); + const n1Stake_beforeRedelegate = + await contracts.stakingStorage.getNodeStake(node1Id); + await contracts.staking + .connect(accounts.delegator1) + .redelegate(nodeIds.node2Id, node1Id, d1BaseN2_before); + console.log(' ✅ Redelegation transaction sent.'); + + /* ──────────────── 4. POST-SNAPSHOT & ASSERTIONS ──────────────── */ + console.log(`🔎 [B.4] Final State & Assertions...`); + + const [ + d1BaseN2_after, + d1BaseN1_after, + n2Stake_after, + n1Stake_after, + stillDelegatorOnN2, + lastStakeHeldEpochN2, + ] = await Promise.all([ + contracts.stakingStorage.getDelegatorStakeBase(nodeIds.node2Id, d1Key), + contracts.stakingStorage.getDelegatorStakeBase(node1Id, d1Key), + contracts.stakingStorage.getNodeStake(nodeIds.node2Id), + contracts.stakingStorage.getNodeStake(node1Id), + contracts.delegatorsInfo.isNodeDelegator( + nodeIds.node2Id, + accounts.delegator1.address, + ), + contracts.delegatorsInfo.getLastStakeHeldEpoch( + nodeIds.node2Id, + accounts.delegator1.address, + ), + ]); + + console.log( + ` - Final D1 on N2: isDelegator=${stillDelegatorOnN2}, lastStakeHeldEpoch=${lastStakeHeldEpochN2}`, + ); + + expect(d1BaseN2_after, 'D1 stake on N2 should now be zero').to.equal(0n); + expect(d1BaseN1_after, 'Stake must fully move to N1').to.equal( + d1BaseN2_before, + ); + expect(n2Stake_after).to.equal( + n2Stake_beforeProof - d1BaseN2_before, + 'N2 total stake should decrease by the redelegated amount', + ); + expect(n1Stake_after).to.equal( + n1Stake_beforeRedelegate + d1BaseN2_before, + 'N1 total stake should increase by the redelegated amount', + ); + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + expect(stillDelegatorOnN2, 'D1 must remain delegator on N2').to.be.true; + expect( + lastStakeHeldEpochN2, + 'lastStakeHeldEpoch mismatch, should be set to current epoch', + ).to.equal(epoch); + }); + + /** + * STEP C – Move to the next epoch, explicitly call + * _validateDelegatorEpochClaims twice (N1 ✓, N2 ✗), + * then try the real redelegate which must revert. + */ + it('STEP C – validate twice, cancelWithdrawal, then failed redelegate', async function () { + /* ────────────────────────────────────────────────────────────── + * 1️⃣ Advance exactly one epoch forward + * (make the test independent of the absolute epoch number) + * ────────────────────────────────────────────────────────────── */ + const beforeEpoch = await contracts.chronos.getCurrentEpoch(); + const ttn = await contracts.chronos.timeUntilNextEpoch(); + await time.increase(ttn + 1n); // → +1 epoch + const afterEpoch = await contracts.chronos.getCurrentEpoch(); + + expect(afterEpoch).to.equal( + beforeEpoch + 1n, + 'Epoch did not advance by exactly one', + ); + console.log(`\n🚦 STEP C: now in epoch ${afterEpoch}`); + + /* ---------------------------------------------------------------- + * 1-b) Finalise the *previous* epoch by creating a tiny KC + * (prevents "epoch not finalised" surprises in later claims) + * ---------------------------------------------------------------- */ + await createKnowledgeCollection( + accounts.kcCreator, + accounts.node1, // any node is fine – we use N1 + Number(node1Id), + receivingNodes, + receivingNodesIdentityIds, + { KnowledgeCollection: contracts.kc, Token: contracts.token }, + merkleRoot, + 'finalise-stepC', + 1, // holders + chunkSize * 2, // byteSize - use multiple of chunkSize for proper chunk generation + 1, // replicas + toTRAC(1), // 1 TRAC fee – enough to finalise + ); + + expect( + await contracts.epochStorage.lastFinalizedEpoch(1), + 'Previous epoch should now be finalised', + ).to.be.gte(afterEpoch - 1n); + + /* ---------------------------------------------------------------- + * Helper – current Delegator-1 stake on N1 (used later) + * ---------------------------------------------------------------- */ + const stakeN1_start = await contracts.stakingStorage.getDelegatorStakeBase( + node1Id, + d1Key, + ); + + /* ────────────────────────────────────────────────────────────── + * 2️⃣ Dry-run the internal validator through callStatic + * ────────────────────────────────────────────────────────────── */ + console.log('\n🔍 Manual _validateDelegatorEpochClaims checks…'); + + // 2-a) N1 – should **pass** + await expect( + contracts.staking + .connect(accounts.delegator1) + .requestWithdrawal.staticCall(node1Id, 1n), // 1 wei is enough + ).to.not.be.reverted; + console.log(' ✅ Validation on N1 passed'); + + // Make a real 1-wei withdrawal so we can cancel it immediately + await contracts.staking + .connect(accounts.delegator1) + .requestWithdrawal(node1Id, 1n); + await contracts.staking + .connect(accounts.delegator1) + .cancelWithdrawal(node1Id); + console.log(' ↩️ requestWithdrawal + cancelWithdrawal on N1 succeeded'); + + // 2-b) N2 – must **revert** + await expect( + contracts.staking + .connect(accounts.delegator1) + .requestWithdrawal.staticCall(nodeIds.node2Id, 1n), + ).to.be.revertedWith( + 'Must claim rewards up to the lastStakeHeldEpoch before changing stake', + ); + console.log(' ✅ Validation on N2 reverted as expected'); + + /* ────────────────────────────────────────────────────────────── + * 3️⃣ Attempt a real redelegate N1 ➜ N2 – must revert + * ────────────────────────────────────────────────────────────── */ + const halfStake = stakeN1_start / 2n; + console.log( + `\n↪️ Attempting to redelegate ${ethers.formatUnits(halfStake, 18)} TRAC N1 ➜ N2`, + ); + + await expect( + contracts.staking + .connect(accounts.delegator1) + .redelegate(node1Id, nodeIds.node2Id, halfStake), + ).to.be.revertedWith( + 'Must claim rewards up to the lastStakeHeldEpoch before changing stake', + ); + console.log(' ✅ Redelegate reverted – pending N2 rewards not claimed'); + + /* ────────────────────────────────────────────────────────────── + * 4️⃣ Sanity-check – stake amounts must be unchanged + * ────────────────────────────────────────────────────────────── */ + const stakeN1_end = await contracts.stakingStorage.getDelegatorStakeBase( + node1Id, + d1Key, + ); + const stakeN2_end = await contracts.stakingStorage.getDelegatorStakeBase( + nodeIds.node2Id, + d1Key, + ); + + expect(stakeN1_end).to.equal( + stakeN1_start, + 'Stake on N1 must remain unchanged', + ); + expect(stakeN2_end).to.equal(0n, 'Stake on N2 must remain zero'); + + console.log( + ` ✅ State unchanged → N1: ${ethers.formatUnits(stakeN1_end, 18)} TRAC | ` + + `N2: ${ethers.formatUnits(stakeN2_end, 18)} TRAC`, + ); + console.log(`\n🚦 STEP C: now in epoch ${afterEpoch}`); + }); + + /****************************************************************************************** + * STEP D – two un-claimed epochs, claim one, redelegate half, check rolling + /* ------------------------------------------------------------------ + * STEP D – epoch-8: claim epoch-6 on N2 (→ goes to rollingRewards), + * redelegate half of live stake N1 → N2, verify state + * ------------------------------------------------------------------ */ + it('STEP D – claim one on N2, redelegate half, check rolling', async function () { + const delegator = accounts.delegator1; + const fmt = (x: bigint) => ethers.formatUnits(x, 18); + + /* ── 0. Move to epoch-8 and finalise epoch-7 ────────────────────── */ + await time.increase((await contracts.chronos.timeUntilNextEpoch()) + 1n); // → 8 + const epoch8 = await contracts.chronos.getCurrentEpoch(); + + await createKnowledgeCollection( + accounts.kcCreator, + accounts.node1, + Number(node1Id), + receivingNodes, + receivingNodesIdentityIds, + { KnowledgeCollection: contracts.kc, Token: contracts.token }, + merkleRoot, + 'finalise-ep7', + 1, + chunkSize * 2, // byteSize - use multiple of chunkSize for proper chunk generation + 1, + toTRAC(1), + ); + expect(await contracts.epochStorage.lastFinalizedEpoch(1)).to.be.gte(7n); + + console.log( + '\n────────────── STEP D – STATE BEFORE ACTIONS ──────────────', + ); + console.log(`[D-0] Current epoch: ${epoch8}`); + + /* ── 1. Quick sanity check for claimable epochs ────────────────── */ + const lastClaimedN1 = await contracts.delegatorsInfo.getLastClaimedEpoch( + node1Id, + delegator.address, + ); // 6 + const lastClaimedN2 = await contracts.delegatorsInfo.getLastClaimedEpoch( + nodeIds.node2Id, + delegator.address, + ); // 5 + const lastStakeHeldN2 = + await contracts.delegatorsInfo.getLastStakeHeldEpoch( + nodeIds.node2Id, + delegator.address, + ); // 6 + + console.log(`[D-1] N1.lastClaimed = ${lastClaimedN1}`); + console.log(`[D-1] N2.lastClaimed = ${lastClaimedN2}`); + console.log(`[D-1] N2.lastStakeHeldEpoch = ${lastStakeHeldN2}`); + + // exactly one claimable epoch on N2 → epoch-6 + expect(lastClaimedN2 + 1n).to.equal(lastStakeHeldN2); + expect(epoch8 - lastClaimedN2).to.equal(3n); // epochs 6-8 + + /* ── 2. Claim epoch-6 on N2 (gap = 2 ⇒ reward → rollingRewards) ── */ + const [baseN2_before, rollingN2_before, nodeScore6, delegScore6, pool6] = + await Promise.all([ + contracts.stakingStorage.getDelegatorStakeBase(nodeIds.node2Id, d1Key), + contracts.delegatorsInfo.getDelegatorRollingRewards( + nodeIds.node2Id, + delegator.address, + ), + contracts.randomSamplingStorage.getNodeEpochScore(6n, nodeIds.node2Id), + contracts.randomSamplingStorage.getEpochNodeDelegatorScore( + 6n, + nodeIds.node2Id, + d1Key, + ), + contracts.stakingKPI.getNetNodeRewards(nodeIds.node2Id, 6n), + ]); + const expectedReward6 = + nodeScore6 === 0n ? 0n : (delegScore6 * pool6) / nodeScore6; + + console.log('\n[D-2] BEFORE claim epoch-6 on N2'); + console.log(` baseN2 : ${fmt(baseN2_before)} TRAC`); + console.log(` rollingN2 : ${fmt(rollingN2_before)} TRAC`); + console.log(` expectedReward: ${fmt(expectedReward6)} TRAC`); + + await contracts.staking + .connect(delegator) + .claimDelegatorRewards(nodeIds.node2Id, 6n, delegator.address); + + const [baseN2_after, rollingN2_after, lastClaimedN2_after] = + await Promise.all([ + contracts.stakingStorage.getDelegatorStakeBase(nodeIds.node2Id, d1Key), + contracts.delegatorsInfo.getDelegatorRollingRewards( + nodeIds.node2Id, + delegator.address, + ), + contracts.delegatorsInfo.getLastClaimedEpoch( + nodeIds.node2Id, + delegator.address, + ), + ]); + + console.log('\n[D-2] AFTER claim epoch-6 on N2'); + console.log(` baseN2 : ${fmt(baseN2_after)} TRAC`); + console.log(` rollingN2 : ${fmt(rollingN2_after)} TRAC`); + console.log(` lastClaimedN2 : ${lastClaimedN2_after}`); + + // reward should sit in rollingRewards, stake stays unchanged + expect(baseN2_after).to.equal(baseN2_before, 'base stake unchanged'); + expect(rollingN2_after - rollingN2_before).to.equal( + expectedReward6, + 'rolling diff', + ); + expect(lastClaimedN2_after).to.equal(6n); + + /* ── 3. Redelegate half of live stake N1 → N2 ─────────────────── */ + const baseN1_before = await contracts.stakingStorage.getDelegatorStakeBase( + node1Id, + d1Key, + ); + const halfStake = baseN1_before / 2n; + + const [n1Total_before, n2Total_before] = await Promise.all([ + contracts.stakingStorage.getNodeStake(node1Id), + contracts.stakingStorage.getNodeStake(nodeIds.node2Id), + ]); + + console.log('\n[D-3] BEFORE redelegate'); + console.log(` baseN1 : ${fmt(baseN1_before)} TRAC`); + console.log(` baseN2 : ${fmt(baseN2_after)} TRAC`); + console.log(` halfStake : ${fmt(halfStake)} TRAC`); + + await contracts.staking + .connect(delegator) + .redelegate(node1Id, nodeIds.node2Id, halfStake); + + /* ── 4. Post-redelegate assertions & logs ──────────────────────── */ + const [ + baseN1_after, + baseN2_final, + n1Total_after, + n2Total_after, + rollingN1_final, + rollingN2_final, + ] = await Promise.all([ + contracts.stakingStorage.getDelegatorStakeBase(node1Id, d1Key), + contracts.stakingStorage.getDelegatorStakeBase(nodeIds.node2Id, d1Key), + contracts.stakingStorage.getNodeStake(node1Id), + contracts.stakingStorage.getNodeStake(nodeIds.node2Id), + contracts.delegatorsInfo.getDelegatorRollingRewards( + node1Id, + delegator.address, + ), + contracts.delegatorsInfo.getDelegatorRollingRewards( + nodeIds.node2Id, + delegator.address, + ), + ]); + + console.log('\n[D-4] AFTER redelegate'); + console.log(` baseN1 : ${fmt(baseN1_after)} TRAC`); + console.log(` baseN2 : ${fmt(baseN2_final)} TRAC`); + console.log( + ` N1 total stake: ${fmt(n1Total_before)} ➜ ${fmt(n1Total_after)} TRAC`, + ); + console.log( + ` N2 total stake: ${fmt(n2Total_before)} ➜ ${fmt(n2Total_after)} TRAC`, + ); + console.log(` rollingN1 : ${fmt(rollingN1_final)} TRAC`); + console.log(` rollingN2 : ${fmt(rollingN2_final)} TRAC\n`); + + // stake balances + expect(baseN1_after).to.equal(baseN1_before - halfStake); + expect(baseN2_final).to.equal(baseN2_after + halfStake); + expect(n1Total_after).to.equal(n1Total_before - halfStake); + expect(n2Total_after).to.equal(n2Total_before + halfStake); + + // rollingRewards must stay the same after redelegate + expect(rollingN2_final).to.equal( + rollingN2_after, + 'rolling on N2 unchanged', + ); + expect(rollingN1_final).to.equal(0n, 'rolling on N1 remains zero'); + + console.log( + ` ✔ Redelegate OK – N1:${fmt(baseN1_after)} | N2:${fmt(baseN2_final)} TRAC`, + ); + }); +}); + +describe(`Delegator Scoring`, function () { + let accounts: TestAccounts; + let contracts: TestContracts; + let nodeIds: { node1Id: bigint; node2Id: bigint }; + let node1Id: bigint; + let d1Key: string, d2Key: string; + let epoch1: bigint; // eslint-disable-line @typescript-eslint/no-unused-vars + let receivingNodes: { + operational: SignerWithAddress; + admin: SignerWithAddress; + }[]; + let receivingNodesIdentityIds: number[]; + + beforeEach(async function () { + // Setup test environment + const setup = await setupTestEnvironment(); + accounts = setup.accounts; + contracts = setup.contracts; + nodeIds = setup.nodeIds; + node1Id = nodeIds.node1Id; + + epoch1 = await contracts.chronos.getCurrentEpoch(); + + // Create delegator keys for state verification + d1Key = ethers.keccak256( + ethers.solidityPacked(['address'], [accounts.delegator1.address]), + ); + d2Key = ethers.keccak256( + ethers.solidityPacked(['address'], [accounts.delegator2.address]), + ); + + // Setup receiving nodes for KC creation + receivingNodes = [ + accounts.receiver1, + accounts.receiver2, + accounts.receiver3, + ]; + receivingNodesIdentityIds = []; + for (const recNode of receivingNodes) { + const { identityId } = await createProfile(contracts.profile, recNode); + receivingNodesIdentityIds.push(Number(identityId)); + } + + // Initialize ask system properly to prevent division by zero + // Stake some tokens to node1 to make it eligible for ask setting + await contracts.token + .connect(accounts.node1.operational) + .approve(await contracts.staking.getAddress(), toTRAC(100)); + await contracts.staking + .connect(accounts.node1.operational) + .stake(node1Id, toTRAC(100)); + + // Set ask price to establish bounds + const nodeAsk = ethers.parseUnits('0.1', 18); + await contracts.profile + .connect(accounts.node1.operational) + .updateAsk(node1Id, nodeAsk); + await contracts.ask.connect(accounts.owner).recalculateActiveSet(); + + // Create knowledge collection for reward pool + const kcTokenAmount = toTRAC(10_000); + const numberOfEpochs = 5; + await createKnowledgeCollection( + accounts.kcCreator, + accounts.node1, + Number(node1Id), + receivingNodes, + receivingNodesIdentityIds, + { KnowledgeCollection: contracts.kc, Token: contracts.token }, + merkleRoot, + 'delegator-scoring-test', + 10, + 1000, + numberOfEpochs, + kcTokenAmount, + ); + }); + + describe('Suite 1: Basic Delegator Scoring', function () { + it('1A - First-time stake (no node score yet)', async function () { + console.log('\n📊 TEST 1A: First-time stake (no node score yet)'); + + // Fresh epoch, no proofs yet + const currentEpoch = await contracts.chronos.getCurrentEpoch(); + console.log(` ℹ️ Current epoch: ${currentEpoch}`); + + // Verify no node score exists yet + const nodeScoreBefore = + await contracts.randomSamplingStorage.getNodeEpochScore( + currentEpoch, + node1Id, + ); + expect(nodeScoreBefore).to.equal( + 0n, + 'Node should have no score initially', + ); + + // Delegator1 stakes 100 TRAC + const stakeAmount = toTRAC(100); + await contracts.token + .connect(accounts.delegator1) + .approve(await contracts.staking.getAddress(), stakeAmount); + await contracts.staking + .connect(accounts.delegator1) + .stake(node1Id, stakeAmount); + + // **DELEGATOR SCORING ASSERTIONS** + const delegatorScore = + await contracts.randomSamplingStorage.getEpochNodeDelegatorScore( + currentEpoch, + node1Id, + d1Key, + ); + expect(delegatorScore).to.equal( + 0n, + '**epochNodeDelegatorScore should be 0 (no proofs yet)**', + ); + + const lastSettledIndex = + await contracts.randomSamplingStorage.getDelegatorLastSettledNodeEpochScorePerStake( + currentEpoch, + node1Id, + d1Key, + ); + expect(lastSettledIndex).to.equal( + 0n, + 'Last settled index should be 0 initially', + ); + + // Verify stake amounts (account for setup stake from node1.operational + delegator stake) + const delegatorStakeBase = + await contracts.stakingStorage.getDelegatorStakeBase(node1Id, d1Key); + const nodeStake = await contracts.stakingStorage.getNodeStake(node1Id); + const totalStake = await contracts.stakingStorage.getTotalStake(); + const setupStake = toTRAC(100); // from beforeEach setup + const expectedNodeStake = setupStake + stakeAmount; + + expect(delegatorStakeBase).to.equal( + stakeAmount, + 'stakeBase should equal delegator stake amount', + ); + expect(nodeStake).to.equal( + expectedNodeStake, + 'node stake should equal setup stake + delegator stake', + ); + expect(totalStake).to.equal( + expectedNodeStake, + 'total stake should equal node stake', + ); + + console.log(` ✅ Delegator score: ${delegatorScore} (expected: 0)`); + console.log( + ` ✅ Stake base: ${ethers.formatUnits(delegatorStakeBase, 18)} TRAC`, + ); + console.log( + ` ✅ Node stake: ${ethers.formatUnits(nodeStake, 18)} TRAC`, + ); + }); + + it('1B - Proof, then same delegator stakes more', async function () { + console.log('\n🔬 TEST 1B: Proof, then same delegator stakes more'); + + const currentEpoch = await contracts.chronos.getCurrentEpoch(); + + // Step 1: Initial stake + const initialStake = toTRAC(100); + await contracts.token + .connect(accounts.delegator1) + .approve(await contracts.staking.getAddress(), initialStake); + await contracts.staking + .connect(accounts.delegator1) + .stake(node1Id, initialStake); + + // Step 2: Node submits proof - Record index₀ + await contracts.randomSampling.updateAndGetActiveProofPeriodStartBlock(); + const setupStake = toTRAC(100); // from beforeEach setup + const totalStakeForScore = setupStake + initialStake; + const { nodeScorePerStake: index0 } = await submitProofAndVerifyScore( + node1Id, + accounts.node1, + contracts, + currentEpoch, + totalStakeForScore, + ); + console.log(` 📋 Recorded index₀: ${index0}`); + + // Step 3: Delegator stakes more - Record index₁ + const additionalStake = toTRAC(50); + await contracts.token + .connect(accounts.delegator1) + .approve(await contracts.staking.getAddress(), additionalStake); + + await contracts.staking + .connect(accounts.delegator1) + .stake(node1Id, additionalStake); + + const index1 = + await contracts.randomSamplingStorage.getNodeEpochScorePerStake( + currentEpoch, + node1Id, + ); + console.log(` 📋 Recorded nodeScorePerStake: ${index1}`); + + // **DELEGATOR SCORING ASSERTIONS** + const SCALE18 = ethers.parseUnits('1', 18); + const expectedDeltaScore = + (initialStake * (index1 - BigInt(0))) / SCALE18; // index₀ was 0 when delegator first staked + const actualDelegatorScore = + await contracts.randomSamplingStorage.getEpochNodeDelegatorScore( + currentEpoch, + node1Id, + d1Key, + ); + + console.log( + ` 🧮 Expected Δscore: 100 TRAC × (${index1} - 0) / 1e18 = ${expectedDeltaScore}`, + ); + console.log(` 🧮 Actual delegator score: ${actualDelegatorScore}`); + + expect(actualDelegatorScore).to.equal( + expectedDeltaScore, + '**Δscore should equal 100 · (index₁−index₀)/1e18**', + ); + + // Last-settled index should be updated to current index + const lastSettledIndex = + await contracts.randomSamplingStorage.getDelegatorLastSettledNodeEpochScorePerStake( + currentEpoch, + node1Id, + d1Key, + ); + expect(lastSettledIndex).to.equal( + index1, + '**Last-settled index should equal index₁**', + ); + + // Stake base should be 150 TRAC + const finalStakeBase = + await contracts.stakingStorage.getDelegatorStakeBase(node1Id, d1Key); + expect(finalStakeBase).to.equal( + initialStake + additionalStake, + '**stakeBase should be 150 TRAC**', + ); + + console.log( + ` ✅ Delegator score correctly calculated: ${actualDelegatorScore}`, + ); + console.log(` ✅ Last settled index: ${lastSettledIndex}`); + console.log( + ` ✅ Final stake base: ${ethers.formatUnits(finalStakeBase, 18)} TRAC`, + ); + }); + + it('1C - Partial withdrawal mid-epoch', async function () { + console.log('\n📤 TEST 1C: Partial withdrawal mid-epoch'); + + const currentEpoch = await contracts.chronos.getCurrentEpoch(); + + // Setup from 1B: stake 100, proof, stake +50 + const initialStake = toTRAC(100); + await contracts.token + .connect(accounts.delegator1) + .approve(await contracts.staking.getAddress(), initialStake); + await contracts.staking + .connect(accounts.delegator1) + .stake(node1Id, initialStake); + + await contracts.randomSampling.updateAndGetActiveProofPeriodStartBlock(); + const setupStake = toTRAC(100); // from beforeEach setup + await submitProofAndVerifyScore( + node1Id, + accounts.node1, + contracts, + currentEpoch, + setupStake + initialStake, + ); + + const additionalStake = toTRAC(50); + await contracts.token + .connect(accounts.delegator1) + .approve(await contracts.staking.getAddress(), additionalStake); + await contracts.staking + .connect(accounts.delegator1) + .stake(node1Id, additionalStake); + + // Record state before withdrawal + const delegatorScoreBefore = + await contracts.randomSamplingStorage.getEpochNodeDelegatorScore( + currentEpoch, + node1Id, + d1Key, + ); + const lastSettledIndexBefore = + await contracts.randomSamplingStorage.getDelegatorLastSettledNodeEpochScorePerStake( + currentEpoch, + node1Id, + d1Key, + ); + const currentIndex = + await contracts.randomSamplingStorage.getNodeEpochScorePerStake( + currentEpoch, + node1Id, + ); + + console.log(` 📊 Score before withdrawal: ${delegatorScoreBefore}`); + console.log( + ` 📊 Last settled index before: ${lastSettledIndexBefore}`, + ); + console.log(` 📊 Current index: ${currentIndex}`); + + // Partial withdrawal of 25 TRAC + const withdrawalAmount = toTRAC(25); + await contracts.staking + .connect(accounts.delegator1) + .requestWithdrawal(node1Id, withdrawalAmount); + + // **DELEGATOR SCORING ASSERTIONS** + const delegatorScoreAfter = + await contracts.randomSamplingStorage.getEpochNodeDelegatorScore( + currentEpoch, + node1Id, + d1Key, + ); + const lastSettledIndexAfter = + await contracts.randomSamplingStorage.getDelegatorLastSettledNodeEpochScorePerStake( + currentEpoch, + node1Id, + d1Key, + ); + const currentIndexAfter = + await contracts.randomSamplingStorage.getNodeEpochScorePerStake( + currentEpoch, + node1Id, + ); + + // Score should be unchanged from before withdrawal + expect(delegatorScoreAfter).to.equal( + delegatorScoreBefore, + '**Delegator score should be unchanged**', + ); + + // Last-settled index should be updated to current index + expect(lastSettledIndexAfter).to.equal( + currentIndexAfter, + '**Last-settled index should equal current index**', + ); + + // Stake base should be 125 TRAC (150 - 25) + const finalStakeBase = + await contracts.stakingStorage.getDelegatorStakeBase(node1Id, d1Key); + expect(finalStakeBase).to.equal( + toTRAC(125), + '**stakeBase should be 125 TRAC**', + ); + + console.log(` ✅ Delegator score unchanged: ${delegatorScoreAfter}`); + console.log( + ` ✅ Last settled index updated: ${lastSettledIndexAfter}`, + ); + console.log( + ` ✅ Final stake base: ${ethers.formatUnits(finalStakeBase, 18)} TRAC`, + ); + }); + + it('1D - Single-epoch reward claim & auto-restake', async function () { + console.log('\n💰 TEST 1D: Single-epoch reward claim & auto-restake'); + + const startEpoch = await contracts.chronos.getCurrentEpoch(); + + // Setup: stake and earn score in startEpoch + const initialStake = toTRAC(100); + await contracts.token + .connect(accounts.delegator1) + .approve(await contracts.staking.getAddress(), initialStake); + await contracts.staking + .connect(accounts.delegator1) + .stake(node1Id, initialStake); + + await contracts.randomSampling.updateAndGetActiveProofPeriodStartBlock(); + const setupStake = toTRAC(100); // from beforeEach setup + await submitProofAndVerifyScore( + node1Id, + accounts.node1, + contracts, + startEpoch, + setupStake + initialStake, + ); + + // Trigger score settlement by doing a minimal stake operation + await contracts.token + .connect(accounts.delegator1) + .approve(await contracts.staking.getAddress(), toTRAC(1)); + await contracts.staking + .connect(accounts.delegator1) + .stake(node1Id, toTRAC(1)); + + const delegatorScoreInStartEpoch = + await contracts.randomSamplingStorage.getEpochNodeDelegatorScore( + startEpoch, + node1Id, + d1Key, + ); + console.log( + ` 📊 Delegator score in epoch ${startEpoch}: ${delegatorScoreInStartEpoch}`, + ); + + // Advance to epoch E+1 + const timeUntilNext = await contracts.chronos.timeUntilNextEpoch(); + await time.increase(timeUntilNext + 1n); + const nextEpoch = await contracts.chronos.getCurrentEpoch(); + expect(nextEpoch).to.equal(startEpoch + 1n); + + // Node proof in new epoch to finalize previous epoch + await createKnowledgeCollection( + accounts.kcCreator, + accounts.node1, + Number(node1Id), + receivingNodes, + receivingNodesIdentityIds, + { KnowledgeCollection: contracts.kc, Token: contracts.token }, + merkleRoot, + 'finalize-epoch', + 1, + 1000, + 1, + toTRAC(100), + ); + + // Verify epoch is finalized + expect(await contracts.epochStorage.lastFinalizedEpoch(1)).to.be.gte( + startEpoch, + ); + + // Get data before claim + const stakeBaseBefore = + await contracts.stakingStorage.getDelegatorStakeBase(node1Id, d1Key); + const nodeScore = await contracts.randomSamplingStorage.getNodeEpochScore( + startEpoch, + node1Id, + ); + const netNodeRewards = await contracts.stakingKPI.getNetNodeRewards( + node1Id, + startEpoch, + ); + + // Calculate expected reward + const expectedReward = + nodeScore === 0n + ? 0n + : (delegatorScoreInStartEpoch * netNodeRewards) / nodeScore; + console.log( + ` 🧮 Expected reward: (${delegatorScoreInStartEpoch} × ${ethers.formatUnits(netNodeRewards, 18)}) / ${nodeScore} = ${ethers.formatUnits(expectedReward, 18)} TRAC`, + ); + + // Claim rewards + await contracts.staking + .connect(accounts.delegator1) + .claimDelegatorRewards( + node1Id, + startEpoch, + accounts.delegator1.address, + ); + + // **DELEGATOR SCORING ASSERTIONS** + const stakeBaseAfter = + await contracts.stakingStorage.getDelegatorStakeBase(node1Id, d1Key); + const actualReward = stakeBaseAfter - stakeBaseBefore; + + expect(actualReward).to.equal( + expectedReward, + '**Reward should equal delegatorScore × netNodeRewards / nodeScore**', + ); + + // Check that epochNodeDelegatorScore is now consumed (this is implicit as it's used in reward calculation) + const delegatorScoreAfterClaim = + await contracts.randomSamplingStorage.getEpochNodeDelegatorScore( + startEpoch, + node1Id, + d1Key, + ); + // Score should still be there (it's not reset, just used for calculation) + expect(delegatorScoreAfterClaim).to.equal( + delegatorScoreInStartEpoch, + '**epochNodeDelegatorScore should remain for future reference**', + ); + + // Rolling rewards should be reset (0) since gap is only 1 epoch (auto-restake) + const rollingRewards = + await contracts.delegatorsInfo.getDelegatorRollingRewards( + node1Id, + accounts.delegator1.address, + ); + expect(rollingRewards).to.equal( + 0n, + '**rollingRewards should be reset to 0 (auto-restake)**', + ); + + console.log( + ` ✅ Actual reward: ${ethers.formatUnits(actualReward, 18)} TRAC`, + ); + console.log( + ` ✅ Stake base increased: ${ethers.formatUnits(stakeBaseBefore, 18)} → ${ethers.formatUnits(stakeBaseAfter, 18)} TRAC`, + ); + console.log(` ✅ Rolling rewards reset: ${rollingRewards}`); + }); + + it('1E - New delegator joins after index>0', async function () { + console.log('\n👤 TEST 1E: New delegator joins after index>0'); + + const currentEpoch = await contracts.chronos.getCurrentEpoch(); + + // Setup: existing delegator stakes and node submits proof + const initialStake = toTRAC(100); + await contracts.token + .connect(accounts.delegator1) + .approve(await contracts.staking.getAddress(), initialStake); + await contracts.staking + .connect(accounts.delegator1) + .stake(node1Id, initialStake); + + await contracts.randomSampling.updateAndGetActiveProofPeriodStartBlock(); + const setupStake = toTRAC(100); // from beforeEach setup + await submitProofAndVerifyScore( + node1Id, + accounts.node1, + contracts, + currentEpoch, + setupStake + initialStake, + ); + + // Trigger score settlement by doing a minimal stake operation for existing delegator + await contracts.token + .connect(accounts.delegator1) + .approve(await contracts.staking.getAddress(), toTRAC(1)); + await contracts.staking + .connect(accounts.delegator1) + .stake(node1Id, toTRAC(1)); + + // Verify index > 0 after proof + const indexAfterProof = + await contracts.randomSamplingStorage.getNodeEpochScorePerStake( + currentEpoch, + node1Id, + ); + expect(indexAfterProof).to.be.gt(0n, 'Index should be > 0 after proof'); + console.log(` 📊 Index after proof: ${indexAfterProof}`); + + // New delegator (delegator2) joins + const newDelegatorStake = toTRAC(60); + await contracts.token + .connect(accounts.delegator2) + .approve(await contracts.staking.getAddress(), newDelegatorStake); + await contracts.staking + .connect(accounts.delegator2) + .stake(node1Id, newDelegatorStake); + + // **DELEGATOR SCORING ASSERTIONS** + const newDelegatorScore = + await contracts.randomSamplingStorage.getEpochNodeDelegatorScore( + currentEpoch, + node1Id, + d2Key, + ); + expect(newDelegatorScore).to.equal( + 0n, + '**epochNodeDelegatorScore should be 0 for new delegator**', + ); + + // Last-settled index should be bumped to current value + const newDelegatorLastSettled = + await contracts.randomSamplingStorage.getDelegatorLastSettledNodeEpochScorePerStake( + currentEpoch, + node1Id, + d2Key, + ); + const currentIndex = + await contracts.randomSamplingStorage.getNodeEpochScorePerStake( + currentEpoch, + node1Id, + ); + expect(newDelegatorLastSettled).to.equal( + currentIndex, + '**Last-settled index should be bumped to current value**', + ); + + // Verify stake amounts + const newDelegatorStakeBase = + await contracts.stakingStorage.getDelegatorStakeBase(node1Id, d2Key); + expect(newDelegatorStakeBase).to.equal( + newDelegatorStake, + 'New delegator stake base should equal stake amount', + ); + + // Verify existing delegator is unaffected + const existingDelegatorScore = + await contracts.randomSamplingStorage.getEpochNodeDelegatorScore( + currentEpoch, + node1Id, + d1Key, + ); + expect(existingDelegatorScore).to.be.gt( + 0n, + 'Existing delegator should still have score', + ); + + console.log( + ` ✅ New delegator score: ${newDelegatorScore} (expected: 0)`, + ); + console.log( + ` ✅ New delegator last settled index: ${newDelegatorLastSettled}`, + ); + console.log(` ✅ Current index: ${currentIndex}`); + console.log( + ` ✅ New delegator stake base: ${ethers.formatUnits(newDelegatorStakeBase, 18)} TRAC`, + ); + console.log( + ` ✅ Existing delegator score unchanged: ${existingDelegatorScore}`, + ); + }); + }); + + describe('Suite 2: Advanced Delegator Scoring', function () { + it('2A - Join in epoch E when score only in E-1', async function () { + console.log('\n🕐 TEST 2A: Join in epoch E when score only in E-1'); + + const startEpoch = await contracts.chronos.getCurrentEpoch(); + console.log(` ℹ️ Starting epoch: ${startEpoch}`); + + // Step 1: Node proof in E-1 (current epoch) + await contracts.randomSampling.updateAndGetActiveProofPeriodStartBlock(); + const setupStake = toTRAC(100); // from beforeEach setup + await submitProofAndVerifyScore( + node1Id, + accounts.node1, + contracts, + startEpoch, + setupStake, + ); + + // Step 2: Advance to epoch E (next epoch) + const timeUntilNext = await contracts.chronos.timeUntilNextEpoch(); + await time.increase(timeUntilNext + 1n); + const nextEpoch = await contracts.chronos.getCurrentEpoch(); + expect(nextEpoch).to.equal(startEpoch + 1n); + console.log(` ⏭️ Advanced to epoch: ${nextEpoch}`); + + // Step 3: Delegator stakes in new epoch E + const stakeAmount = toTRAC(80); + await contracts.token + .connect(accounts.delegator1) + .approve(await contracts.staking.getAddress(), stakeAmount); + await contracts.staking + .connect(accounts.delegator1) + .stake(node1Id, stakeAmount); + + // **DELEGATOR SCORING ASSERTIONS** + const delegatorScoreInPrevEpoch = + await contracts.randomSamplingStorage.getEpochNodeDelegatorScore( + startEpoch, // E-1 + node1Id, + d1Key, + ); + expect(delegatorScoreInPrevEpoch).to.equal( + 0n, + '**epochNodeDelegatorScore(E-1) should be 0**', + ); + + const delegatorScoreInCurrentEpoch = + await contracts.randomSamplingStorage.getEpochNodeDelegatorScore( + nextEpoch, // E + node1Id, + d1Key, + ); + expect(delegatorScoreInCurrentEpoch).to.equal( + 0n, + 'epochNodeDelegatorScore(E) should also be 0 initially', + ); + + console.log( + ` ✅ Delegator score in epoch ${startEpoch}: ${delegatorScoreInPrevEpoch} (expected: 0)`, + ); + console.log( + ` ✅ Delegator score in epoch ${nextEpoch}: ${delegatorScoreInCurrentEpoch} (expected: 0)`, + ); + }); + + it('2B - Stake→proof→withdraw→stake (three settlements)', async function () { + console.log( + '\n🔄 TEST 2B: Stake→proof→withdraw→stake (three settlements)', + ); + + const currentEpoch = await contracts.chronos.getCurrentEpoch(); + + // Step 1: stake(40) + const initialStake = toTRAC(40); + await contracts.token + .connect(accounts.delegator1) + .approve(await contracts.staking.getAddress(), initialStake); + await contracts.staking + .connect(accounts.delegator1) + .stake(node1Id, initialStake); + + const scoreAfterStake1 = + await contracts.randomSamplingStorage.getEpochNodeDelegatorScore( + currentEpoch, + node1Id, + d1Key, + ); + + // Step 2: proof + await contracts.randomSampling.updateAndGetActiveProofPeriodStartBlock(); + const setupStake = toTRAC(100); // from beforeEach setup + await submitProofAndVerifyScore( + node1Id, + accounts.node1, + contracts, + currentEpoch, + setupStake + initialStake, + ); + + // Step 3: withdraw(10) - triggers first settlement + const withdrawAmount = toTRAC(10); + await contracts.staking + .connect(accounts.delegator1) + .requestWithdrawal(node1Id, withdrawAmount); + + const scoreAfterWithdraw = + await contracts.randomSamplingStorage.getEpochNodeDelegatorScore( + currentEpoch, + node1Id, + d1Key, + ); + const indexAfterWithdraw = + await contracts.randomSamplingStorage.getDelegatorLastSettledNodeEpochScorePerStake( + currentEpoch, + node1Id, + d1Key, + ); + + // Step 4: stake(30) - triggers second settlement + const additionalStake = toTRAC(30); + await contracts.token + .connect(accounts.delegator1) + .approve(await contracts.staking.getAddress(), additionalStake); + await contracts.staking + .connect(accounts.delegator1) + .stake(node1Id, additionalStake); + + const scoreAfterStake2 = + await contracts.randomSamplingStorage.getEpochNodeDelegatorScore( + currentEpoch, + node1Id, + d1Key, + ); + const indexAfterStake2 = + await contracts.randomSamplingStorage.getDelegatorLastSettledNodeEpochScorePerStake( + currentEpoch, + node1Id, + d1Key, + ); + + // **DELEGATOR SCORING ASSERTIONS** + const currentIndex = + await contracts.randomSamplingStorage.getNodeEpochScorePerStake( + currentEpoch, + node1Id, + ); + + // Manual calculation: first settlement should give score, subsequent settlements with same index give 0 additional score + const SCALE18 = ethers.parseUnits('1', 18); + const expectedScoreIncrement = (initialStake * currentIndex) / SCALE18; + + console.log(` 📊 Score progression:`); + console.log(` • After stake(40): ${scoreAfterStake1}`); + console.log( + ` • After withdraw(10): ${scoreAfterWithdraw} (should have score from proof period)`, + ); + console.log( + ` • After stake(30): ${scoreAfterStake2} (same as withdraw, no new score)`, + ); + console.log(` 🧮 Expected score increment: ${expectedScoreIncrement}`); + + expect(scoreAfterWithdraw).to.equal( + expectedScoreIncrement, + '**Sum of settlements should equal manual formula**', + ); + expect(scoreAfterStake2).to.equal( + scoreAfterWithdraw, + 'No additional score when index unchanged', + ); + + // Check that index was updated properly + expect(indexAfterWithdraw).to.equal( + currentIndex, + 'Index should be updated after withdrawal', + ); + expect(indexAfterStake2).to.equal( + currentIndex, + 'Index should remain current after additional stake', + ); + + console.log( + ` ✅ Three settlements completed with correct score accumulation`, + ); + }); + + it('2C - Withdraw *all* after earning score', async function () { + console.log('\n📤 TEST 2C: Withdraw all after earning score'); + + const currentEpoch = await contracts.chronos.getCurrentEpoch(); + + // Setup: stake and earn score + const stakeAmount = toTRAC(80); + await contracts.token + .connect(accounts.delegator1) + .approve(await contracts.staking.getAddress(), stakeAmount); + await contracts.staking + .connect(accounts.delegator1) + .stake(node1Id, stakeAmount); + + // Node proof to enable score earning + await contracts.randomSampling.updateAndGetActiveProofPeriodStartBlock(); + const setupStake = toTRAC(100); // from beforeEach setup + await submitProofAndVerifyScore( + node1Id, + accounts.node1, + contracts, + currentEpoch, + setupStake + stakeAmount, + ); + + // Trigger score settlement with minimal stake + await contracts.token + .connect(accounts.delegator1) + .approve(await contracts.staking.getAddress(), toTRAC(1)); + await contracts.staking + .connect(accounts.delegator1) + .stake(node1Id, toTRAC(1)); + + const scoreAfterEarning = + await contracts.randomSamplingStorage.getEpochNodeDelegatorScore( + currentEpoch, + node1Id, + d1Key, + ); + console.log(` 📊 Score after earning: ${scoreAfterEarning}`); + + // Withdraw all stake + const totalStake = await contracts.stakingStorage.getDelegatorStakeBase( + node1Id, + d1Key, + ); + await contracts.staking + .connect(accounts.delegator1) + .requestWithdrawal(node1Id, totalStake); + + // **DELEGATOR SCORING ASSERTIONS** + const scoreAfterWithdrawal = + await contracts.randomSamplingStorage.getEpochNodeDelegatorScore( + currentEpoch, + node1Id, + d1Key, + ); + expect(scoreAfterWithdrawal).to.equal( + scoreAfterEarning, + '**No further score accrual after withdrawal**', + ); + + // Check lastStakeHeldEpoch + const lastStakeHeldEpoch = + await contracts.delegatorsInfo.getLastStakeHeldEpoch( + node1Id, + accounts.delegator1.address, + ); + expect(lastStakeHeldEpoch).to.equal( + currentEpoch, + '**lastStakeHeldEpoch should equal current epoch**', + ); + + // Delegator should still be in the list (not removed immediately due to earned score) + const isDelegator = await contracts.delegatorsInfo.isNodeDelegator( + node1Id, + accounts.delegator1.address, + ); + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + expect(isDelegator).to.be.true; + + console.log( + ` ✅ Score unchanged after withdrawal: ${scoreAfterWithdrawal}`, + ); + console.log(` ✅ Last stake held epoch: ${lastStakeHeldEpoch}`); + console.log(` ✅ Delegator kept in list (scored in current epoch)`); + }); + + it('2D - Withdraw *all* before any score', async function () { + console.log('\n📤 TEST 2D: Withdraw all before any score'); + + const currentEpoch = await contracts.chronos.getCurrentEpoch(); + + // Step 1: stake(50) + const stakeAmount = toTRAC(50); + await contracts.token + .connect(accounts.delegator1) + .approve(await contracts.staking.getAddress(), stakeAmount); + await contracts.staking + .connect(accounts.delegator1) + .stake(node1Id, stakeAmount); + + // Step 2: requestWithdrawal(all) - NO proof yet + await contracts.staking + .connect(accounts.delegator1) + .requestWithdrawal(node1Id, stakeAmount); + + // **DELEGATOR SCORING ASSERTIONS** + const delegatorScore = + await contracts.randomSamplingStorage.getEpochNodeDelegatorScore( + currentEpoch, + node1Id, + d1Key, + ); + expect(delegatorScore).to.equal( + 0n, + '**epochNodeDelegatorScore should be 0**', + ); + + // Delegator should be removed from node list since no score was earned + const isDelegator = await contracts.delegatorsInfo.isNodeDelegator( + node1Id, + accounts.delegator1.address, + ); + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + expect(isDelegator).to.be.false; + + const stakeBase = await contracts.stakingStorage.getDelegatorStakeBase( + node1Id, + d1Key, + ); + expect(stakeBase).to.equal(0n, 'Stake base should be 0'); + + console.log(` ✅ Delegator score: ${delegatorScore} (expected: 0)`); + console.log(` ✅ Delegator removed from node list: ${!isDelegator}`); + console.log( + ` ✅ Stake base: ${ethers.formatUnits(stakeBase, 18)} TRAC`, + ); + }); + + it('2E - Redelegate half A→B mid-epoch', async function () { + console.log('\n🔄 TEST 2E: Redelegate half A→B mid-epoch'); + + const currentEpoch = await contracts.chronos.getCurrentEpoch(); + const nodeAId = node1Id; + const nodeBId = nodeIds.node2Id; + + // Setup: delegator stakes to node A + const initialStake = toTRAC(100); + await contracts.token + .connect(accounts.delegator1) + .approve(await contracts.staking.getAddress(), initialStake); + await contracts.staking + .connect(accounts.delegator1) + .stake(nodeAId, initialStake); + + // Proof on node A + await contracts.randomSampling.updateAndGetActiveProofPeriodStartBlock(); + const setupStake = toTRAC(100); // from beforeEach setup + await submitProofAndVerifyScore( + nodeAId, + accounts.node1, + contracts, + currentEpoch, + setupStake + initialStake, + ); + + // Trigger score settlement on A by minimal stake + await contracts.token + .connect(accounts.delegator1) + .approve(await contracts.staking.getAddress(), toTRAC(1)); + await contracts.staking + .connect(accounts.delegator1) + .stake(nodeAId, toTRAC(1)); + + const scoreOnABeforeRedelegate = + await contracts.randomSamplingStorage.getEpochNodeDelegatorScore( + currentEpoch, + nodeAId, + d1Key, + ); + + // Redelegate half to node B + const redelegateAmount = toTRAC(50.5); // half of 101 + await contracts.staking + .connect(accounts.delegator1) + .redelegate(nodeAId, nodeBId, redelegateAmount); + + // **DELEGATOR SCORING ASSERTIONS** + const scoreOnAAfterRedelegate = + await contracts.randomSamplingStorage.getEpochNodeDelegatorScore( + currentEpoch, + nodeAId, + d1Key, + ); + const scoreOnB = + await contracts.randomSamplingStorage.getEpochNodeDelegatorScore( + currentEpoch, + nodeBId, + d1Key, + ); + + expect(scoreOnAAfterRedelegate).to.equal( + scoreOnABeforeRedelegate, + '**Score should remain on A side**', + ); + expect(scoreOnB).to.equal( + 0n, + '**epochNodeDelegatorScore(B) should be 0**', + ); + + // B's last-settled index should equal A's at moment of move + const lastSettledIndexOnB = + await contracts.randomSamplingStorage.getDelegatorLastSettledNodeEpochScorePerStake( + currentEpoch, + nodeBId, + d1Key, + ); + const currentIndexOnB = + await contracts.randomSamplingStorage.getNodeEpochScorePerStake( + currentEpoch, + nodeBId, + ); + + expect(lastSettledIndexOnB).to.equal( + currentIndexOnB, + "**B's last-settled index should be current**", + ); + + console.log(` ✅ Score on A: ${scoreOnAAfterRedelegate} (unchanged)`); + console.log(` ✅ Score on B: ${scoreOnB} (expected: 0)`); + console.log(` ✅ B's settled index: ${lastSettledIndexOnB}`); + }); + + it('2F - restakeOperatorFee', async function () { + console.log('\n💰 TEST 2F: restakeOperatorFee'); + // Setup: Manually set some operator fee for testing (avoiding complex reward claiming setup) + const restakeAmount = toTRAC(20); + await contracts.stakingStorage + .connect(accounts.owner) + .setOperatorFeeBalance(node1Id, restakeAmount); + + const operatorFeeBalanceBefore = + await contracts.stakingStorage.getOperatorFeeBalance(node1Id); + console.log( + ` 💰 Operator fee balance set: ${ethers.formatUnits(operatorFeeBalanceBefore, 18)} TRAC`, + ); + + // Admin restakes operator fee + await contracts.staking + .connect(accounts.node1.admin) + .restakeOperatorFee(node1Id, restakeAmount); + + // **DELEGATOR SCORING ASSERTIONS** + const operatorFeeBalanceAfter = + await contracts.stakingStorage.getOperatorFeeBalance(node1Id); + const adminStakeBase = + await contracts.stakingStorage.getDelegatorStakeBase( + node1Id, + ethers.keccak256( + ethers.solidityPacked(['address'], [accounts.node1.admin.address]), + ), + ); + + expect(operatorFeeBalanceAfter).to.equal( + 0n, + '**Fee balance should be depleted**', + ); + expect(adminStakeBase).to.equal( + restakeAmount, + '**Admin stake base should equal restaked amount**', + ); + + console.log( + ` ✅ Fee balance: ${ethers.formatUnits(operatorFeeBalanceBefore, 18)} → ${ethers.formatUnits(operatorFeeBalanceAfter, 18)} TRAC`, + ); + console.log( + ` ✅ Admin stake base: ${ethers.formatUnits(adminStakeBase, 18)} TRAC`, + ); + }); + + it('2G - Early-exit path (Δindex = 0)', async function () { + console.log('\n⚡ TEST 2G: Early-exit path (Δindex = 0)'); + + const currentEpoch = await contracts.chronos.getCurrentEpoch(); + + // Setup: stake and establish some score + const stakeAmount = toTRAC(100); + await contracts.token + .connect(accounts.delegator1) + .approve(await contracts.staking.getAddress(), stakeAmount); + await contracts.staking + .connect(accounts.delegator1) + .stake(node1Id, stakeAmount); + + // Submit proof to establish non-zero index + await contracts.randomSampling.updateAndGetActiveProofPeriodStartBlock(); + const setupStake = toTRAC(100); // from beforeEach setup + await submitProofAndVerifyScore( + node1Id, + accounts.node1, + contracts, + currentEpoch, + setupStake + stakeAmount, + ); + + // Trigger settlement once + await contracts.token + .connect(accounts.delegator1) + .approve(await contracts.staking.getAddress(), toTRAC(1)); + await contracts.staking + .connect(accounts.delegator1) + .stake(node1Id, toTRAC(1)); + + const scoreBefore = + await contracts.randomSamplingStorage.getEpochNodeDelegatorScore( + currentEpoch, + node1Id, + d1Key, + ); + + // Call stake change path again with no new proofs (Δindex = 0) + await contracts.token + .connect(accounts.delegator1) + .approve(await contracts.staking.getAddress(), toTRAC(1)); + await contracts.staking + .connect(accounts.delegator1) + .stake(node1Id, toTRAC(1)); + + // **DELEGATOR SCORING ASSERTIONS** + const scoreAfter = + await contracts.randomSamplingStorage.getEpochNodeDelegatorScore( + currentEpoch, + node1Id, + d1Key, + ); + + expect(scoreAfter).to.equal( + scoreBefore, + '**Delegator score should be identical pre-/post-call**', + ); + + console.log(` ✅ Score before: ${scoreBefore}`); + console.log(` ✅ Score after: ${scoreAfter} (identical)`); + console.log( + ` ✅ Early-exit path correctly prevents unnecessary computation`, + ); + }); + + it('2H - Proof after stake→withdrawAll', async function () { + console.log('\n🔬 TEST 2H: Proof after stake→withdrawAll'); + + const currentEpoch = await contracts.chronos.getCurrentEpoch(); + + // Step 1: stake(40) + const stakeAmount = toTRAC(40); + await contracts.token + .connect(accounts.delegator1) + .approve(await contracts.staking.getAddress(), stakeAmount); + await contracts.staking + .connect(accounts.delegator1) + .stake(node1Id, stakeAmount); + + // Step 2: withdrawAll + await contracts.staking + .connect(accounts.delegator1) + .requestWithdrawal(node1Id, stakeAmount); + + const scoreBeforeProof = + await contracts.randomSamplingStorage.getEpochNodeDelegatorScore( + currentEpoch, + node1Id, + d1Key, + ); + const lastSettledBefore = + await contracts.randomSamplingStorage.getDelegatorLastSettledNodeEpochScorePerStake( + currentEpoch, + node1Id, + d1Key, + ); + + // Step 3: Node proof (delegator has zero stake) + await contracts.randomSampling.updateAndGetActiveProofPeriodStartBlock(); + const setupStake = toTRAC(100); // from beforeEach setup + await submitProofAndVerifyScore( + node1Id, + accounts.node1, + contracts, + currentEpoch, + setupStake, // only setup stake, delegator withdrew + ); + + // Trigger settlement for delegator by small stake operation + await contracts.token + .connect(accounts.delegator1) + .approve(await contracts.staking.getAddress(), toTRAC(1)); + await contracts.staking + .connect(accounts.delegator1) + .stake(node1Id, toTRAC(1)); + + const scoreAfterProof = + await contracts.randomSamplingStorage.getEpochNodeDelegatorScore( + currentEpoch, + node1Id, + d1Key, + ); + const lastSettledAfter = + await contracts.randomSamplingStorage.getDelegatorLastSettledNodeEpochScorePerStake( + currentEpoch, + node1Id, + d1Key, + ); + const currentIndex = + await contracts.randomSamplingStorage.getNodeEpochScorePerStake( + currentEpoch, + node1Id, + ); + + // **DELEGATOR SCORING ASSERTIONS** + expect(scoreAfterProof).to.equal( + scoreBeforeProof, + '**No score added (zero stake)**', + ); + expect(lastSettledAfter).to.equal( + currentIndex, + '**Last-settled index should be bumped**', + ); + + console.log( + ` ✅ Score unchanged: ${scoreBeforeProof} → ${scoreAfterProof}`, + ); + console.log( + ` ✅ Last settled index: ${lastSettledBefore} → ${lastSettledAfter}`, + ); + console.log(` ✅ Index bumped despite zero stake`); + }); + + it('2I - Stress: 10 delegators random stakes', async function () { + console.log('\n🎯 TEST 2I: Stress test with 10 delegators'); + + const currentEpoch = await contracts.chronos.getCurrentEpoch(); + const signers = await hre.ethers.getSigners(); + const delegators = [ + accounts.delegator1, + accounts.delegator2, + accounts.delegator3, + signers[51], + signers[52], + signers[53], + signers[54], + signers[55], + signers[56], + ]; + + const stakes = [ + toTRAC(100), + toTRAC(150), + toTRAC(200), + toTRAC(50), + toTRAC(75), + toTRAC(120), + toTRAC(80), + toTRAC(300), + toTRAC(25), + ]; + const totalDelegatorStake = stakes.reduce( + (sum, stake) => sum + stake, + 0n, + ); + console.log( + ` 📊 Total delegator stakes: ${ethers.formatUnits(totalDelegatorStake, 18)} TRAC`, + ); + + // Mint tokens and stake for all delegators + for (let i = 0; i < delegators.length; i++) { + await contracts.token.mint(delegators[i].address, stakes[i]); + await contracts.token + .connect(delegators[i]) + .approve(await contracts.staking.getAddress(), stakes[i]); + await contracts.staking + .connect(delegators[i]) + .stake(node1Id, stakes[i]); + } + + // Add node1.operational as a delegator - from beforeEach setup + delegators.push(accounts.node1.operational); + stakes.push(toTRAC(100)); + + // Node proof + await contracts.randomSampling.updateAndGetActiveProofPeriodStartBlock(); + + // Submit proof manually for stress test (bypassing expected score checks) + console.log(` 📋 Submitting proof for node ${node1Id}...`); + await contracts.randomSampling + .connect(accounts.node1.operational) + .createChallenge(); + + // Get the challenge details to construct proper proof + const challenge = + await contracts.randomSamplingStorage.getNodeChallenge(node1Id); + const chunks = kcTools.splitIntoChunks(quads, 32); + const chunkId = Number(challenge[1]); + const { proof } = kcTools.calculateMerkleProof(quads, 32, chunkId); + await contracts.randomSampling + .connect(accounts.node1.operational) + .submitProof(chunks[chunkId], proof); + + // await contracts.randomSampling + // .connect(accounts.node1.operational) + // .submitProof(chunk, []); + + // Settle scores for all delegators with minimal stakes + for (const delegator of delegators) { + await contracts.token.mint(delegator.address, toTRAC(1)); + await contracts.token + .connect(delegator) + .approve(await contracts.staking.getAddress(), toTRAC(1)); + await contracts.staking.connect(delegator).stake(node1Id, toTRAC(1)); + } + + // **DELEGATOR SCORING ASSERTIONS** + const nodeScorePerStake = + await contracts.randomSamplingStorage.getNodeEpochScorePerStake( + currentEpoch, + node1Id, + ); + let totalDelegatorScore = 0n; + for (let i = 0; i < delegators.length; i++) { + const delegatorKey = ethers.keccak256( + ethers.solidityPacked(['address'], [delegators[i].address]), + ); + const delegatorScore = + await contracts.randomSamplingStorage.getEpochNodeDelegatorScore( + currentEpoch, + node1Id, + delegatorKey, + ); + totalDelegatorScore += delegatorScore; + + const expectedRatio = (stakes[i] * 10000n) / totalDelegatorStake; // basis points + const actualRatio = (delegatorScore * 10000n) / totalDelegatorScore; + + // Calculate expected delegator score based on their stake and the node's score per stake + const expectedDelegatorScore = calculateExpectedDelegatorScore( + stakes[i], + nodeScorePerStake, + 0n, // all delegators start from 0 + ); + expect(delegatorScore).to.equal( + expectedDelegatorScore, + `Delegator ${i + 1} score should equal calculated value`, + ); + + console.log( + ` • Delegator ${i + 1}: ${ethers.formatUnits(delegatorScore, 18)} score, ratio ${actualRatio}bp (expected ~${expectedRatio}bp)`, + ); + } + + const nodeScore = await contracts.randomSamplingStorage.getNodeEpochScore( + currentEpoch, + node1Id, + ); + const scoreDiff = + nodeScore > totalDelegatorScore + ? nodeScore - totalDelegatorScore + : totalDelegatorScore - nodeScore; + + expect(scoreDiff).to.be.equal(0, '**Σ delegatorScore ≈ nodeScore**'); + + console.log(` ✅ Total delegator score: ${totalDelegatorScore}`); + console.log(` ✅ Node score: ${nodeScore}`); + console.log(` ✅ Difference: ${scoreDiff} wei (≤10 wei)`); + }); + + it('2J - cancelWithdrawal() split restake', async function () { + console.log('\n🔄 TEST 2J: cancelWithdrawal split restake'); + + const currentEpoch = await contracts.chronos.getCurrentEpoch(); + + // Setup: stake and withdraw + const initialStake = toTRAC(100); + await contracts.token + .connect(accounts.delegator1) + .approve(await contracts.staking.getAddress(), initialStake); + await contracts.staking + .connect(accounts.delegator1) + .stake(node1Id, initialStake); + + const withdrawAmount = toTRAC(70); + await contracts.staking + .connect(accounts.delegator1) + .requestWithdrawal(node1Id, withdrawAmount); + + // Set maximum stake lower to trigger split scenario + await contracts.parametersStorage.setMaximumStake(toTRAC(150)); + + const scoreBefore = + await contracts.randomSamplingStorage.getEpochNodeDelegatorScore( + currentEpoch, + node1Id, + d1Key, + ); + + const stakeBaseBefore = + await contracts.stakingStorage.getDelegatorStakeBase(node1Id, d1Key); + const nodeStakeBefore = + await contracts.stakingStorage.getNodeStake(node1Id); + + // Cancel withdrawal (should partially restake due to max stake limit) + await contracts.staking + .connect(accounts.delegator1) + .cancelWithdrawal(node1Id); + + // **DELEGATOR SCORING ASSERTIONS** + const scoreAfter = + await contracts.randomSamplingStorage.getEpochNodeDelegatorScore( + currentEpoch, + node1Id, + d1Key, + ); + + const stakeBaseAfter = + await contracts.stakingStorage.getDelegatorStakeBase(node1Id, d1Key); + const nodeStakeAfter = + await contracts.stakingStorage.getNodeStake(node1Id); + + // Check withdrawal request for remaining pending amount + const [pendingAmount, ,] = + await contracts.stakingStorage.getDelegatorWithdrawalRequest( + node1Id, + d1Key, + ); + + expect(scoreAfter).to.equal( + scoreBefore, + '**Single new Δscore (no double count)**', + ); + expect(stakeBaseAfter).to.be.equal( + stakeBaseBefore + toTRAC(20), + 'Some amount should be restaked', + ); + expect(nodeStakeAfter).to.be.equal( + nodeStakeBefore + toTRAC(20), + 'Some amount should be restaked', + ); + expect(pendingAmount).to.be.equal( + withdrawAmount - toTRAC(20), + 'Some amount should remain pending', + ); + + console.log(` ✅ Score unchanged: ${scoreBefore} → ${scoreAfter}`); + console.log( + ` ✅ Stake base: ${ethers.formatUnits(stakeBaseBefore, 18)} → ${ethers.formatUnits(stakeBaseAfter, 18)} TRAC`, + ); + console.log( + ` ✅ Pending withdrawal: ${ethers.formatUnits(pendingAmount, 18)} TRAC`, + ); + }); + + it('2K - Two proofs same epoch with stake change', async function () { + console.log('\n🔬 TEST 2K: Two proofs same epoch with stake change'); + + const currentEpoch = await contracts.chronos.getCurrentEpoch(); + + // Step 1: Stake 100 + const initialStake = toTRAC(100); + await contracts.token + .connect(accounts.delegator1) + .approve(await contracts.staking.getAddress(), initialStake); + await contracts.staking + .connect(accounts.delegator1) + .stake(node1Id, initialStake); + + // Step 2: proof₁ + await contracts.randomSampling.updateAndGetActiveProofPeriodStartBlock(); + const setupStake = toTRAC(100); // from beforeEach setup + await submitProofAndVerifyScore( + node1Id, + accounts.node1, + contracts, + currentEpoch, + setupStake + initialStake, + ); + + const index1 = + await contracts.randomSamplingStorage.getNodeEpochScorePerStake( + currentEpoch, + node1Id, + ); + + // Step 3: Stake +50 + const additionalStake = toTRAC(50); + await contracts.token + .connect(accounts.delegator1) + .approve(await contracts.staking.getAddress(), additionalStake); + await contracts.staking + .connect(accounts.delegator1) + .stake(node1Id, additionalStake); + + // Step 4: proof₂ + await advanceToNextProofingPeriod(contracts); + await submitProofAndVerifyScore( + node1Id, + accounts.node1, + contracts, + currentEpoch, + setupStake + initialStake + additionalStake, + ); + + const index2 = + await contracts.randomSamplingStorage.getNodeEpochScorePerStake( + currentEpoch, + node1Id, + ); + + // Trigger final settlement + await contracts.token + .connect(accounts.delegator1) + .approve(await contracts.staking.getAddress(), toTRAC(1)); + await contracts.staking + .connect(accounts.delegator1) + .stake(node1Id, toTRAC(1)); + + // **DELEGATOR SCORING ASSERTIONS** + const finalScore = + await contracts.randomSamplingStorage.getEpochNodeDelegatorScore( + currentEpoch, + node1Id, + d1Key, + ); + + const SCALE18 = ethers.parseUnits('1', 18); + const delta1 = index1 - 0n; // from 0 to index1 + const delta2 = index2 - index1; // from index1 to index2 + const expectedScore = + (initialStake * delta1) / SCALE18 + + ((initialStake + additionalStake) * delta2) / SCALE18; + + console.log(` 🧮 Expected calculation:`); + console.log( + ` • 100 TRAC × ${delta1} / 1e18 = ${(initialStake * delta1) / SCALE18}`, + ); + console.log( + ` • 150 TRAC × ${delta2} / 1e18 = ${((initialStake + additionalStake) * delta2) / SCALE18}`, + ); + console.log(` • Total expected: ${expectedScore}`); + console.log(` • Actual score: ${finalScore}`); + + expect(finalScore).to.equal( + expectedScore, + '**Total score should equal 100·Δ₁ + 150·Δ₂**', + ); + + console.log(` ✅ Two-proof calculation correct: ${finalScore}`); + }); + }); + + describe('Suite 3: Multi-Node & Advanced Claiming', function () { + it('3A - 2 nodes ×3 delegators each', async function () { + console.log('\n🌐 TEST 3A: 2 nodes ×3 delegators each'); + + const currentEpoch = await contracts.chronos.getCurrentEpoch(); + const nodeAId = node1Id; + const nodeBId = nodeIds.node2Id; + + // Setup: 3 delegators on each node with balanced stakes + const delegatorsA = [ + accounts.delegator1, + accounts.delegator2, + accounts.delegator3, + ]; + const delegatorsB = [ + accounts.receiver1?.operational, + accounts.receiver2?.operational, + accounts.receiver3?.operational, + ].filter(Boolean); + const stakesA = [toTRAC(100), toTRAC(150), toTRAC(200)]; // Total: 450 + const stakesB = [toTRAC(120), toTRAC(150), toTRAC(180)]; // Total: 450 (balanced) + + console.log(` 📊 Setting up Node A (${nodeAId}) with 3 delegators`); + // Stake on Node A + for (let i = 0; i < delegatorsA.length; i++) { + await contracts.token.mint(delegatorsA[i].address, stakesA[i]); + await contracts.token + .connect(delegatorsA[i]) + .approve(await contracts.staking.getAddress(), stakesA[i]); + await contracts.staking + .connect(delegatorsA[i]) + .stake(nodeAId, stakesA[i]); + } + + console.log(` 📊 Setting up Node B (${nodeBId}) with 3 delegators`); + // Stake on Node B + for (let i = 0; i < delegatorsB.length; i++) { + await contracts.token.mint(delegatorsB[i].address, stakesB[i]); + await contracts.token + .connect(delegatorsB[i]) + .approve(await contracts.staking.getAddress(), stakesB[i]); + await contracts.staking + .connect(delegatorsB[i]) + .stake(nodeBId, stakesB[i]); + } + + // Both nodes submit proofs + await contracts.randomSampling.updateAndGetActiveProofPeriodStartBlock(); + + // Node A submits proof + console.log(` 📋 Node A submitting proof...`); + await contracts.randomSampling + .connect(accounts.node1.operational) + .createChallenge(); + const challengeA = + await contracts.randomSamplingStorage.getNodeChallenge(nodeAId); + const chunksA = kcTools.splitIntoChunks(quads, 32); + const chunkIdA = Number(challengeA[1]); + const { proof: proofA } = kcTools.calculateMerkleProof( + quads, + 32, + chunkIdA, + ); + await contracts.randomSampling + .connect(accounts.node1.operational) + .submitProof(chunksA[chunkIdA], proofA); + + // Advance to next proof period for Node B + await advanceToNextProofingPeriod(contracts); + + // Node B submits proof + console.log(` 📋 Node B submitting proof...`); + await contracts.randomSampling + .connect(accounts.node2.operational) + .createChallenge(); + const challengeB = + await contracts.randomSamplingStorage.getNodeChallenge(nodeBId); + const chunksB = kcTools.splitIntoChunks(quads, 32); + const chunkIdB = Number(challengeB[1]); + const { proof: proofB } = kcTools.calculateMerkleProof( + quads, + 32, + chunkIdB, + ); + await contracts.randomSampling + .connect(accounts.node2.operational) + .submitProof(chunksB[chunkIdB], proofB); + + // Settle scores for all delegators (do multiple settlements to ensure all score is captured) + console.log(` ⚙️ Settling scores for all delegators...`); + for (let round = 0; round < 2; round++) { + for (const delegator of delegatorsA) { + await contracts.token.mint(delegator.address, toTRAC(1)); + await contracts.token + .connect(delegator) + .approve(await contracts.staking.getAddress(), toTRAC(1)); + await contracts.staking.connect(delegator).stake(nodeAId, toTRAC(1)); + } + for (const delegator of delegatorsB) { + await contracts.token.mint(delegator.address, toTRAC(1)); + await contracts.token + .connect(delegator) + .approve(await contracts.staking.getAddress(), toTRAC(1)); + await contracts.staking.connect(delegator).stake(nodeBId, toTRAC(1)); + } + } + + // **DELEGATOR SCORING ASSERTIONS** + let totalDelegatorScoreA = 0n; + let totalDelegatorScoreB = 0n; + + // Check Node A delegators + for (let i = 0; i < delegatorsA.length; i++) { + const delegatorKey = ethers.keccak256( + ethers.solidityPacked(['address'], [delegatorsA[i].address]), + ); + const delegatorScore = + await contracts.randomSamplingStorage.getEpochNodeDelegatorScore( + currentEpoch, + nodeAId, + delegatorKey, + ); + totalDelegatorScoreA += delegatorScore; + console.log( + ` • Node A Delegator ${i + 1}: ${ethers.formatUnits(delegatorScore, 18)} score`, + ); + } + + // Check Node B delegators + for (let i = 0; i < delegatorsB.length; i++) { + const delegatorKey = ethers.keccak256( + ethers.solidityPacked(['address'], [delegatorsB[i].address]), + ); + const delegatorScore = + await contracts.randomSamplingStorage.getEpochNodeDelegatorScore( + currentEpoch, + nodeBId, + delegatorKey, + ); + totalDelegatorScoreB += delegatorScore; + console.log( + ` • Node B Delegator ${i + 1}: ${ethers.formatUnits(delegatorScore, 18)} score`, + ); + } + + const nodeScoreA = + await contracts.randomSamplingStorage.getNodeEpochScore( + currentEpoch, + nodeAId, + ); + const nodeScoreB = + await contracts.randomSamplingStorage.getNodeEpochScore( + currentEpoch, + nodeBId, + ); + const allNodesScore = + await contracts.randomSamplingStorage.getAllNodesEpochScore( + currentEpoch, + ); + + // Per node: ΣdelegatorScore == nodeScore (check each individually) + const scoreDiffA = + nodeScoreA > totalDelegatorScoreA + ? nodeScoreA - totalDelegatorScoreA + : totalDelegatorScoreA - nodeScoreA; + const scoreDiffB = + nodeScoreB > totalDelegatorScoreB + ? nodeScoreB - totalDelegatorScoreB + : totalDelegatorScoreB - nodeScoreB; + + // Allow reasonable tolerance for multi-node scoring differences + // The tolerance needs to account for precision loss in score settlement + const toleranceA = nodeScoreA / 5n; // 20% tolerance due to settlement complexity + const toleranceB = nodeScoreB / 5n; // 20% tolerance due to settlement complexity + + expect(scoreDiffA).to.be.lte( + toleranceA, + `**Per node A: ΣdelegatorScore ≈ nodeScore (within 20%)**`, + ); + expect(scoreDiffB).to.be.lte( + toleranceB, + `**Per node B: ΣdelegatorScore ≈ nodeScore (within 20%)**`, + ); + + // Network: allNodesEpochScore == A+B + expect(allNodesScore).to.equal( + nodeScoreA + nodeScoreB, + '**Network: allNodesEpochScore == A+B**', + ); + + console.log( + ` ✅ Node A: delegator sum=${totalDelegatorScoreA}, node score=${nodeScoreA}, diff=${scoreDiffA}`, + ); + console.log( + ` ✅ Node B: delegator sum=${totalDelegatorScoreB}, node score=${nodeScoreB}, diff=${scoreDiffB}`, + ); + console.log( + ` ✅ Network: total=${allNodesScore}, A+B=${nodeScoreA + nodeScoreB}`, + ); + }); + + it('3B - Split stake A→B; both nodes proof', async function () { + console.log('\n🔄 TEST 3B: Split stake A→B; both nodes proof'); + + const currentEpoch = await contracts.chronos.getCurrentEpoch(); + const nodeAId = node1Id; + const nodeBId = nodeIds.node2Id; + + // Step 1: Stake on A + const initialStake = toTRAC(200); + await contracts.token + .connect(accounts.delegator1) + .approve(await contracts.staking.getAddress(), initialStake); + await contracts.staking + .connect(accounts.delegator1) + .stake(nodeAId, initialStake); + + // Step 2: Proof A + await contracts.randomSampling.updateAndGetActiveProofPeriodStartBlock(); + await contracts.randomSampling + .connect(accounts.node1.operational) + .createChallenge(); + const challengeA = + await contracts.randomSamplingStorage.getNodeChallenge(nodeAId); + const chunksA = kcTools.splitIntoChunks(quads, 32); + const chunkIdA = Number(challengeA[1]); + const { proof: proofA } = kcTools.calculateMerkleProof( + quads, + 32, + chunkIdA, + ); + await contracts.randomSampling + .connect(accounts.node1.operational) + .submitProof(chunksA[chunkIdA], proofA); + + // Settle score on A + await contracts.token + .connect(accounts.delegator1) + .approve(await contracts.staking.getAddress(), toTRAC(1)); + await contracts.staking + .connect(accounts.delegator1) + .stake(nodeAId, toTRAC(1)); + + const scoreOnABeforeRedelegate = + await contracts.randomSamplingStorage.getEpochNodeDelegatorScore( + currentEpoch, + nodeAId, + d1Key, + ); + + // Step 3: Redelegate 50% to B + const redelegateAmount = toTRAC(100.5); // half of 201 + await contracts.staking + .connect(accounts.delegator1) + .redelegate(nodeAId, nodeBId, redelegateAmount); + + // Step 4: Proof B + await advanceToNextProofingPeriod(contracts); + await contracts.randomSampling + .connect(accounts.node2.operational) + .createChallenge(); + const challengeB = + await contracts.randomSamplingStorage.getNodeChallenge(nodeBId); + const chunksB = kcTools.splitIntoChunks(quads, 32); + const chunkIdB = Number(challengeB[1]); + const { proof: proofB } = kcTools.calculateMerkleProof( + quads, + 32, + chunkIdB, + ); + await contracts.randomSampling + .connect(accounts.node2.operational) + .submitProof(chunksB[chunkIdB], proofB); + + // Settle score on B + await contracts.token + .connect(accounts.delegator1) + .approve(await contracts.staking.getAddress(), toTRAC(1)); + await contracts.staking + .connect(accounts.delegator1) + .stake(nodeBId, toTRAC(1)); + + // **DELEGATOR SCORING ASSERTIONS** + const scoreOnAAfterProofB = + await contracts.randomSamplingStorage.getEpochNodeDelegatorScore( + currentEpoch, + nodeAId, + d1Key, + ); + const scoreOnB = + await contracts.randomSamplingStorage.getEpochNodeDelegatorScore( + currentEpoch, + nodeBId, + d1Key, + ); + + expect(scoreOnAAfterProofB).to.equal( + scoreOnABeforeRedelegate, + "**A's delegatorScore reflects first half only**", + ); + // Calculate expected score on B based on redelegated stake and proof + const redelegatedStake = toTRAC(100.5); // half of 201 + const indexOnB = + await contracts.randomSamplingStorage.getNodeEpochScorePerStake( + currentEpoch, + nodeBId, + ); + const expectedScoreOnB = calculateExpectedDelegatorScore( + redelegatedStake, + indexOnB, + 0n, // new delegator on B started from 0 + ); + expect(scoreOnB).to.equal( + expectedScoreOnB, + "**B's score should equal calculated expected value**", + ); + + console.log( + ` ✅ Score on A: ${scoreOnABeforeRedelegate} (unchanged after B's proof)`, + ); + console.log(` ✅ Score on B: ${scoreOnB} (earned from proof B)`); + console.log(` ✅ Split delegation scoring works correctly`); + }); + + it('3C - One delegator leaves; others proof later', async function () { + console.log('\n👋 TEST 3C: One delegator leaves; others proof later'); + + const currentEpoch = await contracts.chronos.getCurrentEpoch(); + + // Step 1: Two delegators stake + const stake1 = toTRAC(100); + const stake2 = toTRAC(200); + + await contracts.token + .connect(accounts.delegator1) + .approve(await contracts.staking.getAddress(), stake1); + await contracts.staking + .connect(accounts.delegator1) + .stake(node1Id, stake1); + + await contracts.token + .connect(accounts.delegator2) + .approve(await contracts.staking.getAddress(), stake2); + await contracts.staking + .connect(accounts.delegator2) + .stake(node1Id, stake2); + + const totalStakeBefore = + await contracts.stakingStorage.getNodeStake(node1Id); + console.log( + ` 📊 Total stake before withdrawal: ${ethers.formatUnits(totalStakeBefore, 18)} TRAC`, + ); + + // Step 2: One withdraws all + await contracts.staking + .connect(accounts.delegator1) + .requestWithdrawal(node1Id, stake1); + + const totalStakeAfter = + await contracts.stakingStorage.getNodeStake(node1Id); + console.log( + ` 📊 Total stake after withdrawal: ${ethers.formatUnits(totalStakeAfter, 18)} TRAC`, + ); + + // Step 3: Remaining delegator proofs + await contracts.randomSampling.updateAndGetActiveProofPeriodStartBlock(); + await contracts.randomSampling + .connect(accounts.node1.operational) + .createChallenge(); + const challenge = + await contracts.randomSamplingStorage.getNodeChallenge(node1Id); + const chunks = kcTools.splitIntoChunks(quads, 32); + const chunkId = Number(challenge[1]); + const { proof } = kcTools.calculateMerkleProof(quads, 32, chunkId); + await contracts.randomSampling + .connect(accounts.node1.operational) + .submitProof(chunks[chunkId], proof); + + const nodeScorePerStakeAfterWithdrawal = + await contracts.randomSamplingStorage.getNodeEpochScorePerStake( + currentEpoch, + node1Id, + ); + + // Settle score for remaining delegator + await contracts.token + .connect(accounts.delegator2) + .approve(await contracts.staking.getAddress(), toTRAC(1)); + await contracts.staking + .connect(accounts.delegator2) + .stake(node1Id, toTRAC(1)); + + // **DELEGATOR SCORING ASSERTIONS** + const delegator2Score = + await contracts.randomSamplingStorage.getEpochNodeDelegatorScore( + currentEpoch, + node1Id, + d2Key, + ); + + // Calculate expected score for delegator 2 with higher nodeEpochScorePerStake + const SCALE18 = ethers.parseUnits('1', 18); + const expectedScore = + (stake2 * nodeScorePerStakeAfterWithdrawal) / SCALE18; + + expect(delegator2Score).to.equal( + expectedScore, + '**New nodeEpochScorePerStake higher ⇒ remaining delegator gets bigger Δscore**', + ); + + console.log( + ` ✅ Node score per stake after withdrawal: ${nodeScorePerStakeAfterWithdrawal}`, + ); + console.log( + ` ✅ Delegator 2 score: ${delegator2Score} (expected: ${expectedScore})`, + ); + console.log(` ✅ Higher score per stake due to reduced total stake`); + }); + + it('3D - batchClaimDelegatorRewards', async function () { + console.log('\n📦 TEST 3D: batchClaimDelegatorRewards'); + + const startEpoch = await contracts.chronos.getCurrentEpoch(); + + // Setup: Stake from two delegators + const stake1 = toTRAC(100); + const stake2 = toTRAC(150); + + await contracts.token + .connect(accounts.delegator1) + .approve(await contracts.staking.getAddress(), stake1); + await contracts.staking + .connect(accounts.delegator1) + .stake(node1Id, stake1); + + await contracts.token + .connect(accounts.delegator2) + .approve(await contracts.staking.getAddress(), stake2); + await contracts.staking + .connect(accounts.delegator2) + .stake(node1Id, stake2); + + // Epoch 1: Submit proof and create rewards + await contracts.randomSampling.updateAndGetActiveProofPeriodStartBlock(); + await contracts.randomSampling + .connect(accounts.node1.operational) + .createChallenge(); + const challenge1 = + await contracts.randomSamplingStorage.getNodeChallenge(node1Id); + const chunks1 = kcTools.splitIntoChunks(quads, 32); + const chunkId1 = Number(challenge1[1]); + const { proof: proof1 } = kcTools.calculateMerkleProof( + quads, + 32, + chunkId1, + ); + await contracts.randomSampling + .connect(accounts.node1.operational) + .submitProof(chunks1[chunkId1], proof1); + + // Advance to epoch 2 + let timeUntilNext = await contracts.chronos.timeUntilNextEpoch(); + await time.increase(timeUntilNext + 1n); + const epoch2 = await contracts.chronos.getCurrentEpoch(); + + // Create KC to finalize epoch 1 + await createKnowledgeCollection( + accounts.kcCreator, + accounts.node1, + Number(node1Id), + receivingNodes, + receivingNodesIdentityIds, + { KnowledgeCollection: contracts.kc, Token: contracts.token }, + merkleRoot, + 'epoch1-rewards', + 1, + 1000, + 1, + toTRAC(100), + ); + + // Epoch 2: Submit proof again (advance proof period first) + await advanceToNextProofingPeriod(contracts); + await contracts.randomSampling.updateAndGetActiveProofPeriodStartBlock(); + await contracts.randomSampling + .connect(accounts.node1.operational) + .createChallenge(); + const challenge2 = + await contracts.randomSamplingStorage.getNodeChallenge(node1Id); + const chunks2 = kcTools.splitIntoChunks(quads, 32); + const chunkId2 = Number(challenge2[1]); + const { proof: proof2 } = kcTools.calculateMerkleProof( + quads, + 32, + chunkId2, + ); + await contracts.randomSampling + .connect(accounts.node1.operational) + .submitProof(chunks2[chunkId2], proof2); + + // Advance to epoch 3 + timeUntilNext = await contracts.chronos.timeUntilNextEpoch(); + await time.increase(timeUntilNext + 1n); + + // Create KC to finalize epoch 2 + await createKnowledgeCollection( + accounts.kcCreator, + accounts.node1, + Number(node1Id), + receivingNodes, + receivingNodesIdentityIds, + { KnowledgeCollection: contracts.kc, Token: contracts.token }, + merkleRoot, + 'epoch2-rewards', + 1, + 1000, + 1, + toTRAC(100), + ); + + // Get stake bases before claiming + const delegator1StakeBefore = + await contracts.stakingStorage.getDelegatorStakeBase(node1Id, d1Key); + const delegator2StakeBefore = + await contracts.stakingStorage.getDelegatorStakeBase(node1Id, d2Key); + + console.log( + ` 📊 Delegator 1 stake before: ${ethers.formatUnits(delegator1StakeBefore, 18)} TRAC`, + ); + console.log( + ` 📊 Delegator 2 stake before: ${ethers.formatUnits(delegator2StakeBefore, 18)} TRAC`, + ); + + // **DELEGATOR SCORING ASSERTIONS** + // Step 1: Call batchClaimDelegatorRewards for both epochs and both delegators + await contracts.staking.batchClaimDelegatorRewards( + node1Id, + [startEpoch, epoch2], + [accounts.delegator1.address, accounts.delegator2.address], + ); + + const delegator1StakeAfter = + await contracts.stakingStorage.getDelegatorStakeBase(node1Id, d1Key); + const delegator2StakeAfter = + await contracts.stakingStorage.getDelegatorStakeBase(node1Id, d2Key); + + // Calculate expected rewards for verification + const expectedReward1Epoch1 = + await contracts.stakingKPI.getDelegatorReward( + node1Id, + startEpoch, + accounts.delegator1.address, + ); + const expectedReward1Epoch2 = + await contracts.stakingKPI.getDelegatorReward( + node1Id, + epoch2, + accounts.delegator1.address, + ); + const expectedReward2Epoch1 = + await contracts.stakingKPI.getDelegatorReward( + node1Id, + startEpoch, + accounts.delegator2.address, + ); + const expectedReward2Epoch2 = + await contracts.stakingKPI.getDelegatorReward( + node1Id, + epoch2, + accounts.delegator2.address, + ); + + const expectedTotalReward1 = + expectedReward1Epoch1 + expectedReward1Epoch2; + const expectedTotalReward2 = + expectedReward2Epoch1 + expectedReward2Epoch2; + + expect(delegator1StakeAfter).to.equal( + delegator1StakeBefore + expectedTotalReward1, + '**Delegator 1 stakeBase should increase by calculated rewards**', + ); + expect(delegator2StakeAfter).to.equal( + delegator2StakeBefore + expectedTotalReward2, + '**Delegator 2 stakeBase should increase by calculated rewards**', + ); + + const reward1 = delegator1StakeAfter - delegator1StakeBefore; + const reward2 = delegator2StakeAfter - delegator2StakeBefore; + + console.log( + ` ✅ Delegator 1 total rewards: ${ethers.formatUnits(reward1, 18)} TRAC`, + ); + console.log( + ` ✅ Delegator 2 total rewards: ${ethers.formatUnits(reward2, 18)} TRAC`, + ); + + // Step 2: Attempt second batch call - should revert + await expect( + contracts.staking.batchClaimDelegatorRewards( + node1Id, + [startEpoch, epoch2], + [accounts.delegator1.address, accounts.delegator2.address], + ), + ).to.be.revertedWith('Already claimed all finalised epochs'); + + console.log( + ` ✅ Second batch call properly reverted with "Already claimed..."`, + ); + console.log( + ` ✅ Batch claiming works correctly for multiple epochs and delegators`, + ); + }); + }); + + describe('Suite 4: Long-Term & Edge Cases', function () { + it('4A - 20-epoch gap, then claim & restake', async function () { + console.log('\n⏰ TEST 4A: 20-epoch gap, then claim & restake'); + + const startEpoch = await contracts.chronos.getCurrentEpoch(); + + // Step 1: Stake and submit proof at epoch N + const initialStake = toTRAC(200); + await contracts.token + .connect(accounts.delegator1) + .approve(await contracts.staking.getAddress(), initialStake); + await contracts.staking + .connect(accounts.delegator1) + .stake(node1Id, initialStake); + + // Submit proof to create rewards - use direct approach due to long gap scenario + await contracts.randomSampling.updateAndGetActiveProofPeriodStartBlock(); + await contracts.randomSampling + .connect(accounts.node1.operational) + .createChallenge(); + const challenge = + await contracts.randomSamplingStorage.getNodeChallenge(node1Id); + const chunks = kcTools.splitIntoChunks(quads, 32); + const chunkId = Number(challenge[1]); + const { proof } = kcTools.calculateMerkleProof(quads, 32, chunkId); + await contracts.randomSampling + .connect(accounts.node1.operational) + .submitProof(chunks[chunkId], proof); + + console.log(` 📊 Proof submitted at epoch ${startEpoch}`); + + // Step 2: Advance to next epoch to make rewards claimable + const timeUntilNext = await contracts.chronos.timeUntilNextEpoch(); + await time.increase(timeUntilNext + 1n); + + // Create KC to finalize the epoch with rewards + await createKnowledgeCollection( + accounts.kcCreator, + accounts.node1, + Number(node1Id), + receivingNodes, + receivingNodesIdentityIds, + { KnowledgeCollection: contracts.kc, Token: contracts.token }, + merkleRoot, + 'rewards-epoch', + 1, + 1000, + 1, + toTRAC(1), + ); + + // Record stake before claiming to verify rewards are added + const stakeBeforeClaim = + await contracts.stakingStorage.getDelegatorStakeBase(node1Id, d1Key); + + // Claim the rewards first (required before changing stake) + await contracts.staking + .connect(accounts.delegator1) + .claimDelegatorRewards( + node1Id, + startEpoch, + accounts.delegator1.address, + ); + + // Verify rewards were added to stake base + const stakeAfterClaim = + await contracts.stakingStorage.getDelegatorStakeBase(node1Id, d1Key); + const rewardsClaimed = stakeAfterClaim - stakeBeforeClaim; + + expect(rewardsClaimed).to.be.gt( + 0n, + '**Claimed score from N should be added to stakeBase**', + ); + console.log( + ` ✅ Rewards claimed and restaked: ${ethers.formatUnits(rewardsClaimed, 18)} TRAC`, + ); + + // Now withdraw all stake (including rewards) + const allStake = stakeAfterClaim; + await contracts.staking + .connect(accounts.delegator1) + .requestWithdrawal(node1Id, allStake); + + console.log( + ` 📤 Withdrew all stake: ${ethers.formatUnits(allStake, 18)} TRAC`, + ); + + // Step 3: Advance 20 epochs + for (let i = 0; i < 20; i++) { + const timeUntilNext = await contracts.chronos.timeUntilNextEpoch(); + await time.increase(timeUntilNext + 1n); + // Create KC occasionally to advance epochs properly + if (i % 5 === 0) { + await createKnowledgeCollection( + accounts.kcCreator, + accounts.node1, + Number(node1Id), + receivingNodes, + receivingNodesIdentityIds, + { KnowledgeCollection: contracts.kc, Token: contracts.token }, + merkleRoot, + `epoch-advance-${i}`, + 1, + 1000, + 1, + toTRAC(1), + ); + } + } + + const currentEpoch = await contracts.chronos.getCurrentEpoch(); + console.log( + ` ⏭️ Advanced to epoch ${currentEpoch} (gap of ${currentEpoch - startEpoch} epochs)`, + ); + + // Step 4: Verify delegation after 20-epoch gap + // The delegator should have zero stake after withdrawal + const currentStakeBase = + await contracts.stakingStorage.getDelegatorStakeBase(node1Id, d1Key); + + // **DELEGATOR SCORING ASSERTIONS** + expect(currentStakeBase).to.equal( + 0n, + 'Delegator should have zero stake after withdrawal', + ); + console.log( + ` ✅ After 20-epoch gap, delegator stake: ${currentStakeBase} TRAC (expected: 0)`, + ); + + // Step 5: Stake again + const newStake = toTRAC(100); + await contracts.token + .connect(accounts.delegator1) + .approve(await contracts.staking.getAddress(), newStake); + await contracts.staking + .connect(accounts.delegator1) + .stake(node1Id, newStake); + + // Check that new stake starts with 0 score + const newStakeScore = + await contracts.randomSamplingStorage.getEpochNodeDelegatorScore( + currentEpoch, + node1Id, + d1Key, + ); + + expect(newStakeScore).to.equal( + 0n, + '**New stake starts with delegatorScore == 0**', + ); + + console.log(` ✅ New stake has score: ${newStakeScore} (expected: 0)`); + console.log( + ` ✅ Long-term claim and restake scenario works correctly`, + ); + }); + + it('4B - Node earns while delegator zero-stake', async function () { + console.log('\n🚫 TEST 4B: Node earns while delegator zero-stake'); + + const startEpoch = await contracts.chronos.getCurrentEpoch(); + + // Step 1: Stake initially + const initialStake = toTRAC(150); + await contracts.token + .connect(accounts.delegator1) + .approve(await contracts.staking.getAddress(), initialStake); + await contracts.staking + .connect(accounts.delegator1) + .stake(node1Id, initialStake); + + // Step 2: Withdraw all stake + await contracts.staking + .connect(accounts.delegator1) + .requestWithdrawal(node1Id, initialStake); + + console.log(` 📤 Withdrew all stake at epoch ${startEpoch}`); + + // Step 3: Node proofs for 3 epochs while delegator has zero stake + const proofEpochs: bigint[] = []; + + for (let i = 0; i < 3; i++) { + // Advance to next epoch + const timeUntilNext = await contracts.chronos.timeUntilNextEpoch(); + await time.increase(timeUntilNext + 1n); + + const currentEpoch = await contracts.chronos.getCurrentEpoch(); + proofEpochs.push(currentEpoch); + + // Create KC to advance epoch - make sure it exists before challenge + await createKnowledgeCollection( + accounts.kcCreator, + accounts.node1, + Number(node1Id), + receivingNodes, + receivingNodesIdentityIds, + { KnowledgeCollection: contracts.kc, Token: contracts.token }, + merkleRoot, + `zero-stake-epoch-${i}`, + 1, + 1000, + 1, + toTRAC(1), + ); + + // Submit proof - simplified direct approach + // skip to the next proof period + const durationInBlocks = + await contracts.randomSampling.getActiveProofingPeriodDurationInBlocks(); + for (let j = 0; j < durationInBlocks; j++) { + await hre.network.provider.send('evm_mine'); + } + await contracts.randomSampling.updateAndGetActiveProofPeriodStartBlock(); + await contracts.randomSampling + .connect(accounts.node1.operational) + .createChallenge(); + const challenge = + await contracts.randomSamplingStorage.getNodeChallenge(node1Id); + const chunks = kcTools.splitIntoChunks(quads, 32); + const chunkId = Number(challenge[1]); + const { proof } = kcTools.calculateMerkleProof(quads, 32, chunkId); + await contracts.randomSampling + .connect(accounts.node1.operational) + .submitProof(chunks[chunkId], proof); + + console.log(` 📋 Node proof submitted at epoch ${currentEpoch}`); + } + + // Step 4: Delegator stakes again + const newStake = toTRAC(200); + await contracts.token + .connect(accounts.delegator1) + .approve(await contracts.staking.getAddress(), newStake); + await contracts.staking + .connect(accounts.delegator1) + .stake(node1Id, newStake); + + // **DELEGATOR SCORING ASSERTIONS** + // Check delegator score for zero-stake epochs + for (const epoch of proofEpochs) { + const delegatorScore = + await contracts.randomSamplingStorage.getEpochNodeDelegatorScore( + epoch, + node1Id, + d1Key, + ); + expect(delegatorScore).to.equal( + 0n, + `**delegatorScore == 0 for zero-stake epoch ${epoch}**`, + ); + console.log( + ` ✅ Epoch ${epoch}: delegator score = ${delegatorScore} (zero stake)`, + ); + } + + // Check that last-settled index was advanced properly + const finalEpoch = proofEpochs[proofEpochs.length - 1]; + const lastSettledIndex = + await contracts.randomSamplingStorage.getDelegatorLastSettledNodeEpochScorePerStake( + finalEpoch, + node1Id, + d1Key, + ); + + expect(lastSettledIndex).to.be.gt( + 0n, + '**Last-settled index should be advanced each epoch**', + ); + + console.log( + ` ✅ Last settled index: ${lastSettledIndex} (properly advanced)`, + ); + console.log(` ✅ Zero-stake epochs handled correctly`); + }); + + it('4C - Restake before claiming → revert', async function () { + console.log('\n⛔ TEST 4C: Restake before claiming → revert'); + + const startEpoch = await contracts.chronos.getCurrentEpoch(); + + // Step 1: Stake and submit proof to create rewards + const initialStake = toTRAC(180); + await contracts.token + .connect(accounts.delegator1) + .approve(await contracts.staking.getAddress(), initialStake); + await contracts.staking + .connect(accounts.delegator1) + .stake(node1Id, initialStake); + + // Submit proof - create challenge and proof directly + await contracts.randomSampling.updateAndGetActiveProofPeriodStartBlock(); + await contracts.randomSampling + .connect(accounts.node1.operational) + .createChallenge(); + const challenge = + await contracts.randomSamplingStorage.getNodeChallenge(node1Id); + const chunks = kcTools.splitIntoChunks(quads, 32); + const chunkId = Number(challenge[1]); + const { proof } = kcTools.calculateMerkleProof(quads, 32, chunkId); + await contracts.randomSampling + .connect(accounts.node1.operational) + .submitProof(chunks[chunkId], proof); + + // Step 2: Withdraw all stake + await contracts.staking + .connect(accounts.delegator1) + .requestWithdrawal(node1Id, initialStake); + + // Advance to next epoch to make rewards claimable + const timeUntilNext = await contracts.chronos.timeUntilNextEpoch(); + await time.increase(timeUntilNext + 1n); + + // Create KC to finalize the epoch + await createKnowledgeCollection( + accounts.kcCreator, + accounts.node1, + Number(node1Id), + receivingNodes, + receivingNodesIdentityIds, + { KnowledgeCollection: contracts.kc, Token: contracts.token }, + merkleRoot, + 'revert-test-epoch', + 1, + 1000, + 1, + toTRAC(1), + ); + + console.log( + ` 📤 Withdrew all stake, rewards available for epoch ${startEpoch}`, + ); + + // Step 3: Try to stake again without claiming (should revert) + const scoreBeforeRestake = + await contracts.randomSamplingStorage.getEpochNodeDelegatorScore( + startEpoch, + node1Id, + d1Key, + ); + + const newStake = toTRAC(100); + await contracts.token + .connect(accounts.delegator1) + .approve(await contracts.staking.getAddress(), newStake); + + // **DELEGATOR SCORING ASSERTIONS** + await expect( + contracts.staking.connect(accounts.delegator1).stake(node1Id, newStake), + ).to.be.revertedWith( + 'Must claim rewards up to the lastStakeHeldEpoch before changing stake', + ); + + const scoreAfterRevert = + await contracts.randomSamplingStorage.getEpochNodeDelegatorScore( + startEpoch, + node1Id, + d1Key, + ); + + expect(scoreAfterRevert).to.equal( + scoreBeforeRestake, + '**delegatorScore unchanged after revert**', + ); + + console.log(` ✅ Transaction properly reverted: "Must claim ..."`); + console.log( + ` ✅ Delegator score unchanged: ${scoreBeforeRestake} → ${scoreAfterRevert}`, + ); + console.log(` ✅ Claim-before-restake validation works correctly`); + }); + + it('4D - Out-of-order claim (includes score)', async function () { + console.log('\n🔀 TEST 4D: Out-of-order claim (includes score)'); + + const startEpoch = await contracts.chronos.getCurrentEpoch(); + + // Step 1: Stake initially + const stake = toTRAC(160); + await contracts.token + .connect(accounts.delegator1) + .approve(await contracts.staking.getAddress(), stake); + await contracts.staking + .connect(accounts.delegator1) + .stake(node1Id, stake); + + // Step 2: Node proofs in epoch N + await contracts.randomSampling.updateAndGetActiveProofPeriodStartBlock(); + await contracts.randomSampling + .connect(accounts.node1.operational) + .createChallenge(); + let challenge = + await contracts.randomSamplingStorage.getNodeChallenge(node1Id); + let chunks = kcTools.splitIntoChunks(quads, 32); + let chunkId = Number(challenge[1]); + let { proof } = kcTools.calculateMerkleProof(quads, 32, chunkId); + await contracts.randomSampling + .connect(accounts.node1.operational) + .submitProof(chunks[chunkId], proof); + + console.log(` 📋 Proof submitted for epoch ${startEpoch}`); + + // Advance to epoch N+1 + let timeUntilNext = await contracts.chronos.timeUntilNextEpoch(); + await time.increase(timeUntilNext + 1n); + const epochN1 = await contracts.chronos.getCurrentEpoch(); + + // Create KC to finalize epoch N + await createKnowledgeCollection( + accounts.kcCreator, + accounts.node1, + Number(node1Id), + receivingNodes, + receivingNodesIdentityIds, + { KnowledgeCollection: contracts.kc, Token: contracts.token }, + merkleRoot, + 'epoch-n-rewards', + 1, + 1000, + 1, + toTRAC(1), + ); + + // Step 3: Node proofs in epoch N+1 + await advanceToNextProofingPeriod(contracts); + await contracts.randomSampling.updateAndGetActiveProofPeriodStartBlock(); + await contracts.randomSampling + .connect(accounts.node1.operational) + .createChallenge(); + challenge = + await contracts.randomSamplingStorage.getNodeChallenge(node1Id); + chunks = kcTools.splitIntoChunks(quads, 32); + chunkId = Number(challenge[1]); + ({ proof } = kcTools.calculateMerkleProof(quads, 32, chunkId)); + await contracts.randomSampling + .connect(accounts.node1.operational) + .submitProof(chunks[chunkId], proof); + + console.log(` 📋 Proof submitted for epoch ${epochN1}`); + + // Advance to epoch N+2 to make N+1 claimable + timeUntilNext = await contracts.chronos.timeUntilNextEpoch(); + await time.increase(timeUntilNext + 1n); + + // Create KC to finalize epoch N+1 + await createKnowledgeCollection( + accounts.kcCreator, + accounts.node1, + Number(node1Id), + receivingNodes, + receivingNodesIdentityIds, + { KnowledgeCollection: contracts.kc, Token: contracts.token }, + merkleRoot, + 'epoch-n1-rewards', + 1, + 1000, + 1, + toTRAC(1), + ); + + // Step 4: Try to claim N+1 before N (should revert) + const scoreNBefore = + await contracts.randomSamplingStorage.getEpochNodeDelegatorScore( + startEpoch, + node1Id, + d1Key, + ); + const scoreN1Before = + await contracts.randomSamplingStorage.getEpochNodeDelegatorScore( + epochN1, + node1Id, + d1Key, + ); + + // **DELEGATOR SCORING ASSERTIONS** + await expect( + contracts.staking + .connect(accounts.delegator1) + .claimDelegatorRewards(node1Id, epochN1, accounts.delegator1.address), + ).to.be.revertedWith('Must claim older epochs first'); + + const scoreNAfterRevert = + await contracts.randomSamplingStorage.getEpochNodeDelegatorScore( + startEpoch, + node1Id, + d1Key, + ); + const scoreN1AfterRevert = + await contracts.randomSamplingStorage.getEpochNodeDelegatorScore( + epochN1, + node1Id, + d1Key, + ); + + expect(scoreNAfterRevert).to.equal( + scoreNBefore, + '**Revert keeps epoch N delegatorScore intact**', + ); + expect(scoreN1AfterRevert).to.equal( + scoreN1Before, + '**Revert keeps epoch N+1 delegatorScore intact**', + ); + + console.log( + ` ✅ Out-of-order claim properly reverted: "Must claim older epochs first"`, + ); + + // Step 5: Claim in proper order (N then N+1) + const stakeBaseBefore = + await contracts.stakingStorage.getDelegatorStakeBase(node1Id, d1Key); + + // Claim epoch N + await contracts.staking + .connect(accounts.delegator1) + .claimDelegatorRewards( + node1Id, + startEpoch, + accounts.delegator1.address, + ); + + const stakeBaseAfterN = + await contracts.stakingStorage.getDelegatorStakeBase(node1Id, d1Key); + + // Claim epoch N+1 + await contracts.staking + .connect(accounts.delegator1) + .claimDelegatorRewards(node1Id, epochN1, accounts.delegator1.address); + + const stakeBaseAfterN1 = + await contracts.stakingStorage.getDelegatorStakeBase(node1Id, d1Key); + + const totalRewards = stakeBaseAfterN1 - stakeBaseBefore; + const rewardN = stakeBaseAfterN - stakeBaseBefore; + const rewardN1 = stakeBaseAfterN1 - stakeBaseAfterN; + + expect(totalRewards).to.equal( + rewardN + rewardN1, + '**Σ stakeBase increase == rewards N+N+1**', + ); + + console.log( + ` ✅ Claimed epoch ${startEpoch} reward: ${ethers.formatUnits(rewardN, 18)} TRAC`, + ); + console.log( + ` ✅ Claimed epoch ${epochN1} reward: ${ethers.formatUnits(rewardN1, 18)} TRAC`, + ); + console.log( + ` ✅ Total rewards: ${ethers.formatUnits(totalRewards, 18)} TRAC`, + ); + console.log(` ✅ Sequential claiming works correctly after revert`); + }); + }); + + describe('Suite 5: Rolling Rewards & Fee Mechanics', function () { + it('5A - Rolling rewards across 3 epochs', async function () { + console.log('\n🔄 TEST 5A: Rolling rewards across 3 epochs'); + // Step 1: Stake initially + const stake = toTRAC(150); + await contracts.token + .connect(accounts.delegator1) + .approve(await contracts.staking.getAddress(), stake); + await contracts.staking + .connect(accounts.delegator1) + .stake(node1Id, stake); + + const epochs: bigint[] = []; + + // Step 2: Submit proofs for epochs 1-3 + for (let i = 0; i < 3; i++) { + const currentEpoch = await contracts.chronos.getCurrentEpoch(); + epochs.push(currentEpoch); + + // Submit proof for current epoch - advance proofing period first + await advanceToNextProofingPeriod(contracts); + await contracts.randomSampling.updateAndGetActiveProofPeriodStartBlock(); + await contracts.randomSampling + .connect(accounts.node1.operational) + .createChallenge(); + const challenge = + await contracts.randomSamplingStorage.getNodeChallenge(node1Id); + const chunks = kcTools.splitIntoChunks(quads, 32); + const chunkId = Number(challenge[1]); + const { proof } = kcTools.calculateMerkleProof(quads, 32, chunkId); + await contracts.randomSampling + .connect(accounts.node1.operational) + .submitProof(chunks[chunkId], proof); + + console.log(` 📋 Proof submitted for epoch ${currentEpoch}`); + + // Advance to next epoch (except for last iteration) + if (i < 2) { + const timeUntilNext = await contracts.chronos.timeUntilNextEpoch(); + await time.increase(timeUntilNext + 1n); + + // Create KC to finalize the epoch + await createKnowledgeCollection( + accounts.kcCreator, + accounts.node1, + Number(node1Id), + receivingNodes, + receivingNodesIdentityIds, + { KnowledgeCollection: contracts.kc, Token: contracts.token }, + merkleRoot, + `rolling-epoch-${i}`, + 1, + 1000, + 1, + toTRAC(1), + ); + } + } + + // Advance to make epoch 3 claimable + const timeUntilNext = await contracts.chronos.timeUntilNextEpoch(); + await time.increase(timeUntilNext + 1n); + await createKnowledgeCollection( + accounts.kcCreator, + accounts.node1, + Number(node1Id), + receivingNodes, + receivingNodesIdentityIds, + { KnowledgeCollection: contracts.kc, Token: contracts.token }, + merkleRoot, + 'rolling-final', + 1, + 1000, + 1, + toTRAC(1), + ); + + console.log(` ✅ Proofs completed for epochs: ${epochs.join(', ')}`); + + // Step 3: Claim epoch 1 only + const stakeBaseBefore = + await contracts.stakingStorage.getDelegatorStakeBase(node1Id, d1Key); + + await contracts.staking + .connect(accounts.delegator1) + .claimDelegatorRewards(node1Id, epochs[0], accounts.delegator1.address); + + const stakeBaseAfterFirst = + await contracts.stakingStorage.getDelegatorStakeBase(node1Id, d1Key); + const rollingAfterFirst = + await contracts.delegatorsInfo.getDelegatorRollingRewards( + node1Id, + accounts.delegator1.address, + ); + + const expectedReward1 = await contracts.stakingKPI.getDelegatorReward( + node1Id, + epochs[0], + accounts.delegator1.address, + ); + + // **DELEGATOR SCORING ASSERTIONS** + expect(rollingAfterFirst).to.equal( + expectedReward1, + '**After first claim: rollingRewards == expectedReward₁**', + ); + expect(stakeBaseAfterFirst).to.equal( + stakeBaseBefore, + 'StakeBase should not increase yet (rolling rewards)', + ); + + console.log( + ` ✅ Epoch ${epochs[0]} claimed: ${ethers.formatUnits(expectedReward1, 18)} TRAC (rolling)`, + ); + console.log( + ` ✅ Rolling rewards: ${ethers.formatUnits(rollingAfterFirst, 18)} TRAC`, + ); + + // Step 4: Claim epoch 3 (auto restake path - skipping epoch 2) + await contracts.staking + .connect(accounts.delegator1) + .claimDelegatorRewards(node1Id, epochs[1], accounts.delegator1.address); + + // Now claim epoch 3 which should trigger auto-restake + await contracts.staking + .connect(accounts.delegator1) + .claimDelegatorRewards(node1Id, epochs[2], accounts.delegator1.address); + + const stakeBaseFinal = + await contracts.stakingStorage.getDelegatorStakeBase(node1Id, d1Key); + const rollingFinal = + await contracts.delegatorsInfo.getDelegatorRollingRewards( + node1Id, + accounts.delegator1.address, + ); + + const totalRewards = stakeBaseFinal - stakeBaseBefore; + + // Calculate expected total rewards for all 3 epochs + const expectedReward2 = await contracts.stakingKPI.getDelegatorReward( + node1Id, + epochs[1], + accounts.delegator1.address, + ); + const expectedReward3 = await contracts.stakingKPI.getDelegatorReward( + node1Id, + epochs[2], + accounts.delegator1.address, + ); + const expectedTotalRewards = + expectedReward1 + expectedReward2 + expectedReward3; + + // **DELEGATOR SCORING ASSERTIONS** + expect(rollingFinal).to.equal( + 0n, + '**After final claim: rollingRewards == 0**', + ); + expect(totalRewards).to.equal( + expectedTotalRewards, + '**stakeBase should increase by sum of all epoch rewards**', + ); + + console.log( + ` ✅ Final stake base: ${ethers.formatUnits(stakeBaseFinal, 18)} TRAC`, + ); + console.log( + ` ✅ Total rewards claimed: ${ethers.formatUnits(totalRewards, 18)} TRAC`, + ); + console.log(` ✅ Rolling rewards reset: ${rollingFinal} TRAC`); + console.log(` ✅ Rolling rewards mechanism works correctly`); + }); + + it('5B - Operator-fee split, 2 delegators', async function () { + console.log('\n💰 TEST 5B: Operator-fee split, 2 delegators'); + // Step 1: Set operator fee to 5% + const operatorFeePercentage = 5; + await contracts.profileStorage.addOperatorFee( + node1Id, + operatorFeePercentage * 100, + (await contracts.chronos.getCurrentEpoch()) + 1n, + ); + console.log(` 📊 Using operator fee: ${operatorFeePercentage}%`); + + // Skip to the next epoch for new operator fee to take effect + await time.increase((await contracts.chronos.timeUntilNextEpoch()) + 1n); + + const startEpoch = await contracts.chronos.getCurrentEpoch(); + + // Step 2: Two delegators stake + const stake1 = toTRAC(100); + const stake2 = toTRAC(200); + + await contracts.token + .connect(accounts.delegator1) + .approve(await contracts.staking.getAddress(), stake1); + await contracts.staking + .connect(accounts.delegator1) + .stake(node1Id, stake1); + + await contracts.token + .connect(accounts.delegator2) + .approve(await contracts.staking.getAddress(), stake2); + await contracts.staking + .connect(accounts.delegator2) + .stake(node1Id, stake2); + + console.log( + ` 👥 Delegator1 staked: ${ethers.formatUnits(stake1, 18)} TRAC`, + ); + console.log( + ` 👥 Delegator2 staked: ${ethers.formatUnits(stake2, 18)} TRAC`, + ); + + // Step 3: Submit proof to generate rewards + await contracts.randomSampling.updateAndGetActiveProofPeriodStartBlock(); + await contracts.randomSampling + .connect(accounts.node1.operational) + .createChallenge(); + const challenge = + await contracts.randomSamplingStorage.getNodeChallenge(node1Id); + const chunks = kcTools.splitIntoChunks(quads, 32); + const chunkId = Number(challenge[1]); + const { proof } = kcTools.calculateMerkleProof(quads, 32, chunkId); + await contracts.randomSampling + .connect(accounts.node1.operational) + .submitProof(chunks[chunkId], proof); + + console.log(` 📋 Proof submitted for epoch ${startEpoch}`); + + // Step 4: Advance to next epoch to make rewards claimable + const timeUntilNext = await contracts.chronos.timeUntilNextEpoch(); + await time.increase(timeUntilNext + 1n); + await createKnowledgeCollection( + accounts.kcCreator, + accounts.node1, + Number(node1Id), + receivingNodes, + receivingNodesIdentityIds, + { KnowledgeCollection: contracts.kc, Token: contracts.token }, + merkleRoot, + 'fee-split-epoch', + 1, + 1000, + 1, + toTRAC(1), + ); + + // Step 5: Record operator fee balance before claims + const operatorFeeBalanceBefore = + await contracts.stakingStorage.getOperatorFeeBalance(node1Id); + + // Step 6: Both delegators claim + const d1StakeBefore = + await contracts.stakingStorage.getDelegatorStakeBase(node1Id, d1Key); + const d2StakeBefore = + await contracts.stakingStorage.getDelegatorStakeBase(node1Id, d2Key); + + await contracts.staking + .connect(accounts.delegator1) + .claimDelegatorRewards( + node1Id, + startEpoch, + accounts.delegator1.address, + ); + + await contracts.staking + .connect(accounts.delegator2) + .claimDelegatorRewards( + node1Id, + startEpoch, + accounts.delegator2.address, + ); + + const d1StakeAfter = await contracts.stakingStorage.getDelegatorStakeBase( + node1Id, + d1Key, + ); + const d2StakeAfter = await contracts.stakingStorage.getDelegatorStakeBase( + node1Id, + d2Key, + ); + + const operatorFeeBalanceAfter = + await contracts.stakingStorage.getOperatorFeeBalance(node1Id); + + const delegator1Rewards = d1StakeAfter - d1StakeBefore; + const delegator2Rewards = d2StakeAfter - d2StakeBefore; + const nodeOperatorRewards = await contracts.stakingKPI.getDelegatorReward( + node1Id, + startEpoch, + accounts.node1.operational.address, + ); + const operatorFeeEarned = + operatorFeeBalanceAfter - operatorFeeBalanceBefore; + + // Calculate expected gross rewards (before operator fee) + const totalDelegatorRewards = + delegator1Rewards + delegator2Rewards + nodeOperatorRewards; + const grossRewards = totalDelegatorRewards + operatorFeeEarned; + + const expectedNetNodeRewards = + await contracts.stakingKPI.getNetNodeRewards(node1Id, startEpoch); + + expect(expectedNetNodeRewards).to.be.equal(totalDelegatorRewards); + + // **DELEGATOR SCORING ASSERTIONS** + expect(expectedNetNodeRewards + operatorFeeEarned).to.equal( + grossRewards, + '**Delegator₁ + Delegator₂ + operatorFee == grossRewards**', + ); + + expect(operatorFeeEarned).to.be.equal( + (grossRewards * BigInt(operatorFeePercentage * 100)) / 10_000n, + ); + + // Calculate expected rewards based on stake proportions + const expectedDelegator1Reward = + await contracts.stakingKPI.getDelegatorReward( + node1Id, + startEpoch, + accounts.delegator1.address, + ); + const expectedDelegator2Reward = + await contracts.stakingKPI.getDelegatorReward( + node1Id, + startEpoch, + accounts.delegator2.address, + ); + + expect(delegator1Rewards).to.equal( + expectedDelegator1Reward, + 'Delegator1 rewards should equal calculated value', + ); + expect(delegator2Rewards).to.equal( + expectedDelegator2Reward, + 'Delegator2 rewards should equal calculated value', + ); + + console.log( + ` ✅ Delegator1 rewards: ${ethers.formatUnits(delegator1Rewards, 18)} TRAC`, + ); + console.log( + ` ✅ Delegator2 rewards: ${ethers.formatUnits(delegator2Rewards, 18)} TRAC`, + ); + console.log( + ` ✅ Operator fee earned: ${ethers.formatUnits(operatorFeeEarned, 18)} TRAC`, + ); + console.log( + ` ✅ Gross rewards: ${ethers.formatUnits(grossRewards, 18)} TRAC`, + ); + const actualRatio = (delegator2Rewards * 100n) / delegator1Rewards; + console.log( + ` ✅ Reward ratio D2/D1: ${actualRatio}% (expected ~200%)`, + ); + console.log(` ✅ Operator fee distribution works correctly`); + }); + + it('5C - Double-claim guard', async function () { + console.log('\n🚫 TEST 5C: Double-claim guard'); + + const startEpoch = await contracts.chronos.getCurrentEpoch(); + + // Step 1: Stake and submit proof + const stake = toTRAC(120); + await contracts.token + .connect(accounts.delegator1) + .approve(await contracts.staking.getAddress(), stake); + await contracts.staking + .connect(accounts.delegator1) + .stake(node1Id, stake); + + // Submit proof + await contracts.randomSampling.updateAndGetActiveProofPeriodStartBlock(); + await contracts.randomSampling + .connect(accounts.node1.operational) + .createChallenge(); + const challenge = + await contracts.randomSamplingStorage.getNodeChallenge(node1Id); + const chunks = kcTools.splitIntoChunks(quads, 32); + const chunkId = Number(challenge[1]); + const { proof } = kcTools.calculateMerkleProof(quads, 32, chunkId); + await contracts.randomSampling + .connect(accounts.node1.operational) + .submitProof(chunks[chunkId], proof); + + console.log(` 📋 Proof submitted for epoch ${startEpoch}`); + + // Step 2: Advance to next epoch to make rewards claimable + const timeUntilNext = await contracts.chronos.timeUntilNextEpoch(); + await time.increase(timeUntilNext + 1n); + await createKnowledgeCollection( + accounts.kcCreator, + accounts.node1, + Number(node1Id), + receivingNodes, + receivingNodesIdentityIds, + { KnowledgeCollection: contracts.kc, Token: contracts.token }, + merkleRoot, + 'double-claim-epoch', + 1, + 1000, + 1, + toTRAC(1), + ); + + // Step 3: Claim epoch E successfully + const stakeBaseBefore = + await contracts.stakingStorage.getDelegatorStakeBase(node1Id, d1Key); + + await contracts.staking + .connect(accounts.delegator1) + .claimDelegatorRewards( + node1Id, + startEpoch, + accounts.delegator1.address, + ); + + const stakeBaseAfterClaim = + await contracts.stakingStorage.getDelegatorStakeBase(node1Id, d1Key); + const rewardClaimed = stakeBaseAfterClaim - stakeBaseBefore; + + console.log( + ` ✅ First claim successful: ${ethers.formatUnits(rewardClaimed, 18)} TRAC`, + ); + + // Step 4: Attempt second claim for same epoch (should revert) + // **DELEGATOR SCORING ASSERTIONS** + await expect( + contracts.staking + .connect(accounts.delegator1) + .claimDelegatorRewards( + node1Id, + startEpoch, + accounts.delegator1.address, + ), + ).to.be.revertedWith('Already claimed all finalised epochs'); + + // Verify stake base is unchanged after failed double claim + const stakeBaseAfterRevert = + await contracts.stakingStorage.getDelegatorStakeBase(node1Id, d1Key); + + expect(stakeBaseAfterRevert).to.equal( + stakeBaseAfterClaim, + 'Stake base should be unchanged after failed double claim', + ); + + console.log( + ` ✅ Second claim properly reverted: "Already claimed all finalised epochs"`, + ); + console.log( + ` ✅ Stake base unchanged: ${ethers.formatUnits(stakeBaseAfterRevert, 18)} TRAC`, + ); + console.log(` ✅ Double-claim protection works correctly`); + }); + }); +}); diff --git a/test/integration/StakingRewards.test.ts b/test/integration/StakingRewards.test.ts new file mode 100644 index 00000000..10f71d7d --- /dev/null +++ b/test/integration/StakingRewards.test.ts @@ -0,0 +1,3081 @@ +// test/rewards.initial-state.spec.ts +/* eslint-disable @typescript-eslint/no-non-null-assertion */ + +import { SignerWithAddress } from '@nomicfoundation/hardhat-ethers/signers'; +import { time } from '@nomicfoundation/hardhat-network-helpers'; +import { kcTools } from 'assertion-tools'; +import { expect } from 'chai'; +import hre from 'hardhat'; + +import { + Token, + Profile, + ProfileStorage, + Staking, + Chronos, + RandomSamplingStorage, + EpochStorage, + KnowledgeCollection, + Hub, + StakingStorage, + RandomSampling, + Ask, + AskStorage, + ParametersStorage, + DelegatorsInfo, +} from '../../typechain'; +import { createKnowledgeCollection } from '../helpers/kc-helpers'; +import { createProfile } from '../helpers/profile-helpers'; + +/* ────────────────────────── helpers ────────────────────────── */ + +const toTRAC = (x: number) => hre.ethers.parseEther(x.toString()); + +// Sample data for KC (copied from full scenario) +const quads = [ + ' "468.9 sq mi" .', + ' "New York" .', + ' "8,336,817" .', + ' "New York" .', + ' .', + // Add more quads to ensure we have enough chunks + ...Array(1000).fill( + ' .', + ), +]; + +// Helper function to ensure node has chunks and submit proof +async function ensureNodeHasChunksThisEpoch( + nodeId: number, + node: { operational: SignerWithAddress; admin: SignerWithAddress }, + contracts: any, // eslint-disable-line @typescript-eslint/no-explicit-any + accounts: any, // eslint-disable-line @typescript-eslint/no-explicit-any + receivingNodes: { + operational: SignerWithAddress; + admin: SignerWithAddress; + }[], + receivingNodesIdentityIds: number[], + chunkSize: number, +): Promise { + const produced = + await contracts.epochStorage.getNodeCurrentEpochProducedKnowledgeValue( + nodeId, + ); + + if (produced === 0n) { + if ( + !receivingNodes.some( + (r) => r.operational.address === node.operational.address, + ) + ) { + receivingNodes.unshift(node); + receivingNodesIdentityIds.unshift(Number(nodeId)); + } + + const merkleRoot = kcTools.calculateMerkleRoot(quads, 32); + + await createKnowledgeCollection( + node.operational, // signer = node.operational + node, // publisher-node + Number(nodeId), + receivingNodes, + receivingNodesIdentityIds, + { KnowledgeCollection: contracts.kc, Token: contracts.token }, + merkleRoot, + `ensure-chunks-${Date.now()}`, + 1, // knowledgeAssetsAmount + chunkSize, // byteSize - must be >= CHUNK_BYTE_SIZE to avoid division by zero + 1, // epochs + toTRAC(1), + ); + + await contracts.randomSampling.updateAndGetActiveProofPeriodStartBlock(); + } +} + +// Helper function to advance to next proofing period +async function advanceToNextProofingPeriod( + contracts: any, // eslint-disable-line @typescript-eslint/no-explicit-any +): Promise { + const proofingPeriodDuration = + await contracts.randomSampling.getActiveProofingPeriodDurationInBlocks(); + const { activeProofPeriodStartBlock, isValid } = + await contracts.randomSampling.getActiveProofPeriodStatus(); + if (isValid) { + // Find out how many blocks are left in the current proofing period + const blocksLeft = + Number(activeProofPeriodStartBlock) + + Number(proofingPeriodDuration) - + Number(await hre.network.provider.send('eth_blockNumber')) + + 1; + for (let i = 0; i < blocksLeft; i++) { + await hre.network.provider.send('evm_mine'); + } + } + await contracts.randomSampling.updateAndGetActiveProofPeriodStartBlock(); +} + +// Helper function to submit proof and log scores +async function submitProofAndLogScore( + nodeId: number, + nodeAccount: { operational: SignerWithAddress; admin: SignerWithAddress }, + contracts: any, // eslint-disable-line @typescript-eslint/no-explicit-any + epoch: bigint, +) { + // Get score before proof + const scoreBefore = await contracts.randomSamplingStorage.getNodeEpochScore( + epoch, + nodeId, + ); + + // Create challenge and submit proof + await contracts.randomSampling + .connect(nodeAccount.operational) + .createChallenge(); + const challenge = + await contracts.randomSamplingStorage.getNodeChallenge(nodeId); + + // Calculate merkle proof for the challenge + const chunks = kcTools.splitIntoChunks(quads, 32); + const chunkId = Number(challenge[1]); + const { proof } = kcTools.calculateMerkleProof(quads, 32, chunkId); + + await contracts.randomSampling + .connect(nodeAccount.operational) + .submitProof(chunks[chunkId], proof); + + // Get score after proof + const scoreAfter = await contracts.randomSamplingStorage.getNodeEpochScore( + epoch, + nodeId, + ); + const scorePerStake = + await contracts.randomSamplingStorage.getNodeEpochScorePerStake( + epoch, + nodeId, + ); + + return { scoreBefore, scoreAfter, scorePerStake }; +} + +/* ───────────────────── fixture: build initial state ───────────────────── */ + +export async function buildInitialRewardsState() { + await hre.deployments.fixture(); + + const signers = await hre.ethers.getSigners(); + + const contracts = { + hub: await hre.ethers.getContract('Hub'), + token: await hre.ethers.getContract('Token'), + chronos: await hre.ethers.getContract('Chronos'), + profile: await hre.ethers.getContract('Profile'), + staking: await hre.ethers.getContract('Staking'), + stakingStorage: + await hre.ethers.getContract('StakingStorage'), + delegatorsInfo: + await hre.ethers.getContract('DelegatorsInfo'), + randomSamplingStorage: await hre.ethers.getContract( + 'RandomSamplingStorage', + ), + randomSampling: + await hre.ethers.getContract('RandomSampling'), + epochStorage: await hre.ethers.getContract('EpochStorageV8'), + kc: await hre.ethers.getContract( + 'KnowledgeCollection', + ), + ask: await hre.ethers.getContract('Ask'), + askStorage: await hre.ethers.getContract('AskStorage'), + parametersStorage: + await hre.ethers.getContract('ParametersStorage'), + profileStorage: + await hre.ethers.getContract('ProfileStorage'), + }; + + // Get chunk size to avoid division by zero in challenge generation + const chunkSize = Number( + await contracts.randomSamplingStorage.CHUNK_BYTE_SIZE(), + ); + + const accounts = { + owner: signers[0], + // 4 nodes with separate operational and admin wallets + node1: { operational: signers[1], admin: signers[2] }, + node2: { operational: signers[3], admin: signers[4] }, + node3: { operational: signers[5], admin: signers[6] }, + node4: { operational: signers[7], admin: signers[8] }, + // 12 delegators now (need more for the new distribution) + delegators: signers.slice(10, 22), + kcCreator: signers[9], + }; + + // Create receiving nodes arrays for proof submissions (all nodes) + const receivingNodes = [ + accounts.node1, + accounts.node2, + accounts.node3, + accounts.node4, + ]; + const receivingNodesIdentityIds: number[] = []; + + await contracts.hub.setContractAddress('HubOwner', accounts.owner.address); + + // Initialize ask system to prevent division by zero + await contracts.parametersStorage.setMinimumStake(toTRAC(100)); + await contracts.parametersStorage + .connect(accounts.owner) + .setOperatorFeeUpdateDelay(0); + + // Mint tokens for all delegators + for (const delegator of accounts.delegators) { + await contracts.token.mint(delegator.address, toTRAC(1_000_000)); + } + await contracts.token.mint(accounts.kcCreator.address, toTRAC(1_000_000)); + + // Create node profiles + const { identityId: node1Id } = await createProfile( + contracts.profile, + accounts.node1, + ); + const { identityId: node2Id } = await createProfile( + contracts.profile, + accounts.node2, + ); + const { identityId: node3Id } = await createProfile( + contracts.profile, + accounts.node3, + ); + const { identityId: node4Id } = await createProfile( + contracts.profile, + accounts.node4, + ); + + // Set operator fees to 10% + await contracts.profile + .connect(accounts.node1.admin) + .updateOperatorFee(node1Id, 1000); + await contracts.profile + .connect(accounts.node2.admin) + .updateOperatorFee(node2Id, 1000); + await contracts.profile + .connect(accounts.node3.admin) + .updateOperatorFee(node3Id, 1000); + await contracts.profile + .connect(accounts.node4.admin) + .updateOperatorFee(node4Id, 1000); + + // Populate receiving nodes identity IDs + receivingNodesIdentityIds.push(node1Id, node2Id, node3Id, node4Id); + + // Initialize ask system for nodes + const nodeAsk = hre.ethers.parseUnits('0.2', 18); + await contracts.profile + .connect(accounts.node1.operational) + .updateAsk(node1Id, nodeAsk); + await contracts.profile + .connect(accounts.node2.operational) + .updateAsk(node2Id, nodeAsk); + await contracts.profile + .connect(accounts.node3.operational) + .updateAsk(node3Id, nodeAsk); + await contracts.profile + .connect(accounts.node4.operational) + .updateAsk(node4Id, nodeAsk); + await contracts.ask.connect(accounts.owner).recalculateActiveSet(); + + const nodes = [ + { + identityId: node1Id, + operational: accounts.node1.operational, + admin: accounts.node1.admin, + }, + { + identityId: node2Id, + operational: accounts.node2.operational, + admin: accounts.node2.admin, + }, + { + identityId: node3Id, + operational: accounts.node3.operational, + admin: accounts.node3.admin, + }, + { + identityId: node4Id, + operational: accounts.node4.operational, + admin: accounts.node4.admin, + }, + ]; + + // Jump to clean epoch start + const timeUntilNextEpoch = await contracts.chronos.timeUntilNextEpoch(); + await time.increase(timeUntilNextEpoch + 1n); + + // Fast-forward to epoch-2 + while ((await contracts.chronos.getCurrentEpoch()) < 2n) { + await time.increase((await contracts.chronos.timeUntilNextEpoch()) + 1n); + } + + // Create identical reward pools for epoch-2 (each node publishes same amount) + const kcTokenAmount = toTRAC(250); // Split total among 4 nodes + const numberOfEpochs = 5; + const { kcTools } = await import('assertion-tools'); + const merkleRoot = kcTools.calculateMerkleRoot(quads, 32); + + // Create identical KC for each node to ensure equal publishing values + for (let i = 0; i < nodes.length; i++) { + const publisherNode = nodes[i]; + const otherNodes = nodes.filter((_, idx) => idx !== i); + const otherNodeIds = otherNodes.map((n) => n.identityId); + + await createKnowledgeCollection( + accounts.kcCreator, + publisherNode, + publisherNode.identityId, + otherNodes, + otherNodeIds, + { KnowledgeCollection: contracts.kc, Token: contracts.token }, + merkleRoot, + `epoch-2-node-${i + 1}-kc`, + 3, // Same knowledge assets amount for all + chunkSize * 3, // Same byte size for all + numberOfEpochs, + kcTokenAmount, // Same token amount for all + ); + } + + // EPOCH-2 STAKES: + // Node-1: D1→10k, D2→20k + // Node-2: D3→10k, D4→20k (same pattern as Node-1) + console.log( + '\n╔══════════════════════════════════════════════════════════════════════════════════╗', + ); + console.log( + '║ EPOCH-2 STAKING ║', + ); + console.log( + '╠══════════════════════════════════════════════════════════════════════════════════╣', + ); + + // Node-1 delegators + await contracts.token + .connect(accounts.delegators[0]) + .approve(await contracts.staking.getAddress(), toTRAC(10_000)); + await contracts.staking + .connect(accounts.delegators[0]) + .stake(node1Id, toTRAC(10_000)); + console.log( + '║ 📍 D1 → 10,000 TRAC → Node-1 ║', + ); + + await contracts.token + .connect(accounts.delegators[1]) + .approve(await contracts.staking.getAddress(), toTRAC(20_000)); + await contracts.staking + .connect(accounts.delegators[1]) + .stake(node1Id, toTRAC(20_000)); + console.log( + '║ 📍 D2 → 20,000 TRAC → Node-1 ║', + ); + + // Node-2 delegators (same pattern) + await contracts.token + .connect(accounts.delegators[2]) + .approve(await contracts.staking.getAddress(), toTRAC(10_000)); + await contracts.staking + .connect(accounts.delegators[2]) + .stake(node2Id, toTRAC(10_000)); + console.log( + '║ 📍 D3 → 10,000 TRAC → Node-2 ║', + ); + + await contracts.token + .connect(accounts.delegators[3]) + .approve(await contracts.staking.getAddress(), toTRAC(20_000)); + await contracts.staking + .connect(accounts.delegators[3]) + .stake(node2Id, toTRAC(20_000)); + console.log( + '║ 📍 D4 → 20,000 TRAC → Node-2 ║', + ); + console.log( + '╚══════════════════════════════════════════════════════════════════════════════════╝', + ); + + // Submit proofs at end of epoch-2 + await advanceToNextProofingPeriod(contracts); + + // All nodes already have equal KC chunks from the identical KC creation above + // No need for ensureNodeHasChunksThisEpoch() since each node published identical KC + + console.log('\n🔬 EPOCH-2 PROOFS SUBMITTED:'); + const node1Proof2 = await submitProofAndLogScore( + node1Id, + accounts.node1, + contracts, + 2n, + 'Node-1', + ); + console.log( + ` ✅ Node-1: Score ${node1Proof2.scoreBefore} → ${node1Proof2.scoreAfter} (gain: ${node1Proof2.scoreAfter - node1Proof2.scoreBefore})`, + ); + + const node2Proof2 = await submitProofAndLogScore( + node2Id, + accounts.node2, + contracts, + 2n, + 'Node-2', + ); + console.log( + ` ✅ Node-2: Score ${node2Proof2.scoreBefore} → ${node2Proof2.scoreAfter} (gain: ${node2Proof2.scoreAfter - node2Proof2.scoreBefore})`, + ); + + const node3Proof2 = await submitProofAndLogScore( + node3Id, + accounts.node3, + contracts, + 2n, + 'Node-3', + ); + console.log( + ` ✅ Node-3: Score ${node3Proof2.scoreBefore} → ${node3Proof2.scoreAfter} (gain: ${node3Proof2.scoreAfter - node3Proof2.scoreBefore})`, + ); + + const node4Proof2 = await submitProofAndLogScore( + node4Id, + accounts.node4, + contracts, + 2n, + 'Node-4', + ); + console.log( + ` ✅ Node-4: Score ${node4Proof2.scoreBefore} → ${node4Proof2.scoreAfter} (gain: ${node4Proof2.scoreAfter - node4Proof2.scoreBefore})`, + ); + + // → EPOCH-3 + await time.increase((await contracts.chronos.timeUntilNextEpoch()) + 1n); + + // Create identical reward pools for epoch-3 (each node publishes same amount) + const kcTokenAmountEpoch3 = toTRAC(100); // Split total among 4 nodes + const numberOfEpochsEpoch3 = 1; + + // Create identical KC for each node to ensure equal publishing values + for (let i = 0; i < nodes.length; i++) { + const publisherNode = nodes[i]; + const otherNodes = nodes.filter((_, idx) => idx !== i); + const otherNodeIds = otherNodes.map((n) => n.identityId); + + await createKnowledgeCollection( + accounts.kcCreator, + publisherNode, + publisherNode.identityId, + otherNodes, + otherNodeIds, + { KnowledgeCollection: contracts.kc, Token: contracts.token }, + merkleRoot, + `epoch-3-node-${i + 1}-kc`, + 1, // Same knowledge assets amount for all + chunkSize * 5, // Same byte size for all + numberOfEpochsEpoch3, + kcTokenAmountEpoch3, // Same token amount for all + ); + } + + // EPOCH-3 STAKES: + // Node-1: D5→30k, D6→40k, D7→50k + // Node-2: D8→30k, D9→40k, D10→50k (same pattern as Node-1) + // Node-3: D11→60k, D12→50k (original Node-2 pattern from your request) + console.log( + '\n╔══════════════════════════════════════════════════════════════════════════════════╗', + ); + console.log( + '║ EPOCH-3 STAKING ║', + ); + console.log( + '╠══════════════════════════════════════════════════════════════════════════════════╣', + ); + + // Node-1 additional delegators + await contracts.token + .connect(accounts.delegators[4]) + .approve(await contracts.staking.getAddress(), toTRAC(30_000)); + await contracts.staking + .connect(accounts.delegators[4]) + .stake(node1Id, toTRAC(30_000)); + console.log( + '║ 📍 D5 → 30,000 TRAC → Node-1 ║', + ); + + await contracts.token + .connect(accounts.delegators[5]) + .approve(await contracts.staking.getAddress(), toTRAC(40_000)); + await contracts.staking + .connect(accounts.delegators[5]) + .stake(node1Id, toTRAC(40_000)); + console.log( + '║ 📍 D6 → 40,000 TRAC → Node-1 ║', + ); + + await contracts.token + .connect(accounts.delegators[6]) + .approve(await contracts.staking.getAddress(), toTRAC(50_000)); + await contracts.staking + .connect(accounts.delegators[6]) + .stake(node1Id, toTRAC(50_000)); + console.log( + '║ 📍 D7 → 50,000 TRAC → Node-1 ║', + ); + + // Node-2 additional delegators (same pattern as Node-1) + await contracts.token + .connect(accounts.delegators[7]) + .approve(await contracts.staking.getAddress(), toTRAC(30_000)); + await contracts.staking + .connect(accounts.delegators[7]) + .stake(node2Id, toTRAC(30_000)); + console.log( + '║ 📍 D8 → 30,000 TRAC → Node-2 ║', + ); + + await contracts.token + .connect(accounts.delegators[8]) + .approve(await contracts.staking.getAddress(), toTRAC(40_000)); + await contracts.staking + .connect(accounts.delegators[8]) + .stake(node2Id, toTRAC(40_000)); + console.log( + '║ 📍 D9 → 40,000 TRAC → Node-2 ║', + ); + + await contracts.token + .connect(accounts.delegators[9]) + .approve(await contracts.staking.getAddress(), toTRAC(50_000)); + await contracts.staking + .connect(accounts.delegators[9]) + .stake(node2Id, toTRAC(50_000)); + console.log( + '║ 📍 D10 → 50,000 TRAC → Node-2 ║', + ); + + // Node-3 delegators (your original Node-2 pattern) + await contracts.token + .connect(accounts.delegators[10]) + .approve(await contracts.staking.getAddress(), toTRAC(60_000)); + await contracts.staking + .connect(accounts.delegators[10]) + .stake(node3Id, toTRAC(60_000)); + console.log( + '║ 📍 D11 → 60,000 TRAC → Node-3 ║', + ); + + await contracts.token + .connect(accounts.delegators[11]) + .approve(await contracts.staking.getAddress(), toTRAC(50_000)); + await contracts.staking + .connect(accounts.delegators[11]) + .stake(node3Id, toTRAC(50_000)); + console.log( + '║ 📍 D12 → 50,000 TRAC → Node-3 ║', + ); + console.log( + '╚══════════════════════════════════════════════════════════════════════════════════╝', + ); + + // Submit proofs at end of epoch-3 + await advanceToNextProofingPeriod(contracts); + + // All nodes already have equal KC chunks from the identical KC creation above + // No need for ensureNodeHasChunksThisEpoch() since each node published identical KC + + console.log('\n🔬 EPOCH-3 PROOFS SUBMITTED:'); + const node1Proof3 = await submitProofAndLogScore( + node1Id, + accounts.node1, + contracts, + 3n, + 'Node-1', + ); + console.log( + ` ✅ Node-1: Score ${node1Proof3.scoreBefore} → ${node1Proof3.scoreAfter} (gain: ${node1Proof3.scoreAfter - node1Proof3.scoreBefore})`, + ); + + const node2Proof3 = await submitProofAndLogScore( + node2Id, + accounts.node2, + contracts, + 3n, + 'Node-2', + ); + console.log( + ` ✅ Node-2: Score ${node2Proof3.scoreBefore} → ${node2Proof3.scoreAfter} (gain: ${node2Proof3.scoreAfter - node2Proof3.scoreBefore})`, + ); + + const node3Proof3 = await submitProofAndLogScore( + node3Id, + accounts.node3, + contracts, + 3n, + 'Node-3', + ); + console.log( + ` ✅ Node-3: Score ${node3Proof3.scoreBefore} → ${node3Proof3.scoreAfter} (gain: ${node3Proof3.scoreAfter - node3Proof3.scoreBefore})`, + ); + + const node4Proof3 = await submitProofAndLogScore( + node4Id, + accounts.node4, + contracts, + 3n, + 'Node-4', + ); + console.log( + ` ✅ Node-4: Score ${node4Proof3.scoreBefore} → ${node4Proof3.scoreAfter} (gain: ${node4Proof3.scoreAfter - node4Proof3.scoreBefore})`, + ); + + // → EPOCH-4 (to finalize epoch-3) + await time.increase((await contracts.chronos.timeUntilNextEpoch()) + 1n); + + // Create KC to finalize epoch-3 (this is crucial for epoch finalization!) + await createKnowledgeCollection( + accounts.kcCreator, + accounts.node4, + node4Id, + [accounts.node1, accounts.node2, accounts.node3], + [node1Id, node2Id, node3Id], + { KnowledgeCollection: contracts.kc, Token: contracts.token }, + merkleRoot, // Use consistent merkleRoot from quads + 'finalize-epoch-3', + 10, + chunkSize * 20, // byteSize - use multiple of chunkSize + 10, + toTRAC(50_000), + ); + + // Submit proofs at end of epoch-4 + await advanceToNextProofingPeriod(contracts); + + // Ensure all nodes have chunks before submitting proofs for epoch-4 + await ensureNodeHasChunksThisEpoch( + node1Id, + accounts.node1, + contracts, + accounts, + receivingNodes, + receivingNodesIdentityIds, + chunkSize, + ); + await ensureNodeHasChunksThisEpoch( + node2Id, + accounts.node2, + contracts, + accounts, + receivingNodes, + receivingNodesIdentityIds, + chunkSize, + ); + await ensureNodeHasChunksThisEpoch( + node3Id, + accounts.node3, + contracts, + accounts, + receivingNodes, + receivingNodesIdentityIds, + chunkSize, + ); + await ensureNodeHasChunksThisEpoch( + node4Id, + accounts.node4, + contracts, + accounts, + receivingNodes, + receivingNodesIdentityIds, + chunkSize, + ); + + console.log('\n🔬 EPOCH-4 PROOFS SUBMITTED:'); + const node1Proof4 = await submitProofAndLogScore( + node1Id, + accounts.node1, + contracts, + 4n, + 'Node-1', + ); + console.log( + ` ✅ Node-1: Score ${node1Proof4.scoreBefore} → ${node1Proof4.scoreAfter} (gain: ${node1Proof4.scoreAfter - node1Proof4.scoreBefore})`, + ); + + const node2Proof4 = await submitProofAndLogScore( + node2Id, + accounts.node2, + contracts, + 4n, + 'Node-2', + ); + console.log( + ` ✅ Node-2: Score ${node2Proof4.scoreBefore} → ${node2Proof4.scoreAfter} (gain: ${node2Proof4.scoreAfter - node2Proof4.scoreBefore})`, + ); + + const node3Proof4 = await submitProofAndLogScore( + node3Id, + accounts.node3, + contracts, + 4n, + 'Node-3', + ); + console.log( + ` ✅ Node-3: Score ${node3Proof4.scoreBefore} → ${node3Proof4.scoreAfter} (gain: ${node3Proof4.scoreAfter - node3Proof4.scoreBefore})`, + ); + + const node4Proof4 = await submitProofAndLogScore( + node4Id, + accounts.node4, + contracts, + 4n, + 'Node-4', + ); + console.log( + ` ✅ Node-4: Score ${node4Proof4.scoreBefore} → ${node4Proof4.scoreAfter} (gain: ${node4Proof4.scoreAfter - node4Proof4.scoreBefore})`, + ); + + // → EPOCH-5 + await time.increase((await contracts.chronos.timeUntilNextEpoch()) + 1n); + + // Create KC for epoch-5 to ensure there's activity + await createKnowledgeCollection( + accounts.kcCreator, + accounts.node1, + node1Id, + [accounts.node2, accounts.node3, accounts.node4], + [node2Id, node3Id, node4Id], + { KnowledgeCollection: contracts.kc, Token: contracts.token }, + merkleRoot, // Use consistent merkleRoot from quads + 'epoch-5-no-proofs', + 5, + chunkSize * 15, // byteSize - use multiple of chunkSize + 3, + toTRAC(2_000), + ); + + // EPOCH-5 STAKES: + // Add delegator 13 and 14 with 35k TRAC each + console.log( + '\n╔══════════════════════════════════════════════════════════════════════════════════╗', + ); + console.log( + '║ EPOCH-5 STAKING ║', + ); + console.log( + '╠══════════════════════════════════════════════════════════════════════════════════╣', + ); + + // Need to add more delegators to accounts since we only had 12 before + if (accounts.delegators.length < 14) { + const additionalDelegators = signers.slice(22, 24); // Get signers 22 and 23 for D13 and D14 + accounts.delegators.push(...additionalDelegators); + + // Mint tokens for new delegators + for (const delegator of additionalDelegators) { + await contracts.token.mint(delegator.address, toTRAC(1_000_000)); + } + } + + // D13 stakes 35k to Node-1 + await contracts.token + .connect(accounts.delegators[12]) + .approve(await contracts.staking.getAddress(), toTRAC(35_000)); + await contracts.staking + .connect(accounts.delegators[12]) + .stake(node1Id, toTRAC(35_000)); + console.log( + '║ 📍 D13 → 35,000 TRAC → Node-1 ║', + ); + + // D14 stakes 35k to Node-2 + await contracts.token + .connect(accounts.delegators[13]) + .approve(await contracts.staking.getAddress(), toTRAC(35_000)); + await contracts.staking + .connect(accounts.delegators[13]) + .stake(node2Id, toTRAC(35_000)); + console.log( + '║ 📍 D14 → 35,000 TRAC → Node-2 ║', + ); + console.log( + '╚══════════════════════════════════════════════════════════════════════════════════╝', + ); + + console.log('\n🚫 EPOCH-5: NO PROOFS SUBMITTED'); + + // → EPOCH-6 (to finalize epoch-5) + await time.increase((await contracts.chronos.timeUntilNextEpoch()) + 1n); + + // Create KC for epoch-6 to finalize epoch-5 + await createKnowledgeCollection( + accounts.kcCreator, + accounts.node3, + node3Id, + [accounts.node1, accounts.node2, accounts.node4], + [node1Id, node2Id, node4Id], + { KnowledgeCollection: contracts.kc, Token: contracts.token }, + merkleRoot, // Use consistent merkleRoot from quads + 'finalize-epoch-5', + 8, + chunkSize * 25, // byteSize - use multiple of chunkSize + 5, + toTRAC(10_000), + ); + + console.log('\n🚫 EPOCH-6: NO PROOFS SUBMITTED'); + + // → EPOCH-7 (to finalize epoch-6) + await time.increase((await contracts.chronos.timeUntilNextEpoch()) + 1n); + + // Create KC for epoch-7 to finalize epoch-6 + await createKnowledgeCollection( + accounts.kcCreator, + accounts.node4, + node4Id, + [accounts.node1, accounts.node2, accounts.node3], + [node1Id, node2Id, node3Id], + { KnowledgeCollection: contracts.kc, Token: contracts.token }, + merkleRoot, // Use consistent merkleRoot from quads + 'finalize-epoch-6', + 12, + chunkSize * 30, // byteSize - use multiple of chunkSize + 8, + toTRAC(15_000), + ); + + console.log('\n📝 EPOCH-7: System ready for comprehensive testing'); + + // Print detailed snapshot + console.log('\n'); + console.log( + '═══════════════════════════════════════════════════════════════════════════════════════════════', + ); + console.log( + ' 🎯 FINAL SYSTEM STATE 🎯 ', + ); + console.log( + '═══════════════════════════════════════════════════════════════════════════════════════════════', + ); + + const currentEpoch = await contracts.chronos.getCurrentEpoch(); + const lastFinalizedEpoch = await contracts.epochStorage.lastFinalizedEpoch(1); + console.log( + `📅 Current Epoch: ${currentEpoch} | Last Finalized: ${lastFinalizedEpoch}`, + ); + console.log(''); + + console.log( + '┌─────────────────────────────────────────────────────────────────────────────────────────────┐', + ); + console.log( + '│ 📊 STAKING TIMELINE │', + ); + console.log( + '├─────────────────────────────────────────────────────────────────────────────────────────────┤', + ); + console.log( + '│ EPOCH-2: D1→10k, D2→20k (Node-1) │ D3→10k, D4→20k (Node-2) │ All nodes proofs │', + ); + console.log( + '│ EPOCH-3: D5→30k, D6→40k, D7→50k (Node-1) │ D8→30k, D9→40k, D10→50k (Node-2) │', + ); + console.log( + '│ D11→60k, D12→50k (Node-3) │ All nodes submitted proofs │', + ); + console.log( + '│ EPOCH-4: All nodes submitted proofs │', + ); + console.log( + '│ EPOCH-5: D13→35k (Node-1) │ D14→35k (Node-2) │ NO PROOFS SUBMITTED │', + ); + console.log( + '│ EPOCH-6: NO PROOFS SUBMITTED (finalization epoch for epoch-5) │', + ); + console.log( + '│ EPOCH-7: Current epoch (finalization epoch for epoch-6) │', + ); + console.log( + '└─────────────────────────────────────────────────────────────────────────────────────────────┘', + ); + console.log(''); + + for (const [i, node] of nodes.entries()) { + const totalStake = await contracts.stakingStorage.getNodeStake( + node.identityId, + ); + const nodeScore2 = await contracts.randomSamplingStorage.getNodeEpochScore( + 2n, + node.identityId, + ); + const nodeScore3 = await contracts.randomSamplingStorage.getNodeEpochScore( + 3n, + node.identityId, + ); + const nodeScore4 = await contracts.randomSamplingStorage.getNodeEpochScore( + 4n, + node.identityId, + ); + const nodeScore5 = await contracts.randomSamplingStorage.getNodeEpochScore( + 5n, + node.identityId, + ); + + console.log(`🚀 Node-${i + 1} (ID: ${node.identityId})`); + console.log( + ` 💰 Total Stake: ${hre.ethers.formatUnits(totalStake, 18)} TRAC | 🎯 Operator Fee: 10%`, + ); + console.log( + ` 📊 Scores → E2: ${nodeScore2} | E3: ${nodeScore3} | E4: ${nodeScore4} | E5: ${nodeScore5}`, + ); + + const delegatorStakes = []; + for (let d = 0; d < accounts.delegators.length; d++) { + const key = hre.ethers.keccak256( + hre.ethers.solidityPacked( + ['address'], + [accounts.delegators[d].address], + ), + ); + const stake = await contracts.stakingStorage.getDelegatorStakeBase( + node.identityId, + key, + ); + if (stake > 0n) { + delegatorStakes.push(`D${d + 1}: ${hre.ethers.formatUnits(stake, 18)}`); + } + } + + if (delegatorStakes.length > 0) { + console.log(` 👥 Delegators: ${delegatorStakes.join(' | ')}`); + } + console.log(''); + } + + console.log( + '═══════════════════════════════════════════════════════════════════════════════════════════════\n', + ); + + // Return environment for tests + return { + Token: contracts.token, + Profile: contracts.profile, + ProfileStorage: contracts.profileStorage, + Staking: contracts.staking, + StakingStorage: contracts.stakingStorage, + DelegatorsInfo: contracts.delegatorsInfo, + Chronos: contracts.chronos, + RandomSamplingStorage: contracts.randomSamplingStorage, + EpochStorage: contracts.epochStorage, + KC: contracts.kc, + delegators: accounts.delegators, + nodes, + receivingNodes, + receivingNodesIdentityIds, + accounts, + }; +} + +/* ───────────────────────────── tests ───────────────────────────── */ + +describe('rewards tests', () => { + /* fixture state visible to all tests in this describe-block */ + let env: Awaited>; + + before(async () => { + env = await buildInitialRewardsState(); + }); + + /* 1️⃣ Claim-jumping guard. */ + it('D1 cannot claim the newest finalised epoch while older remain unclaimed', async () => { + const { Staking, EpochStorage, delegators, nodes } = env; + const newestFinalised = await EpochStorage.lastFinalizedEpoch(1); // == 3 + await expect( + Staking.connect(delegators[0]).claimDelegatorRewards( + nodes[0].identityId, + newestFinalised, + delegators[0].address, + ), + ).to.be.reverted; + }); + + /* 2️⃣ Operator-fee sanity (all nodes @ 1000 ‱). */ + it('every node stores 10 % operator fee', async () => { + const { ProfileStorage, nodes } = env; + for (const n of nodes) { + const opFee = await ProfileStorage.getOperatorFee(n.identityId); + expect(opFee).to.equal(1000); // 1000 ‱ == 10 % + } + }); + + /* Add more `it()` tests below using env.* contracts & objects. */ +}); + +describe('Claim order enforcement tests', () => { + /* fixture state visible to all tests in this describe-block */ + let env: Awaited>; + + before(async () => { + env = await buildInitialRewardsState(); + }); + + it('D1, D3 attempt to claim epoch 3 rewards - should revert (must claim epoch 2 first)', async () => { + const { Staking, delegators, nodes } = env; + + console.log( + '\n⛔ TEST 1: D1, D3 attempting to claim epoch 3 - should revert', + ); + + // D1 attempts to claim epoch 3 + await expect( + Staking.connect(delegators[0]).claimDelegatorRewards( + nodes[0].identityId, // Node-1 + 3n, // epoch 3 + delegators[0].address, + ), + ).to.be.revertedWith('Must claim older epochs first'); + + console.log(' ✅ D1 claim for epoch 3 reverted as expected'); + + // D3 attempts to claim epoch 3 + await expect( + Staking.connect(delegators[2]).claimDelegatorRewards( + nodes[1].identityId, // Node-2 + 3n, // epoch 3 + delegators[2].address, + ), + ).to.be.revertedWith('Must claim older epochs first'); + + console.log(' ✅ D3 claim for epoch 3 reverted as expected'); + }); + + it('D1, D3 attempt to claim epoch 4 rewards - should revert (must claim epoch 2 first)', async () => { + const { Staking, delegators, nodes } = env; + + console.log( + '\n⛔ TEST 2: D1, D3 attempting to claim epoch 4 - should revert', + ); + + // D1 attempts to claim epoch 4 + await expect( + Staking.connect(delegators[0]).claimDelegatorRewards( + nodes[0].identityId, // Node-1 + 4n, // epoch 4 + delegators[0].address, + ), + ).to.be.revertedWith('Must claim older epochs first'); + + console.log(' ✅ D1 claim for epoch 4 reverted as expected'); + + // D3 attempts to claim epoch 4 + await expect( + Staking.connect(delegators[2]).claimDelegatorRewards( + nodes[1].identityId, // Node-2 + 4n, // epoch 4 + delegators[2].address, + ), + ).to.be.revertedWith('Must claim older epochs first'); + + console.log(' ✅ D3 claim for epoch 4 reverted as expected'); + }); + + it('D1, D3 attempt to claim epoch 5 rewards - should revert (must claim epoch 2 first)', async () => { + const { Staking, delegators, nodes } = env; + + console.log( + '\n⛔ TEST 3: D1, D3 attempting to claim epoch 5 - should revert', + ); + + // D1 attempts to claim epoch 5 + await expect( + Staking.connect(delegators[0]).claimDelegatorRewards( + nodes[0].identityId, // Node-1 + 5n, // epoch 5 + delegators[0].address, + ), + ).to.be.revertedWith('Must claim older epochs first'); + + console.log(' ✅ D1 claim for epoch 5 reverted as expected'); + + // D3 attempts to claim epoch 5 + await expect( + Staking.connect(delegators[2]).claimDelegatorRewards( + nodes[1].identityId, // Node-2 + 5n, // epoch 5 + delegators[2].address, + ), + ).to.be.revertedWith('Must claim older epochs first'); + + console.log(' ✅ D3 claim for epoch 5 reverted as expected'); + }); + + it('D5, D8, D10 attempt to claim epoch 2 rewards - should revert (were not delegators in that epoch)', async () => { + const { Staking, delegators, nodes } = env; + + console.log( + '\n⛔ TEST 4: D5, D8, D10 attempting to claim epoch 2 - should revert (not delegators then)', + ); + + // D5 attempts to claim epoch 2 (but was not delegator in epoch 2) + await expect( + Staking.connect(delegators[4]).claimDelegatorRewards( + nodes[0].identityId, // Node-1 + 2n, // epoch 2 + delegators[4].address, + ), + ).to.be.revertedWith('Epoch already claimed'); + + console.log( + ' ✅ D5 claim for epoch 2 reverted as expected (was not delegator)', + ); + + // D8 attempts to claim epoch 2 (but was not delegator in epoch 2) + await expect( + Staking.connect(delegators[7]).claimDelegatorRewards( + nodes[1].identityId, // Node-2 + 2n, // epoch 2 + delegators[7].address, + ), + ).to.be.revertedWith('Epoch already claimed'); + + console.log( + ' ✅ D8 claim for epoch 2 reverted as expected (was not delegator)', + ); + + // D10 attempts to claim epoch 2 (but was not delegator in epoch 2) + await expect( + Staking.connect(delegators[9]).claimDelegatorRewards( + nodes[1].identityId, // Node-2 + 2n, // epoch 2 + delegators[9].address, + ), + ).to.be.revertedWith('Epoch already claimed'); + + console.log( + ' ✅ D10 claim for epoch 2 reverted as expected (was not delegator)', + ); + }); + + it('D1, D3 successfully claim epoch 2 rewards - should succeed with equal rewards', async () => { + const { + Staking, + StakingStorage, + DelegatorsInfo, + RandomSamplingStorage, + delegators, + nodes, + } = env; + + console.log('\n✅ TEST 5: D1, D3 successfully claiming epoch 2 rewards'); + + // Get initial state + const d1Key = hre.ethers.keccak256( + hre.ethers.solidityPacked(['address'], [delegators[0].address]), + ); + const d3Key = hre.ethers.keccak256( + hre.ethers.solidityPacked(['address'], [delegators[2].address]), + ); + + const d1StakeBaseBefore = await StakingStorage.getDelegatorStakeBase( + nodes[0].identityId, + d1Key, + ); + const d3StakeBaseBefore = await StakingStorage.getDelegatorStakeBase( + nodes[1].identityId, + d3Key, + ); + + const d1RollingBefore = await DelegatorsInfo.getDelegatorRollingRewards( + nodes[0].identityId, + delegators[0].address, + ); + const d3RollingBefore = await DelegatorsInfo.getDelegatorRollingRewards( + nodes[1].identityId, + delegators[2].address, + ); + + // Verify nodes have equal scores (due to identical KC setup) + const node1Score2 = await RandomSamplingStorage.getNodeEpochScore( + 2n, + nodes[0].identityId, + ); + const node2Score2 = await RandomSamplingStorage.getNodeEpochScore( + 2n, + nodes[1].identityId, + ); + + expect(node1Score2).to.equal( + node2Score2, + 'Node-1 and Node-2 should have equal scores', + ); + console.log(` 📊 Both nodes have equal score: ${node1Score2}`); + + // D1 claims epoch 2 rewards + await Staking.connect(delegators[0]).claimDelegatorRewards( + nodes[0].identityId, // Node-1 + 2n, // epoch 2 + delegators[0].address, + ); + + console.log(' ✅ D1 successfully claimed epoch 2 rewards'); + + // D3 claims epoch 2 rewards + await Staking.connect(delegators[2]).claimDelegatorRewards( + nodes[1].identityId, // Node-2 + 2n, // epoch 2 + delegators[2].address, + ); + + console.log(' ✅ D3 successfully claimed epoch 2 rewards'); + + // Get final state + const d1StakeBaseAfter = await StakingStorage.getDelegatorStakeBase( + nodes[0].identityId, + d1Key, + ); + const d3StakeBaseAfter = await StakingStorage.getDelegatorStakeBase( + nodes[1].identityId, + d3Key, + ); + + const d1RollingAfter = await DelegatorsInfo.getDelegatorRollingRewards( + nodes[0].identityId, + delegators[0].address, + ); + const d3RollingAfter = await DelegatorsInfo.getDelegatorRollingRewards( + nodes[1].identityId, + delegators[2].address, + ); + + // Calculate rewards and stake changes + const d1Reward = d1RollingAfter - d1RollingBefore; + const d3Reward = d3RollingAfter - d3RollingBefore; + const d1StakeChange = d1StakeBaseAfter - d1StakeBaseBefore; + const d3StakeChange = d3StakeBaseAfter - d3StakeBaseBefore; + + console.log( + ` 💰 D1 rolling reward: ${hre.ethers.formatUnits(d1Reward, 18)} TRAC`, + ); + console.log( + ` 💰 D3 rolling reward: ${hre.ethers.formatUnits(d3Reward, 18)} TRAC`, + ); + + // Verify equal rewards (since equal stakes and equal node scores) + expect(d1Reward).to.equal( + d3Reward, + 'D1 and D3 should receive equal rewards', + ); + + // StakeBase should not change (future epochs remain to claim) + expect(d1StakeChange).to.equal( + 0n, + 'D1 stakeBase should not change (rolling rewards)', + ); + expect(d3StakeChange).to.equal( + 0n, + 'D3 stakeBase should not change (rolling rewards)', + ); + + // Both should receive positive rewards + expect(d1Reward).to.be.gt(0n, 'D1 rolling rewards should be positive'); + expect(d3Reward).to.be.gt(0n, 'D3 rolling rewards should be positive'); + + console.log(' ✅ Both delegators received equal rolling rewards'); + console.log( + ' ✅ StakeBase remained unchanged - rewards went to rolling rewards', + ); + console.log( + ' 📝 Note: Equal stakes + equal node performance = equal rewards', + ); + }); + + it('Node scores verification - Node-1 and Node-2 should have identical scores in epoch 2', async () => { + const { RandomSamplingStorage, nodes } = env; + + console.log('\n✅ TEST 6: Verifying equal node scores in epoch 2'); + + // Get node scores for epoch 2 + const node1Score = await RandomSamplingStorage.getNodeEpochScore( + 2n, + nodes[0].identityId, + ); + const node2Score = await RandomSamplingStorage.getNodeEpochScore( + 2n, + nodes[1].identityId, + ); + const node3Score = await RandomSamplingStorage.getNodeEpochScore( + 2n, + nodes[2].identityId, + ); + const node4Score = await RandomSamplingStorage.getNodeEpochScore( + 2n, + nodes[3].identityId, + ); + + // Get score per stake + const node1ScorePerStake = + await RandomSamplingStorage.getNodeEpochScorePerStake( + 2n, + nodes[0].identityId, + ); + const node2ScorePerStake = + await RandomSamplingStorage.getNodeEpochScorePerStake( + 2n, + nodes[1].identityId, + ); + + console.log(` 📊 Node-1 score: ${node1Score}`); + console.log(` 📊 Node-2 score: ${node2Score}`); + console.log(` 📊 Node-3 score: ${node3Score} (should be 0 - no stake)`); + console.log(` 📊 Node-4 score: ${node4Score} (should be 0 - no stake)`); + console.log(` 📈 Node-1 score per stake: ${node1ScorePerStake}`); + console.log(` 📈 Node-2 score per stake: ${node2ScorePerStake}`); + + // Verify equal scores for nodes with stakes + expect(node1Score).to.equal( + node2Score, + 'Node-1 and Node-2 should have equal total scores', + ); + expect(node1ScorePerStake).to.equal( + node2ScorePerStake, + 'Node-1 and Node-2 should have equal score per stake', + ); + + // Verify zero scores for nodes without stakes + expect(node3Score).to.equal( + 0n, + 'Node-3 should have zero score (no stake in epoch 2)', + ); + expect(node4Score).to.equal( + 0n, + 'Node-4 should have zero score (no stake in epoch 2)', + ); + + // Both nodes should have positive scores + expect(node1Score).to.be.gt(0n, 'Node-1 should have positive score'); + expect(node2Score).to.be.gt(0n, 'Node-2 should have positive score'); + + console.log( + ' ✅ Node-1 and Node-2 have identical scores and score per stake', + ); + console.log( + ' ✅ Node-3 and Node-4 have zero scores (no stakes in epoch 2)', + ); + console.log( + ' 📝 Note: Equal KC setup resulted in equal node performance', + ); + }); + + it('D1, D3 claim epoch 3 rewards - rolling rewards should accumulate', async () => { + const { + Staking, + DelegatorsInfo, + RandomSamplingStorage, + delegators, + nodes, + } = env; + + console.log( + '\n✅ TEST 7: D1, D3 claiming epoch 3 rewards - rolling accumulation', + ); + + // Get rolling rewards after epoch 2 claims (from previous test) + const d1RollingAfterEpoch2 = + await DelegatorsInfo.getDelegatorRollingRewards( + nodes[0].identityId, + delegators[0].address, + ); + const d3RollingAfterEpoch2 = + await DelegatorsInfo.getDelegatorRollingRewards( + nodes[1].identityId, + delegators[2].address, + ); + + console.log( + ` 🔄 D1 rolling after epoch 2: ${hre.ethers.formatUnits(d1RollingAfterEpoch2, 18)} TRAC`, + ); + console.log( + ` 🔄 D3 rolling after epoch 2: ${hre.ethers.formatUnits(d3RollingAfterEpoch2, 18)} TRAC`, + ); + + // Verify both have some rolling rewards from epoch 2 + expect(d1RollingAfterEpoch2).to.be.gt( + 0n, + 'D1 should have rolling rewards from epoch 2', + ); + expect(d3RollingAfterEpoch2).to.be.gt( + 0n, + 'D3 should have rolling rewards from epoch 2', + ); + + // Check epoch 3 node scores (these will be different due to different stakes) + const node1Score3 = await RandomSamplingStorage.getNodeEpochScore( + 3n, + nodes[0].identityId, + ); + const node2Score3 = await RandomSamplingStorage.getNodeEpochScore( + 3n, + nodes[1].identityId, + ); + + console.log(` 📊 Node-1 epoch 3 score: ${node1Score3}`); + console.log(` 📊 Node-2 epoch 3 score: ${node2Score3}`); + + // D1 claims epoch 3 rewards + await Staking.connect(delegators[0]).claimDelegatorRewards( + nodes[0].identityId, // Node-1 + 3n, // epoch 3 + delegators[0].address, + ); + + console.log(' ✅ D1 successfully claimed epoch 3 rewards'); + + // D3 claims epoch 3 rewards + await Staking.connect(delegators[2]).claimDelegatorRewards( + nodes[1].identityId, // Node-2 + 3n, // epoch 3 + delegators[2].address, + ); + + console.log(' ✅ D3 successfully claimed epoch 3 rewards'); + + // Get rolling rewards after epoch 3 claims + const d1RollingAfterEpoch3 = + await DelegatorsInfo.getDelegatorRollingRewards( + nodes[0].identityId, + delegators[0].address, + ); + const d3RollingAfterEpoch3 = + await DelegatorsInfo.getDelegatorRollingRewards( + nodes[1].identityId, + delegators[2].address, + ); + + // Calculate epoch 3 rewards + const d1Epoch3Reward = d1RollingAfterEpoch3 - d1RollingAfterEpoch2; + const d3Epoch3Reward = d3RollingAfterEpoch3 - d3RollingAfterEpoch2; + + console.log( + ` 💰 D1 epoch 3 reward: ${hre.ethers.formatUnits(d1Epoch3Reward, 18)} TRAC`, + ); + console.log( + ` 💰 D3 epoch 3 reward: ${hre.ethers.formatUnits(d3Epoch3Reward, 18)} TRAC`, + ); + console.log( + ` 🔄 D1 total rolling after epoch 3: ${hre.ethers.formatUnits(d1RollingAfterEpoch3, 18)} TRAC`, + ); + console.log( + ` 🔄 D3 total rolling after epoch 3: ${hre.ethers.formatUnits(d3RollingAfterEpoch3, 18)} TRAC`, + ); + + // Verify rolling rewards increased (accumulated) + expect(d1RollingAfterEpoch3).to.be.gt( + d1RollingAfterEpoch2, + 'D1 rolling rewards should increase after epoch 3 claim', + ); + expect(d3RollingAfterEpoch3).to.be.gt( + d3RollingAfterEpoch2, + 'D3 rolling rewards should increase after epoch 3 claim', + ); + + // Both should receive positive epoch 3 rewards + expect(d1Epoch3Reward).to.be.gt( + 0n, + 'D1 should receive positive epoch 3 rewards', + ); + expect(d3Epoch3Reward).to.be.gt( + 0n, + 'D3 should receive positive epoch 3 rewards', + ); + + // Verify accumulation: total = epoch2 + epoch3 + expect(d1RollingAfterEpoch3).to.equal( + d1RollingAfterEpoch2 + d1Epoch3Reward, + 'D1 total rolling should equal epoch 2 + epoch 3 rewards', + ); + expect(d3RollingAfterEpoch3).to.equal( + d3RollingAfterEpoch2 + d3Epoch3Reward, + 'D3 total rolling should equal epoch 2 + epoch 3 rewards', + ); + + console.log( + ' ✅ Rolling rewards successfully accumulated from both epochs', + ); + console.log(' ✅ Both delegators received positive epoch 3 rewards'); + console.log( + ' 📝 Note: Rolling rewards = Epoch 2 rewards + Epoch 3 rewards', + ); + }); + + it('D1, D3 attempt to claim epoch 5 rewards - should revert (must claim epoch 4 first)', async () => { + const { Staking, delegators, nodes } = env; + + console.log( + '\n⛔ TEST 8: D1, D3 attempting to claim epoch 5 - should revert (must claim epoch 4 first)', + ); + + // D1 attempts to claim epoch 5 (but hasn't claimed epoch 4 yet) + await expect( + Staking.connect(delegators[0]).claimDelegatorRewards( + nodes[0].identityId, // Node-1 + 5n, // epoch 5 + delegators[0].address, + ), + ).to.be.revertedWith('Must claim older epochs first'); + + console.log( + ' ✅ D1 claim for epoch 5 reverted as expected (must claim epoch 4 first)', + ); + + // D3 attempts to claim epoch 5 (but hasn't claimed epoch 4 yet) + await expect( + Staking.connect(delegators[2]).claimDelegatorRewards( + nodes[1].identityId, // Node-2 + 5n, // epoch 5 + delegators[2].address, + ), + ).to.be.revertedWith('Must claim older epochs first'); + + console.log( + ' ✅ D3 claim for epoch 5 reverted as expected (must claim epoch 4 first)', + ); + console.log( + ' 📝 Note: Sequential claiming enforced - cannot skip epoch 4', + ); + }); + + it('D1, D3 claim epoch 4 rewards - should succeed with equal rewards (equal stakes + all nodes submitted proofs)', async () => { + const { + Staking, + DelegatorsInfo, + RandomSamplingStorage, + delegators, + nodes, + } = env; + + console.log( + '\n✅ TEST 9: D1, D3 claiming epoch 4 rewards - should get equal rewards', + ); + + // Get rolling rewards before epoch 4 claims (should have epoch 2 + epoch 3 rewards) + const d1RollingBefore = await DelegatorsInfo.getDelegatorRollingRewards( + nodes[0].identityId, + delegators[0].address, + ); + const d3RollingBefore = await DelegatorsInfo.getDelegatorRollingRewards( + nodes[1].identityId, + delegators[2].address, + ); + + console.log( + ` 🔄 D1 rolling before epoch 4: ${hre.ethers.formatUnits(d1RollingBefore, 18)} TRAC`, + ); + console.log( + ` 🔄 D3 rolling before epoch 4: ${hre.ethers.formatUnits(d3RollingBefore, 18)} TRAC`, + ); + + // Check epoch 4 node scores (should be positive since all nodes submitted proofs) + const node1Score4 = await RandomSamplingStorage.getNodeEpochScore( + 4n, + nodes[0].identityId, + ); + const node2Score4 = await RandomSamplingStorage.getNodeEpochScore( + 4n, + nodes[1].identityId, + ); + + console.log(` 📊 Node-1 epoch 4 score: ${node1Score4}`); + console.log(` 📊 Node-2 epoch 4 score: ${node2Score4}`); + + // Both nodes should have positive scores (all submitted proofs) + expect(node1Score4).to.be.gt( + 0n, + 'Node-1 should have positive score in epoch 4', + ); + expect(node2Score4).to.be.gt( + 0n, + 'Node-2 should have positive score in epoch 4', + ); + + // D1 claims epoch 4 rewards + await Staking.connect(delegators[0]).claimDelegatorRewards( + nodes[0].identityId, // Node-1 + 4n, // epoch 4 + delegators[0].address, + ); + + console.log(' ✅ D1 successfully claimed epoch 4 rewards'); + + // D3 claims epoch 4 rewards + await Staking.connect(delegators[2]).claimDelegatorRewards( + nodes[1].identityId, // Node-2 + 4n, // epoch 4 + delegators[2].address, + ); + + console.log(' ✅ D3 successfully claimed epoch 4 rewards'); + + // Get rolling rewards after epoch 4 claims + const d1RollingAfter = await DelegatorsInfo.getDelegatorRollingRewards( + nodes[0].identityId, + delegators[0].address, + ); + const d3RollingAfter = await DelegatorsInfo.getDelegatorRollingRewards( + nodes[1].identityId, + delegators[2].address, + ); + + // Calculate epoch 4 rewards + const d1Epoch4Reward = d1RollingAfter - d1RollingBefore; + const d3Epoch4Reward = d3RollingAfter - d3RollingBefore; + + console.log( + ` 💰 D1 epoch 4 reward: ${hre.ethers.formatUnits(d1Epoch4Reward, 18)} TRAC`, + ); + console.log( + ` 💰 D3 epoch 4 reward: ${hre.ethers.formatUnits(d3Epoch4Reward, 18)} TRAC`, + ); + console.log( + ` 🔄 D1 total rolling after epoch 4: ${hre.ethers.formatUnits(d1RollingAfter, 18)} TRAC`, + ); + console.log( + ` 🔄 D3 total rolling after epoch 4: ${hre.ethers.formatUnits(d3RollingAfter, 18)} TRAC`, + ); + + // Verify rolling rewards increased (accumulated) + expect(d1RollingAfter).to.be.gt( + d1RollingBefore, + 'D1 rolling rewards should increase after epoch 4 claim', + ); + expect(d3RollingAfter).to.be.gt( + d3RollingBefore, + 'D3 rolling rewards should increase after epoch 4 claim', + ); + + // Both should receive positive epoch 4 rewards + expect(d1Epoch4Reward).to.be.gt( + 0n, + 'D1 should receive positive epoch 4 rewards', + ); + expect(d3Epoch4Reward).to.be.gt( + 0n, + 'D3 should receive positive epoch 4 rewards', + ); + + // Verify equal rewards (equal stakes in epoch 4, all nodes submitted proofs) + expect(d1Epoch4Reward).to.equal( + d3Epoch4Reward, + 'D1 and D3 should receive equal epoch 4 rewards (equal stakes)', + ); + + console.log( + ' ✅ Rolling rewards successfully accumulated (epochs 2+3+4)', + ); + console.log(' ✅ Both delegators received equal epoch 4 rewards'); + console.log( + ' 📝 Note: Equal stakes + all nodes submitted proofs = equal rewards', + ); + }); + + it('D1, D3 attempt to claim epoch 6 rewards - should revert (must claim epoch 5 first)', async () => { + const { Staking, delegators, nodes } = env; + + console.log( + '\n⛔ TEST 10: D1, D3 attempting to claim epoch 6 - should revert (must claim epoch 5 first)', + ); + + // D1 attempts to claim epoch 6 (but hasn't claimed epoch 5 yet) + await expect( + Staking.connect(delegators[0]).claimDelegatorRewards( + nodes[0].identityId, // Node-1 + 6n, // epoch 6 + delegators[0].address, + ), + ).to.be.revertedWith('Must claim older epochs first'); + + console.log( + ' ✅ D1 claim for epoch 6 reverted as expected (must claim epoch 5 first)', + ); + + // D3 attempts to claim epoch 6 (but hasn't claimed epoch 5 yet) + await expect( + Staking.connect(delegators[2]).claimDelegatorRewards( + nodes[1].identityId, // Node-2 + 6n, // epoch 6 + delegators[2].address, + ), + ).to.be.revertedWith('Must claim older epochs first'); + + console.log( + ' ✅ D3 claim for epoch 6 reverted as expected (must claim epoch 5 first)', + ); + console.log( + ' 📝 Note: Sequential claiming enforced - cannot skip epoch 5', + ); + }); + + it('D1, D3 claim epoch 5 rewards - should succeed with 0 rewards (no proofs submitted)', async () => { + const { + Staking, + DelegatorsInfo, + RandomSamplingStorage, + delegators, + nodes, + } = env; + + console.log( + '\n✅ TEST 11: D1, D3 claiming epoch 5 rewards - should get 0 rewards (no proofs)', + ); + + // Get rolling rewards before epoch 5 claims (should have epoch 2+3+4 rewards) + const d1RollingBefore = await DelegatorsInfo.getDelegatorRollingRewards( + nodes[0].identityId, + delegators[0].address, + ); + const d3RollingBefore = await DelegatorsInfo.getDelegatorRollingRewards( + nodes[1].identityId, + delegators[2].address, + ); + + console.log( + ` 🔄 D1 rolling before epoch 5: ${hre.ethers.formatUnits(d1RollingBefore, 18)} TRAC`, + ); + console.log( + ` 🔄 D3 rolling before epoch 5: ${hre.ethers.formatUnits(d3RollingBefore, 18)} TRAC`, + ); + + // Check epoch 5 node scores (should be 0 since no proofs were submitted) + const node1Score5 = await RandomSamplingStorage.getNodeEpochScore( + 5n, + nodes[0].identityId, + ); + const node2Score5 = await RandomSamplingStorage.getNodeEpochScore( + 5n, + nodes[1].identityId, + ); + + console.log(` 📊 Node-1 epoch 5 score: ${node1Score5} (should be 0)`); + console.log(` 📊 Node-2 epoch 5 score: ${node2Score5} (should be 0)`); + + // Verify scores are 0 (no proofs submitted) + expect(node1Score5).to.equal(0n, 'Node-1 should have 0 score in epoch 5'); + expect(node2Score5).to.equal(0n, 'Node-2 should have 0 score in epoch 5'); + + // D1 claims epoch 5 rewards (should succeed but get 0 rewards) + await Staking.connect(delegators[0]).claimDelegatorRewards( + nodes[0].identityId, // Node-1 + 5n, // epoch 5 + delegators[0].address, + ); + + console.log(' ✅ D1 successfully claimed epoch 5 rewards (0 TRAC)'); + + // D3 claims epoch 5 rewards (should succeed but get 0 rewards) + await Staking.connect(delegators[2]).claimDelegatorRewards( + nodes[1].identityId, // Node-2 + 5n, // epoch 5 + delegators[2].address, + ); + + console.log(' ✅ D3 successfully claimed epoch 5 rewards (0 TRAC)'); + + // Get rolling rewards after epoch 5 claims + const d1RollingAfter = await DelegatorsInfo.getDelegatorRollingRewards( + nodes[0].identityId, + delegators[0].address, + ); + const d3RollingAfter = await DelegatorsInfo.getDelegatorRollingRewards( + nodes[1].identityId, + delegators[2].address, + ); + + // Calculate epoch 5 rewards (should be 0) + const d1Epoch5Reward = d1RollingAfter - d1RollingBefore; + const d3Epoch5Reward = d3RollingAfter - d3RollingBefore; + + console.log( + ` 💰 D1 epoch 5 reward: ${hre.ethers.formatUnits(d1Epoch5Reward, 18)} TRAC`, + ); + console.log( + ` 💰 D3 epoch 5 reward: ${hre.ethers.formatUnits(d3Epoch5Reward, 18)} TRAC`, + ); + console.log( + ` 🔄 D1 total rolling after epoch 5: ${hre.ethers.formatUnits(d1RollingAfter, 18)} TRAC`, + ); + console.log( + ` 🔄 D3 total rolling after epoch 5: ${hre.ethers.formatUnits(d3RollingAfter, 18)} TRAC`, + ); + + // Verify rolling rewards didn't change (no rewards from epoch 5) + expect(d1RollingAfter).to.equal( + d1RollingBefore, + 'D1 rolling rewards should not change (no epoch 5 rewards)', + ); + expect(d3RollingAfter).to.equal( + d3RollingBefore, + 'D3 rolling rewards should not change (no epoch 5 rewards)', + ); + + // Verify epoch 5 rewards are 0 + expect(d1Epoch5Reward).to.equal( + 0n, + 'D1 should receive 0 rewards from epoch 5', + ); + expect(d3Epoch5Reward).to.equal( + 0n, + 'D3 should receive 0 rewards from epoch 5', + ); + + // Verify both have same rolling rewards (should be equal after epochs 2+3+4) + expect(d1RollingAfter).to.equal( + d3RollingAfter, + 'D1 and D3 should have equal rolling rewards (equal stakes in all claimed epochs)', + ); + + console.log( + ' ✅ Both delegators successfully claimed epoch 5 with 0 rewards', + ); + console.log(' ✅ Rolling rewards remained unchanged (no new rewards)'); + console.log(' ✅ Both delegators have equal rolling rewards'); + console.log(' 📝 Note: No proofs in epoch 5 = no rewards to distribute'); + }); + + it('D1, D3 attempt to claim epoch 5 rewards again - should revert (already claimed)', async () => { + const { Staking, delegators, nodes } = env; + + console.log( + '\n⛔ TEST 12: D1, D3 attempting to claim epoch 5 again - should revert (already claimed)', + ); + + // D1 attempts to claim epoch 5 again (but already claimed it) + await expect( + Staking.connect(delegators[0]).claimDelegatorRewards( + nodes[0].identityId, // Node-1 + 5n, // epoch 5 + delegators[0].address, + ), + ).to.be.revertedWith('Epoch already claimed'); + + console.log( + ' ✅ D1 claim for epoch 5 reverted as expected (already claimed)', + ); + + // D3 attempts to claim epoch 5 again (but already claimed it) + await expect( + Staking.connect(delegators[2]).claimDelegatorRewards( + nodes[1].identityId, // Node-2 + 5n, // epoch 5 + delegators[2].address, + ), + ).to.be.revertedWith('Epoch already claimed'); + + console.log( + ' ✅ D3 claim for epoch 5 reverted as expected (already claimed)', + ); + console.log( + ' 📝 Note: Cannot claim the same epoch twice - double claiming prevented', + ); + }); + + it('D1, D3 attempt to claim epoch 7 rewards - should revert (epoch not finalized)', async () => { + const { Staking, delegators, nodes } = env; + + console.log( + '\n⛔ TEST 13: D1, D3 attempting to claim epoch 7 - should revert (epoch not finalized)', + ); + + // D1 attempts to claim epoch 7 (but epoch 7 is not finalized yet) + await expect( + Staking.connect(delegators[0]).claimDelegatorRewards( + nodes[0].identityId, // Node-1 + 7n, // epoch 7 + delegators[0].address, + ), + ).to.be.revertedWith('Epoch not finalised'); + + console.log( + ' ✅ D1 claim for epoch 7 reverted as expected (epoch not finalized)', + ); + + // D3 attempts to claim epoch 7 (but epoch 7 is not finalized yet) + await expect( + Staking.connect(delegators[2]).claimDelegatorRewards( + nodes[1].identityId, // Node-2 + 7n, // epoch 7 + delegators[2].address, + ), + ).to.be.revertedWith('Epoch not finalised'); + + console.log( + ' ✅ D3 claim for epoch 7 reverted as expected (epoch not finalized)', + ); + console.log(' 📝 Note: Cannot claim rewards for non-finalized epochs'); + }); + + it('D1, D3 claim epoch 6 rewards - should succeed with 0 rewards (no proofs submitted)', async () => { + const { + Staking, + DelegatorsInfo, + RandomSamplingStorage, + delegators, + nodes, + } = env; + + console.log( + '\n✅ TEST 14: D1, D3 claiming epoch 6 rewards - should get 0 rewards (no proofs)', + ); + + // Get rolling rewards before epoch 6 claims (should have epoch 2+3+4+5 rewards) + const d1RollingBefore = await DelegatorsInfo.getDelegatorRollingRewards( + nodes[0].identityId, + delegators[0].address, + ); + const d3RollingBefore = await DelegatorsInfo.getDelegatorRollingRewards( + nodes[1].identityId, + delegators[2].address, + ); + + console.log( + ` 🔄 D1 rolling before epoch 6: ${hre.ethers.formatUnits(d1RollingBefore, 18)} TRAC`, + ); + console.log( + ` 🔄 D3 rolling before epoch 6: ${hre.ethers.formatUnits(d3RollingBefore, 18)} TRAC`, + ); + + // Check epoch 6 node scores (should be 0 since no proofs were submitted) + const node1Score6 = await RandomSamplingStorage.getNodeEpochScore( + 6n, + nodes[0].identityId, + ); + const node2Score6 = await RandomSamplingStorage.getNodeEpochScore( + 6n, + nodes[1].identityId, + ); + + console.log(` 📊 Node-1 epoch 6 score: ${node1Score6} (should be 0)`); + console.log(` 📊 Node-2 epoch 6 score: ${node2Score6} (should be 0)`); + + // Verify scores are 0 (no proofs submitted) + expect(node1Score6).to.equal(0n, 'Node-1 should have 0 score in epoch 6'); + expect(node2Score6).to.equal(0n, 'Node-2 should have 0 score in epoch 6'); + + // D1 claims epoch 6 rewards (should succeed but get 0 rewards) + await Staking.connect(delegators[0]).claimDelegatorRewards( + nodes[0].identityId, // Node-1 + 6n, // epoch 6 + delegators[0].address, + ); + + console.log(' ✅ D1 successfully claimed epoch 6 rewards (0 TRAC)'); + + // D3 claims epoch 6 rewards (should succeed but get 0 rewards) + await Staking.connect(delegators[2]).claimDelegatorRewards( + nodes[1].identityId, // Node-2 + 6n, // epoch 6 + delegators[2].address, + ); + + console.log(' ✅ D3 successfully claimed epoch 6 rewards (0 TRAC)'); + + // Get rolling rewards after epoch 6 claims + const d1RollingAfter = await DelegatorsInfo.getDelegatorRollingRewards( + nodes[0].identityId, + delegators[0].address, + ); + const d3RollingAfter = await DelegatorsInfo.getDelegatorRollingRewards( + nodes[1].identityId, + delegators[2].address, + ); + + // Read actual values from contracts after claiming + const d1RollingTransferred = d1RollingBefore - d1RollingAfter; // How much was transferred + const d3RollingTransferred = d3RollingBefore - d3RollingAfter; // How much was transferred + + console.log(` 💰 D1 epoch 6 reward: 0.0 TRAC (no proofs submitted)`); + console.log(` 💰 D3 epoch 6 reward: 0.0 TRAC (no proofs submitted)`); + console.log( + ` 🔄 D1 rolling transferred: ${hre.ethers.formatUnits(d1RollingTransferred, 18)} TRAC → stakeBase`, + ); + console.log( + ` 🔄 D3 rolling transferred: ${hre.ethers.formatUnits(d3RollingTransferred, 18)} TRAC → stakeBase`, + ); + console.log( + ` 🔄 D1 total rolling after epoch 6: ${hre.ethers.formatUnits(d1RollingAfter, 18)} TRAC`, + ); + console.log( + ` 🔄 D3 total rolling after epoch 6: ${hre.ethers.formatUnits(d3RollingAfter, 18)} TRAC`, + ); + + // Get stakeBase after epoch 6 claims to check if rolling rewards were transferred + const d1StakeBaseAfter = await env.StakingStorage.getDelegatorStakeBase( + nodes[0].identityId, + hre.ethers.keccak256( + hre.ethers.solidityPacked(['address'], [delegators[0].address]), + ), + ); + const d3StakeBaseAfter = await env.StakingStorage.getDelegatorStakeBase( + nodes[1].identityId, + hre.ethers.keccak256( + hre.ethers.solidityPacked(['address'], [delegators[2].address]), + ), + ); + + console.log( + ` 💎 D1 stakeBase after epoch 6: ${hre.ethers.formatUnits(d1StakeBaseAfter, 18)} TRAC`, + ); + console.log( + ` 💎 D3 stakeBase after epoch 6: ${hre.ethers.formatUnits(d3StakeBaseAfter, 18)} TRAC`, + ); + + // Verify epoch 6 behavior - no new rewards, but rolling rewards transferred + // Since no proofs were submitted in epoch 6, no new rewards should be generated + // But rolling rewards should be transferred to stakeBase since this is the last claimable epoch + + // Since epoch 6 is the last claimable epoch (epoch 7 is current and not finalized), + // rolling rewards should have been transferred to stakeBase + expect(d1RollingAfter).to.equal( + 0n, + 'D1 rolling rewards should be 0 (transferred to stakeBase as last epoch)', + ); + expect(d3RollingAfter).to.equal( + 0n, + 'D3 rolling rewards should be 0 (transferred to stakeBase as last epoch)', + ); + + // Verify that rolling rewards were properly transferred to stakeBase + // Both delegators should have equal stakeBase (since they had equal stakes and equal rewards) + expect(d1StakeBaseAfter).to.equal( + d3StakeBaseAfter, + 'D1 and D3 should have equal stakeBase after claiming all epochs', + ); + + // Verify that stakeBase increased by the amount of rolling rewards that were transferred + expect(d1StakeBaseAfter).to.be.gt( + toTRAC(10_000), + 'D1 stakeBase should be greater than original 10k stake (includes transferred rewards)', + ); + expect(d3StakeBaseAfter).to.be.gt( + toTRAC(10_000), + 'D3 stakeBase should be greater than original 10k stake (includes transferred rewards)', + ); + + console.log( + ' ✅ Both delegators successfully claimed epoch 6 with 0 rewards', + ); + console.log( + ' ✅ Rolling rewards transferred to stakeBase (last claimable epoch)', + ); + console.log(' ✅ Both delegators have equal final stakeBase'); + console.log( + ' 📝 Note: Last epoch claim transfers rolling rewards to stakeBase', + ); + }); + + it('D1, D3 attempt to claim epoch 7 rewards again - should revert (epoch not finalized)', async () => { + const { Staking, delegators, nodes, Chronos, EpochStorage } = env; + + console.log( + '\n⛔ TEST 15: D1, D3 attempting to claim epoch 7 - should revert (epoch not finalized)', + ); + + // Verify current state + const currentEpoch = await Chronos.getCurrentEpoch(); + const lastFinalizedEpoch = await EpochStorage.lastFinalizedEpoch(1); + + console.log(` ℹ️ Current epoch: ${currentEpoch}`); + console.log(` ℹ️ Last finalized epoch: ${lastFinalizedEpoch}`); + + // Verify epoch 7 is current and not finalized + expect(currentEpoch).to.equal(7n, 'Current epoch should be 7'); + expect(lastFinalizedEpoch).to.be.lt( + 7n, + 'Epoch 7 should not be finalized yet', + ); + + // D1 attempts to claim epoch 7 (but epoch 7 is current and not finalized) + await expect( + Staking.connect(delegators[0]).claimDelegatorRewards( + nodes[0].identityId, // Node-1 + 7n, // epoch 7 + delegators[0].address, + ), + ).to.be.revertedWith('Epoch not finalised'); + + console.log( + ' ✅ D1 claim for epoch 7 reverted as expected (epoch not finalized)', + ); + + // D3 attempts to claim epoch 7 (but epoch 7 is current and not finalized) + await expect( + Staking.connect(delegators[2]).claimDelegatorRewards( + nodes[1].identityId, // Node-2 + 7n, // epoch 7 + delegators[2].address, + ), + ).to.be.revertedWith('Epoch not finalised'); + + console.log( + ' ✅ D3 claim for epoch 7 reverted as expected (epoch not finalized)', + ); + console.log( + ' 📝 Note: Cannot claim rewards for current/non-finalized epochs', + ); + console.log( + ' 📝 Note: Epoch must be finalized before rewards can be claimed', + ); + }); +}); + +describe('Proportional rewards tests - Double stake = Double rewards', () => { + /* fixture state visible to all tests in this describe-block */ + let env: Awaited>; + + before(async () => { + env = await buildInitialRewardsState(); + }); + + it('D1, D2, D3, D4 claim epoch 2 rewards - D2 and D4 should get double rewards (double stakes)', async () => { + const { + Staking, + DelegatorsInfo, + RandomSamplingStorage, + delegators, + nodes, + } = env; + + console.log( + '\n✅ PROPORTIONAL TEST 1: Epoch 2 rewards - Double stake = Double rewards', + ); + + // Verify stakes first + const d1Key = hre.ethers.keccak256( + hre.ethers.solidityPacked(['address'], [delegators[0].address]), + ); + const d2Key = hre.ethers.keccak256( + hre.ethers.solidityPacked(['address'], [delegators[1].address]), + ); + const d3Key = hre.ethers.keccak256( + hre.ethers.solidityPacked(['address'], [delegators[2].address]), + ); + const d4Key = hre.ethers.keccak256( + hre.ethers.solidityPacked(['address'], [delegators[3].address]), + ); + + const d1Stake = await env.StakingStorage.getDelegatorStakeBase( + nodes[0].identityId, + d1Key, + ); + const d2Stake = await env.StakingStorage.getDelegatorStakeBase( + nodes[0].identityId, + d2Key, + ); + const d3Stake = await env.StakingStorage.getDelegatorStakeBase( + nodes[1].identityId, + d3Key, + ); + const d4Stake = await env.StakingStorage.getDelegatorStakeBase( + nodes[1].identityId, + d4Key, + ); + + console.log( + ` 💰 D1 stake: ${hre.ethers.formatUnits(d1Stake, 18)} TRAC (Node-1)`, + ); + console.log( + ` 💰 D2 stake: ${hre.ethers.formatUnits(d2Stake, 18)} TRAC (Node-1)`, + ); + console.log( + ` 💰 D3 stake: ${hre.ethers.formatUnits(d3Stake, 18)} TRAC (Node-2)`, + ); + console.log( + ` 💰 D4 stake: ${hre.ethers.formatUnits(d4Stake, 18)} TRAC (Node-2)`, + ); + + // Verify stake ratios + expect(d2Stake).to.equal(d1Stake * 2n, 'D2 should have double D1 stake'); + expect(d4Stake).to.equal(d3Stake * 2n, 'D4 should have double D3 stake'); + expect(d1Stake).to.equal(d3Stake, 'D1 and D3 should have equal stakes'); + expect(d2Stake).to.equal(d4Stake, 'D2 and D4 should have equal stakes'); + + // Verify nodes have equal scores + const node1Score = await RandomSamplingStorage.getNodeEpochScore( + 2n, + nodes[0].identityId, + ); + const node2Score = await RandomSamplingStorage.getNodeEpochScore( + 2n, + nodes[1].identityId, + ); + expect(node1Score).to.equal(node2Score, 'Nodes should have equal scores'); + console.log(` 📊 Both nodes have equal score: ${node1Score}`); + + // Get rolling rewards before claiming + const d1RollingBefore = await DelegatorsInfo.getDelegatorRollingRewards( + nodes[0].identityId, + delegators[0].address, + ); + const d2RollingBefore = await DelegatorsInfo.getDelegatorRollingRewards( + nodes[0].identityId, + delegators[1].address, + ); + const d3RollingBefore = await DelegatorsInfo.getDelegatorRollingRewards( + nodes[1].identityId, + delegators[2].address, + ); + const d4RollingBefore = await DelegatorsInfo.getDelegatorRollingRewards( + nodes[1].identityId, + delegators[3].address, + ); + + // All should start with 0 rolling rewards + expect(d1RollingBefore).to.equal( + 0n, + 'D1 should start with 0 rolling rewards', + ); + expect(d2RollingBefore).to.equal( + 0n, + 'D2 should start with 0 rolling rewards', + ); + expect(d3RollingBefore).to.equal( + 0n, + 'D3 should start with 0 rolling rewards', + ); + expect(d4RollingBefore).to.equal( + 0n, + 'D4 should start with 0 rolling rewards', + ); + + // Claim epoch 2 rewards for all delegators + await Staking.connect(delegators[0]).claimDelegatorRewards( + nodes[0].identityId, + 2n, + delegators[0].address, + ); + await Staking.connect(delegators[1]).claimDelegatorRewards( + nodes[0].identityId, + 2n, + delegators[1].address, + ); + await Staking.connect(delegators[2]).claimDelegatorRewards( + nodes[1].identityId, + 2n, + delegators[2].address, + ); + await Staking.connect(delegators[3]).claimDelegatorRewards( + nodes[1].identityId, + 2n, + delegators[3].address, + ); + + console.log(' ✅ All delegators successfully claimed epoch 2 rewards'); + + // Get rolling rewards after claiming + const d1RollingAfter = await DelegatorsInfo.getDelegatorRollingRewards( + nodes[0].identityId, + delegators[0].address, + ); + const d2RollingAfter = await DelegatorsInfo.getDelegatorRollingRewards( + nodes[0].identityId, + delegators[1].address, + ); + const d3RollingAfter = await DelegatorsInfo.getDelegatorRollingRewards( + nodes[1].identityId, + delegators[2].address, + ); + const d4RollingAfter = await DelegatorsInfo.getDelegatorRollingRewards( + nodes[1].identityId, + delegators[3].address, + ); + + // Calculate epoch 2 rewards + const d1Reward = d1RollingAfter - d1RollingBefore; + const d2Reward = d2RollingAfter - d2RollingBefore; + const d3Reward = d3RollingAfter - d3RollingBefore; + const d4Reward = d4RollingAfter - d4RollingBefore; + + console.log( + ` 💰 D1 epoch 2 reward: ${hre.ethers.formatUnits(d1Reward, 18)} TRAC`, + ); + console.log( + ` 💰 D2 epoch 2 reward: ${hre.ethers.formatUnits(d2Reward, 18)} TRAC`, + ); + console.log( + ` 💰 D3 epoch 2 reward: ${hre.ethers.formatUnits(d3Reward, 18)} TRAC`, + ); + console.log( + ` 💰 D4 epoch 2 reward: ${hre.ethers.formatUnits(d4Reward, 18)} TRAC`, + ); + + // Verify proportional rewards (allow small rounding differences) + const d2ToD1Ratio = Number(d2Reward) / Number(d1Reward); + const d4ToD3Ratio = Number(d4Reward) / Number(d3Reward); + + expect(d2ToD1Ratio).to.be.closeTo( + 2.0, + 0.001, + 'D2 should get approximately double D1 rewards', + ); + expect(d4ToD3Ratio).to.be.closeTo( + 2.0, + 0.001, + 'D4 should get approximately double D3 rewards', + ); + expect(d1Reward).to.equal( + d3Reward, + 'D1 and D3 should get equal rewards (equal stakes)', + ); + expect(d2Reward).to.equal( + d4Reward, + 'D2 and D4 should get equal rewards (equal stakes)', + ); + + // All rewards should be positive + expect(d1Reward).to.be.gt(0n, 'D1 should get positive rewards'); + expect(d2Reward).to.be.gt(0n, 'D2 should get positive rewards'); + expect(d3Reward).to.be.gt(0n, 'D3 should get positive rewards'); + expect(d4Reward).to.be.gt(0n, 'D4 should get positive rewards'); + + console.log(' ✅ PROPORTIONAL REWARDS VERIFIED:'); + console.log( + ` 📈 D2 reward / D1 reward = ${Number(d2Reward) / Number(d1Reward)} (should be 2.0)`, + ); + console.log( + ` 📈 D4 reward / D3 reward = ${Number(d4Reward) / Number(d3Reward)} (should be 2.0)`, + ); + console.log( + ' 📝 Note: Double stake = Double rewards confirmed for epoch 2', + ); + }); + + it('D1, D2, D3, D4 claim epoch 3 rewards - D2 and D4 should get proportionally more rewards', async () => { + const { + Staking, + DelegatorsInfo, + RandomSamplingStorage, + delegators, + nodes, + } = env; + + console.log( + '\n✅ PROPORTIONAL TEST 2: Epoch 3 rewards - Proportional to stakes', + ); + + // Get rolling rewards before epoch 3 claims + const d1RollingBefore = await DelegatorsInfo.getDelegatorRollingRewards( + nodes[0].identityId, + delegators[0].address, + ); + const d2RollingBefore = await DelegatorsInfo.getDelegatorRollingRewards( + nodes[0].identityId, + delegators[1].address, + ); + const d3RollingBefore = await DelegatorsInfo.getDelegatorRollingRewards( + nodes[1].identityId, + delegators[2].address, + ); + const d4RollingBefore = await DelegatorsInfo.getDelegatorRollingRewards( + nodes[1].identityId, + delegators[3].address, + ); + + console.log( + ` 🔄 D1 rolling before epoch 3: ${hre.ethers.formatUnits(d1RollingBefore, 18)} TRAC`, + ); + console.log( + ` 🔄 D2 rolling before epoch 3: ${hre.ethers.formatUnits(d2RollingBefore, 18)} TRAC`, + ); + console.log( + ` 🔄 D3 rolling before epoch 3: ${hre.ethers.formatUnits(d3RollingBefore, 18)} TRAC`, + ); + console.log( + ` 🔄 D4 rolling before epoch 3: ${hre.ethers.formatUnits(d4RollingBefore, 18)} TRAC`, + ); + + // Verify epoch 3 node scores + const node1Score3 = await RandomSamplingStorage.getNodeEpochScore( + 3n, + nodes[0].identityId, + ); + const node2Score3 = await RandomSamplingStorage.getNodeEpochScore( + 3n, + nodes[1].identityId, + ); + console.log(` 📊 Node-1 epoch 3 score: ${node1Score3}`); + console.log(` 📊 Node-2 epoch 3 score: ${node2Score3}`); + + // Claim epoch 3 rewards for all delegators + await Staking.connect(delegators[0]).claimDelegatorRewards( + nodes[0].identityId, + 3n, + delegators[0].address, + ); + await Staking.connect(delegators[1]).claimDelegatorRewards( + nodes[0].identityId, + 3n, + delegators[1].address, + ); + await Staking.connect(delegators[2]).claimDelegatorRewards( + nodes[1].identityId, + 3n, + delegators[2].address, + ); + await Staking.connect(delegators[3]).claimDelegatorRewards( + nodes[1].identityId, + 3n, + delegators[3].address, + ); + + console.log(' ✅ All delegators successfully claimed epoch 3 rewards'); + + // Get rolling rewards after epoch 3 claims + const d1RollingAfter = await DelegatorsInfo.getDelegatorRollingRewards( + nodes[0].identityId, + delegators[0].address, + ); + const d2RollingAfter = await DelegatorsInfo.getDelegatorRollingRewards( + nodes[0].identityId, + delegators[1].address, + ); + const d3RollingAfter = await DelegatorsInfo.getDelegatorRollingRewards( + nodes[1].identityId, + delegators[2].address, + ); + const d4RollingAfter = await DelegatorsInfo.getDelegatorRollingRewards( + nodes[1].identityId, + delegators[3].address, + ); + + // Calculate epoch 3 rewards + const d1Epoch3Reward = d1RollingAfter - d1RollingBefore; + const d2Epoch3Reward = d2RollingAfter - d2RollingBefore; + const d3Epoch3Reward = d3RollingAfter - d3RollingBefore; + const d4Epoch3Reward = d4RollingAfter - d4RollingBefore; + + console.log( + ` 💰 D1 epoch 3 reward: ${hre.ethers.formatUnits(d1Epoch3Reward, 18)} TRAC`, + ); + console.log( + ` 💰 D2 epoch 3 reward: ${hre.ethers.formatUnits(d2Epoch3Reward, 18)} TRAC`, + ); + console.log( + ` 💰 D3 epoch 3 reward: ${hre.ethers.formatUnits(d3Epoch3Reward, 18)} TRAC`, + ); + console.log( + ` 💰 D4 epoch 3 reward: ${hre.ethers.formatUnits(d4Epoch3Reward, 18)} TRAC`, + ); + + // Verify proportional rewards (allow small rounding differences) + const d2ToD1Epoch3Ratio = Number(d2Epoch3Reward) / Number(d1Epoch3Reward); + const d4ToD3Epoch3Ratio = Number(d4Epoch3Reward) / Number(d3Epoch3Reward); + + expect(d2ToD1Epoch3Ratio).to.be.closeTo( + 2.0, + 0.001, + 'D2 should get approximately double D1 epoch 3 rewards', + ); + expect(d4ToD3Epoch3Ratio).to.be.closeTo( + 2.0, + 0.001, + 'D4 should get approximately double D3 epoch 3 rewards', + ); + expect(d1Epoch3Reward).to.equal( + d3Epoch3Reward, + 'D1 and D3 should get equal epoch 3 rewards', + ); + expect(d2Epoch3Reward).to.equal( + d4Epoch3Reward, + 'D2 and D4 should get equal epoch 3 rewards', + ); + + // All rewards should be positive + expect(d1Epoch3Reward).to.be.gt( + 0n, + 'D1 should get positive epoch 3 rewards', + ); + expect(d2Epoch3Reward).to.be.gt( + 0n, + 'D2 should get positive epoch 3 rewards', + ); + expect(d3Epoch3Reward).to.be.gt( + 0n, + 'D3 should get positive epoch 3 rewards', + ); + expect(d4Epoch3Reward).to.be.gt( + 0n, + 'D4 should get positive epoch 3 rewards', + ); + + // Verify total rolling rewards also maintain proportionality (allow small rounding differences) + const d2ToD1TotalRatio = Number(d2RollingAfter) / Number(d1RollingAfter); + const d4ToD3TotalRatio = Number(d4RollingAfter) / Number(d3RollingAfter); + + expect(d2ToD1TotalRatio).to.be.closeTo( + 2.0, + 0.001, + 'D2 total rolling should be approximately double D1 total rolling', + ); + expect(d4ToD3TotalRatio).to.be.closeTo( + 2.0, + 0.001, + 'D4 total rolling should be approximately double D3 total rolling', + ); + + console.log(' ✅ PROPORTIONAL REWARDS VERIFIED FOR EPOCH 3:'); + console.log( + ` 📈 D2 epoch 3 reward / D1 epoch 3 reward = ${Number(d2Epoch3Reward) / Number(d1Epoch3Reward)} (should be 2.0)`, + ); + console.log( + ` 📈 D4 epoch 3 reward / D3 epoch 3 reward = ${Number(d4Epoch3Reward) / Number(d3Epoch3Reward)} (should be 2.0)`, + ); + console.log( + ` 🔄 D2 total rolling / D1 total rolling = ${Number(d2RollingAfter) / Number(d1RollingAfter)} (should be 2.0)`, + ); + console.log( + ' 📝 Note: Proportional rewards maintained across multiple epochs', + ); + }); + + it('D1, D2, D3, D4 claim epoch 4 rewards - Proportional rewards continue', async () => { + const { Staking, DelegatorsInfo, delegators, nodes } = env; + + console.log( + '\n✅ PROPORTIONAL TEST 3: Epoch 4 rewards - Proportional rewards continue', + ); + + // Get rolling rewards before epoch 4 claims + const d1RollingBefore = await DelegatorsInfo.getDelegatorRollingRewards( + nodes[0].identityId, + delegators[0].address, + ); + const d2RollingBefore = await DelegatorsInfo.getDelegatorRollingRewards( + nodes[0].identityId, + delegators[1].address, + ); + const d3RollingBefore = await DelegatorsInfo.getDelegatorRollingRewards( + nodes[1].identityId, + delegators[2].address, + ); + const d4RollingBefore = await DelegatorsInfo.getDelegatorRollingRewards( + nodes[1].identityId, + delegators[3].address, + ); + + // Claim epoch 4 rewards for all delegators + await Staking.connect(delegators[0]).claimDelegatorRewards( + nodes[0].identityId, + 4n, + delegators[0].address, + ); + await Staking.connect(delegators[1]).claimDelegatorRewards( + nodes[0].identityId, + 4n, + delegators[1].address, + ); + await Staking.connect(delegators[2]).claimDelegatorRewards( + nodes[1].identityId, + 4n, + delegators[2].address, + ); + await Staking.connect(delegators[3]).claimDelegatorRewards( + nodes[1].identityId, + 4n, + delegators[3].address, + ); + + console.log(' ✅ All delegators successfully claimed epoch 4 rewards'); + + // Get rolling rewards after epoch 4 claims + const d1RollingAfter = await DelegatorsInfo.getDelegatorRollingRewards( + nodes[0].identityId, + delegators[0].address, + ); + const d2RollingAfter = await DelegatorsInfo.getDelegatorRollingRewards( + nodes[0].identityId, + delegators[1].address, + ); + const d3RollingAfter = await DelegatorsInfo.getDelegatorRollingRewards( + nodes[1].identityId, + delegators[2].address, + ); + const d4RollingAfter = await DelegatorsInfo.getDelegatorRollingRewards( + nodes[1].identityId, + delegators[3].address, + ); + + // Calculate epoch 4 rewards + const d1Epoch4Reward = d1RollingAfter - d1RollingBefore; + const d2Epoch4Reward = d2RollingAfter - d2RollingBefore; + const d3Epoch4Reward = d3RollingAfter - d3RollingBefore; + const d4Epoch4Reward = d4RollingAfter - d4RollingBefore; + + console.log( + ` 💰 D1 epoch 4 reward: ${hre.ethers.formatUnits(d1Epoch4Reward, 18)} TRAC`, + ); + console.log( + ` 💰 D2 epoch 4 reward: ${hre.ethers.formatUnits(d2Epoch4Reward, 18)} TRAC`, + ); + console.log( + ` 💰 D3 epoch 4 reward: ${hre.ethers.formatUnits(d3Epoch4Reward, 18)} TRAC`, + ); + console.log( + ` 💰 D4 epoch 4 reward: ${hre.ethers.formatUnits(d4Epoch4Reward, 18)} TRAC`, + ); + + // Verify proportional rewards continue (allow small rounding differences) + const d2ToD1Epoch4Ratio = Number(d2Epoch4Reward) / Number(d1Epoch4Reward); + const d4ToD3Epoch4Ratio = Number(d4Epoch4Reward) / Number(d3Epoch4Reward); + + expect(d2ToD1Epoch4Ratio).to.be.closeTo( + 2.0, + 0.001, + 'D2 should get approximately double D1 epoch 4 rewards', + ); + expect(d4ToD3Epoch4Ratio).to.be.closeTo( + 2.0, + 0.001, + 'D4 should get approximately double D3 epoch 4 rewards', + ); + expect(d1Epoch4Reward).to.equal( + d3Epoch4Reward, + 'D1 and D3 should get equal epoch 4 rewards', + ); + expect(d2Epoch4Reward).to.equal( + d4Epoch4Reward, + 'D2 and D4 should get equal epoch 4 rewards', + ); + + // Verify total rolling rewards maintain proportionality (allow small rounding differences) + const d2ToD1TotalRatio4 = Number(d2RollingAfter) / Number(d1RollingAfter); + const d4ToD3TotalRatio4 = Number(d4RollingAfter) / Number(d3RollingAfter); + + expect(d2ToD1TotalRatio4).to.be.closeTo( + 2.0, + 0.001, + 'D2 total rolling should be approximately double D1 total rolling', + ); + expect(d4ToD3TotalRatio4).to.be.closeTo( + 2.0, + 0.001, + 'D4 total rolling should be approximately double D3 total rolling', + ); + + console.log(' ✅ PROPORTIONAL REWARDS VERIFIED FOR EPOCH 4'); + console.log( + ' 📝 Note: Proportional rewards consistently maintained across epochs 2, 3, and 4', + ); + }); + + it('D1, D2, D3, D4 claim epoch 5 rewards - Should get 0 rewards (no proofs) but maintain proportionality', async () => { + const { Staking, DelegatorsInfo, delegators, nodes } = env; + + console.log( + '\n✅ PROPORTIONAL TEST 4: Epoch 5 rewards - 0 rewards but proportionality maintained', + ); + + // Get rolling rewards before epoch 5 claims + const d1RollingBefore = await DelegatorsInfo.getDelegatorRollingRewards( + nodes[0].identityId, + delegators[0].address, + ); + const d2RollingBefore = await DelegatorsInfo.getDelegatorRollingRewards( + nodes[0].identityId, + delegators[1].address, + ); + const d3RollingBefore = await DelegatorsInfo.getDelegatorRollingRewards( + nodes[1].identityId, + delegators[2].address, + ); + const d4RollingBefore = await DelegatorsInfo.getDelegatorRollingRewards( + nodes[1].identityId, + delegators[3].address, + ); + + // Verify proportional rolling rewards before epoch 5 (allow small rounding differences) + const d2ToD1BeforeRatio = Number(d2RollingBefore) / Number(d1RollingBefore); + const d4ToD3BeforeRatio = Number(d4RollingBefore) / Number(d3RollingBefore); + + expect(d2ToD1BeforeRatio).to.be.closeTo( + 2.0, + 0.001, + 'D2 should have approximately double D1 rolling rewards before epoch 5', + ); + expect(d4ToD3BeforeRatio).to.be.closeTo( + 2.0, + 0.001, + 'D4 should have approximately double D3 rolling rewards before epoch 5', + ); + + // Claim epoch 5 rewards for all delegators (should be 0) + await Staking.connect(delegators[0]).claimDelegatorRewards( + nodes[0].identityId, + 5n, + delegators[0].address, + ); + await Staking.connect(delegators[1]).claimDelegatorRewards( + nodes[0].identityId, + 5n, + delegators[1].address, + ); + await Staking.connect(delegators[2]).claimDelegatorRewards( + nodes[1].identityId, + 5n, + delegators[2].address, + ); + await Staking.connect(delegators[3]).claimDelegatorRewards( + nodes[1].identityId, + 5n, + delegators[3].address, + ); + + console.log( + ' ✅ All delegators successfully claimed epoch 5 rewards (0 TRAC each)', + ); + + // Get rolling rewards after epoch 5 claims + const d1RollingAfter = await DelegatorsInfo.getDelegatorRollingRewards( + nodes[0].identityId, + delegators[0].address, + ); + const d2RollingAfter = await DelegatorsInfo.getDelegatorRollingRewards( + nodes[0].identityId, + delegators[1].address, + ); + const d3RollingAfter = await DelegatorsInfo.getDelegatorRollingRewards( + nodes[1].identityId, + delegators[2].address, + ); + const d4RollingAfter = await DelegatorsInfo.getDelegatorRollingRewards( + nodes[1].identityId, + delegators[3].address, + ); + + // Verify no change in rolling rewards (no rewards from epoch 5) + expect(d1RollingAfter).to.equal( + d1RollingBefore, + 'D1 rolling rewards should not change', + ); + expect(d2RollingAfter).to.equal( + d2RollingBefore, + 'D2 rolling rewards should not change', + ); + expect(d3RollingAfter).to.equal( + d3RollingBefore, + 'D3 rolling rewards should not change', + ); + expect(d4RollingAfter).to.equal( + d4RollingBefore, + 'D4 rolling rewards should not change', + ); + + // Verify proportionality is still maintained (allow small rounding differences) + const d2ToD1AfterRatio = Number(d2RollingAfter) / Number(d1RollingAfter); + const d4ToD3AfterRatio = Number(d4RollingAfter) / Number(d3RollingAfter); + + expect(d2ToD1AfterRatio).to.be.closeTo( + 2.0, + 0.001, + 'D2 should still have approximately double D1 rolling rewards', + ); + expect(d4ToD3AfterRatio).to.be.closeTo( + 2.0, + 0.001, + 'D4 should still have approximately double D3 rolling rewards', + ); + + console.log( + ` 💰 All delegators got 0 TRAC from epoch 5 (no proofs submitted)`, + ); + console.log( + ` 🔄 D1 total rolling: ${hre.ethers.formatUnits(d1RollingAfter, 18)} TRAC`, + ); + console.log( + ` 🔄 D2 total rolling: ${hre.ethers.formatUnits(d2RollingAfter, 18)} TRAC`, + ); + console.log( + ` 🔄 D3 total rolling: ${hre.ethers.formatUnits(d3RollingAfter, 18)} TRAC`, + ); + console.log( + ` 🔄 D4 total rolling: ${hre.ethers.formatUnits(d4RollingAfter, 18)} TRAC`, + ); + console.log(' ✅ PROPORTIONALITY MAINTAINED: D2/D1 = D4/D3 = 2.0'); + console.log( + " 📝 Note: Zero rewards don't break proportional relationships", + ); + }); + + it('D1, D2, D3, D4 claim epoch 6 rewards - Final claim transfers rolling rewards to stakeBase proportionally', async () => { + const { Staking, StakingStorage, DelegatorsInfo, delegators, nodes } = env; + + console.log( + '\n✅ PROPORTIONAL TEST 5: Epoch 6 final claim - Proportional transfer to stakeBase', + ); + + // Get states before epoch 6 claims + const d1Key = hre.ethers.keccak256( + hre.ethers.solidityPacked(['address'], [delegators[0].address]), + ); + const d2Key = hre.ethers.keccak256( + hre.ethers.solidityPacked(['address'], [delegators[1].address]), + ); + const d3Key = hre.ethers.keccak256( + hre.ethers.solidityPacked(['address'], [delegators[2].address]), + ); + const d4Key = hre.ethers.keccak256( + hre.ethers.solidityPacked(['address'], [delegators[3].address]), + ); + + const d1StakeBaseBefore = await StakingStorage.getDelegatorStakeBase( + nodes[0].identityId, + d1Key, + ); + const d2StakeBaseBefore = await StakingStorage.getDelegatorStakeBase( + nodes[0].identityId, + d2Key, + ); + const d3StakeBaseBefore = await StakingStorage.getDelegatorStakeBase( + nodes[1].identityId, + d3Key, + ); + const d4StakeBaseBefore = await StakingStorage.getDelegatorStakeBase( + nodes[1].identityId, + d4Key, + ); + + const d1RollingBefore = await DelegatorsInfo.getDelegatorRollingRewards( + nodes[0].identityId, + delegators[0].address, + ); + const d2RollingBefore = await DelegatorsInfo.getDelegatorRollingRewards( + nodes[0].identityId, + delegators[1].address, + ); + const d3RollingBefore = await DelegatorsInfo.getDelegatorRollingRewards( + nodes[1].identityId, + delegators[2].address, + ); + const d4RollingBefore = await DelegatorsInfo.getDelegatorRollingRewards( + nodes[1].identityId, + delegators[3].address, + ); + + console.log( + ` 💎 D1 stakeBase before: ${hre.ethers.formatUnits(d1StakeBaseBefore, 18)} TRAC`, + ); + console.log( + ` 💎 D2 stakeBase before: ${hre.ethers.formatUnits(d2StakeBaseBefore, 18)} TRAC`, + ); + console.log( + ` 💎 D3 stakeBase before: ${hre.ethers.formatUnits(d3StakeBaseBefore, 18)} TRAC`, + ); + console.log( + ` 💎 D4 stakeBase before: ${hre.ethers.formatUnits(d4StakeBaseBefore, 18)} TRAC`, + ); + console.log( + ` 🔄 D1 rolling before: ${hre.ethers.formatUnits(d1RollingBefore, 18)} TRAC`, + ); + console.log( + ` 🔄 D2 rolling before: ${hre.ethers.formatUnits(d2RollingBefore, 18)} TRAC`, + ); + console.log( + ` 🔄 D3 rolling before: ${hre.ethers.formatUnits(d3RollingBefore, 18)} TRAC`, + ); + console.log( + ` 🔄 D4 rolling before: ${hre.ethers.formatUnits(d4RollingBefore, 18)} TRAC`, + ); + + // Verify proportional rolling rewards before final claim (allow small rounding differences) + const d2ToD1BeforeFinalRatio = + Number(d2RollingBefore) / Number(d1RollingBefore); + const d4ToD3BeforeFinalRatio = + Number(d4RollingBefore) / Number(d3RollingBefore); + + expect(d2ToD1BeforeFinalRatio).to.be.closeTo( + 2.0, + 0.001, + 'D2 should have approximately double D1 rolling rewards', + ); + expect(d4ToD3BeforeFinalRatio).to.be.closeTo( + 2.0, + 0.001, + 'D4 should have approximately double D3 rolling rewards', + ); + + // Claim epoch 6 rewards for all delegators (final claim - should transfer to stakeBase) + await Staking.connect(delegators[0]).claimDelegatorRewards( + nodes[0].identityId, + 6n, + delegators[0].address, + ); + await Staking.connect(delegators[1]).claimDelegatorRewards( + nodes[0].identityId, + 6n, + delegators[1].address, + ); + await Staking.connect(delegators[2]).claimDelegatorRewards( + nodes[1].identityId, + 6n, + delegators[2].address, + ); + await Staking.connect(delegators[3]).claimDelegatorRewards( + nodes[1].identityId, + 6n, + delegators[3].address, + ); + + console.log( + ' ✅ All delegators successfully claimed epoch 6 rewards (final claim)', + ); + + // Get states after epoch 6 claims + const d1StakeBaseAfter = await StakingStorage.getDelegatorStakeBase( + nodes[0].identityId, + d1Key, + ); + const d2StakeBaseAfter = await StakingStorage.getDelegatorStakeBase( + nodes[0].identityId, + d2Key, + ); + const d3StakeBaseAfter = await StakingStorage.getDelegatorStakeBase( + nodes[1].identityId, + d3Key, + ); + const d4StakeBaseAfter = await StakingStorage.getDelegatorStakeBase( + nodes[1].identityId, + d4Key, + ); + + const d1RollingAfter = await DelegatorsInfo.getDelegatorRollingRewards( + nodes[0].identityId, + delegators[0].address, + ); + const d2RollingAfter = await DelegatorsInfo.getDelegatorRollingRewards( + nodes[0].identityId, + delegators[1].address, + ); + const d3RollingAfter = await DelegatorsInfo.getDelegatorRollingRewards( + nodes[1].identityId, + delegators[2].address, + ); + const d4RollingAfter = await DelegatorsInfo.getDelegatorRollingRewards( + nodes[1].identityId, + delegators[3].address, + ); + + console.log( + ` 💎 D1 stakeBase after: ${hre.ethers.formatUnits(d1StakeBaseAfter, 18)} TRAC`, + ); + console.log( + ` 💎 D2 stakeBase after: ${hre.ethers.formatUnits(d2StakeBaseAfter, 18)} TRAC`, + ); + console.log( + ` 💎 D3 stakeBase after: ${hre.ethers.formatUnits(d3StakeBaseAfter, 18)} TRAC`, + ); + console.log( + ` 💎 D4 stakeBase after: ${hre.ethers.formatUnits(d4StakeBaseAfter, 18)} TRAC`, + ); + + // Verify rolling rewards were transferred to stakeBase + expect(d1RollingAfter).to.equal( + 0n, + 'D1 rolling rewards should be 0 after final claim', + ); + expect(d2RollingAfter).to.equal( + 0n, + 'D2 rolling rewards should be 0 after final claim', + ); + expect(d3RollingAfter).to.equal( + 0n, + 'D3 rolling rewards should be 0 after final claim', + ); + expect(d4RollingAfter).to.equal( + 0n, + 'D4 rolling rewards should be 0 after final claim', + ); + + // Calculate total rewards transferred + const d1TotalRewards = d1StakeBaseAfter - d1StakeBaseBefore; + const d2TotalRewards = d2StakeBaseAfter - d2StakeBaseBefore; + const d3TotalRewards = d3StakeBaseAfter - d3StakeBaseBefore; + const d4TotalRewards = d4StakeBaseAfter - d4StakeBaseBefore; + + console.log( + ` 🎁 D1 total rewards transferred: ${hre.ethers.formatUnits(d1TotalRewards, 18)} TRAC`, + ); + console.log( + ` 🎁 D2 total rewards transferred: ${hre.ethers.formatUnits(d2TotalRewards, 18)} TRAC`, + ); + console.log( + ` 🎁 D3 total rewards transferred: ${hre.ethers.formatUnits(d3TotalRewards, 18)} TRAC`, + ); + console.log( + ` 🎁 D4 total rewards transferred: ${hre.ethers.formatUnits(d4TotalRewards, 18)} TRAC`, + ); + + // Verify proportional final rewards (allow small rounding differences) + const d2ToD1FinalRewardsRatio = + Number(d2TotalRewards) / Number(d1TotalRewards); + const d4ToD3FinalRewardsRatio = + Number(d4TotalRewards) / Number(d3TotalRewards); + + expect(d2ToD1FinalRewardsRatio).to.be.closeTo( + 2.0, + 0.001, + 'D2 should get approximately double D1 total rewards', + ); + expect(d4ToD3FinalRewardsRatio).to.be.closeTo( + 2.0, + 0.001, + 'D4 should get approximately double D3 total rewards', + ); + expect(d1TotalRewards).to.equal( + d3TotalRewards, + 'D1 and D3 should get equal total rewards', + ); + expect(d2TotalRewards).to.equal( + d4TotalRewards, + 'D2 and D4 should get equal total rewards', + ); + + // Verify final stakeBase proportions + const d1FinalStake = d1StakeBaseAfter; + const d2FinalStake = d2StakeBaseAfter; + const d3FinalStake = d3StakeBaseAfter; + const d4FinalStake = d4StakeBaseAfter; + + // Since D2 started with 2x D1 stake and got 2x rewards, final ratio should be maintained + // But exact 2x ratio might not hold due to rounding, so we check approximate ratios + const d2ToD1Ratio = Number(d2FinalStake) / Number(d1FinalStake); + const d4ToD3Ratio = Number(d4FinalStake) / Number(d3FinalStake); + + console.log( + ` 📊 Final D2/D1 stakeBase ratio: ${d2ToD1Ratio.toFixed(6)}`, + ); + console.log( + ` 📊 Final D4/D3 stakeBase ratio: ${d4ToD3Ratio.toFixed(6)}`, + ); + + // Ratios should be close to 2.0 but might have small deviations due to rounding + expect(d2ToD1Ratio).to.be.closeTo( + 2.0, + 0.01, + 'D2/D1 final stakeBase ratio should be close to 2.0', + ); + expect(d4ToD3Ratio).to.be.closeTo( + 2.0, + 0.01, + 'D4/D3 final stakeBase ratio should be close to 2.0', + ); + + console.log(' ✅ PROPORTIONAL REWARDS SYSTEM VERIFIED:'); + console.log( + ' 📈 Double stake consistently resulted in double rewards across all epochs', + ); + console.log(' 💰 Final stakeBase maintains proportional relationships'); + console.log(' 🎯 Reward system is fair and predictable'); + console.log( + ' 📝 Note: Proportional rewards successfully transferred to permanent stakeBase', + ); + }); +}); diff --git a/test/scripts/run-tests-with-summary.sh b/test/scripts/run-tests-with-summary.sh new file mode 100644 index 00000000..5ac0a94d --- /dev/null +++ b/test/scripts/run-tests-with-summary.sh @@ -0,0 +1,97 @@ +#!/bin/bash + +# Color codes +GREEN='\033[0;32m' +RED='\033[0;31m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +echo "Starting tests..." + +# Initialize counters and arrays +passed=0 +failed=0 +total_passed=0 +total_failed=0 +failed_tests=() +failed_errors=() + +# Dynamically find all test files in the entire test directory +echo "Finding test files in test directory..." +test_files=($(find test -name "*.test.ts" -type f | sort)) + +if [ ${#test_files[@]} -eq 0 ]; then + echo "No test files found in test directory!" + exit 1 +fi + +echo "Found ${#test_files[@]} test files:" +for file in "${test_files[@]}"; do + echo " - $file" +done +echo "" + +# Run each test file +for file in "${test_files[@]}"; do + echo "" + echo "Running $file..." + + # Run the test and capture output and exit code + output=$(hardhat test "$file" --network hardhat 2>&1 | grep -v -E "(Hardhat deployments config reset|Granting minter role|Parameter.*isn't the same as define in config|\[ParametersStorage\] Setting parameter)") + exit_code=$? + + # Also capture full output for error reporting (without filtering) + full_output=$(hardhat test "$file" --network hardhat 2>&1 | grep -v -E "(Hardhat deployments config reset|Granting minter role|Parameter.*isn't the same as define in config|\[ParametersStorage\] Setting parameter)") + + # Extract test counts from output + passing_count=$(echo "$output" | grep -o '[0-9]\+ passing' | head -1 | grep -o '[0-9]\+' || echo "0") + failing_count=$(echo "$output" | grep -o '[0-9]\+ failing' | head -1 | grep -o '[0-9]\+' || echo "0") + + # Check if test file passed or failed + if [ $exit_code -eq 0 ] && [ $failing_count -eq 0 ]; then + echo -e "${GREEN}PASSED: $file ($passing_count passing, $failing_count failing)${NC}" + ((passed++)) + else + echo -e "${RED}FAILED: $file ($passing_count passing, $failing_count failing)${NC}" + failed_tests+=("$file") + failed_errors+=("$full_output") + ((failed++)) + fi + + # Add to totals + total_passed=$((total_passed + passing_count)) + total_failed=$((total_failed + failing_count)) +done + +# Display final summary +echo "" +echo -e "${BLUE}FINAL SUMMARY${NC}" +echo "=============" +echo -e "Total tests passed: ${GREEN}$total_passed${NC}" +echo -e "Total tests failed: ${RED}$total_failed${NC}" +echo "Total individual tests: $((total_passed + total_failed))" + +# Show failed tests and their errors if any +if [ ${#failed_tests[@]} -gt 0 ] || [ $total_failed -gt 0 ]; then + echo "" + echo -e "${RED}FAILED TESTS AND ERRORS:${NC}" + echo "========================" + for i in "${!failed_tests[@]}"; do + echo "" + echo -e "${RED}FAILED: ${failed_tests[$i]}:${NC}" + echo "----------------------------------------" + echo "${failed_errors[$i]}" + echo "----------------------------------------" + done +fi + +# Exit with error code if any tests failed +if [ $failed -gt 0 ] || [ $total_failed -gt 0 ]; then + echo "" + echo -e "${RED}Some tests failed! Check the errors above.${NC}" + exit 1 +else + echo "" + echo -e "${GREEN}All tests passed successfully!${NC}" +fi \ No newline at end of file diff --git a/test/unit/Ask.test.ts b/test/unit/Ask.test.ts index 5c1d47c8..8941f14e 100644 --- a/test/unit/Ask.test.ts +++ b/test/unit/Ask.test.ts @@ -35,7 +35,13 @@ describe('@unit Ask', () => { let Token: Token; async function deployAll(): Promise { - await hre.deployments.fixture(['Profile', 'Ask', 'Staking', 'Token']); + await hre.deployments.fixture([ + 'Profile', + 'Ask', + 'Staking', + 'Token', + 'EpochStorage', + ]); Profile = await hre.ethers.getContract('Profile'); AskStorage = await hre.ethers.getContract('AskStorage'); @@ -179,7 +185,7 @@ describe('@unit Ask', () => { const reward = hre.ethers.parseUnits('10000', 18); await Token.mint(accounts[0].address, reward); - await Staking.distributeRewards(identityId, BigInt(reward)); + await StakingStorage.increaseOperatorFeeBalance(identityId, BigInt(reward)); const restake = hre.ethers.parseUnits('500', 18); await Staking.connect(accounts[0]).restakeOperatorFee(identityId, restake); @@ -271,7 +277,11 @@ describe('@unit Ask', () => { const total = await AskStorage.totalActiveStake(); expect(weighted).to.be.eq(stakeVal * 1000n); expect(total).to.be.eq(stakeVal); - await Staking.distributeRewards( + await StakingStorage.increaseOperatorFeeBalance( + identityId, + hre.ethers.parseUnits('10000', 18), + ); + await Staking.connect(accounts[0]).restakeOperatorFee( identityId, hre.ethers.parseUnits('10000', 18), ); @@ -279,7 +289,11 @@ describe('@unit Ask', () => { let stakeAfterRewards = await AskStorage.totalActiveStake(); expect(sumAfterRewards).to.be.gte(0n); expect(stakeAfterRewards).to.be.gte(stakeVal); - await Staking.distributeRewards( + await StakingStorage.increaseOperatorFeeBalance( + identityId, + hre.ethers.parseUnits('5000', 18), + ); + await Staking.connect(accounts[0]).restakeOperatorFee( identityId, hre.ethers.parseUnits('5000', 18), ); @@ -343,7 +357,7 @@ describe('@unit Ask', () => { await Token.mint(accounts[2].address, stVal); await Token.connect(accounts[2]).approve(Staking.getAddress(), stVal); await Staking.connect(accounts[2]).stake(identityId, stVal); - await Staking.distributeRewards( + await StakingStorage.increaseOperatorFeeBalance( identityId, hre.ethers.parseUnits('30000', 18), ); diff --git a/test/unit/DelegatorsInfo.test.ts b/test/unit/DelegatorsInfo.test.ts new file mode 100644 index 00000000..4497240b --- /dev/null +++ b/test/unit/DelegatorsInfo.test.ts @@ -0,0 +1,918 @@ +import { randomBytes } from 'crypto'; + +import { SignerWithAddress } from '@nomicfoundation/hardhat-ethers/signers'; +import { loadFixture } from '@nomicfoundation/hardhat-network-helpers'; +import { expect } from 'chai'; +import hre, { ethers } from 'hardhat'; + +import { + Token, + Profile, + StakingStorage, + ParametersStorage, + ProfileStorage, + ShardingTable, + ShardingTableStorage, + AskStorage, + Hub, + Staking, + DelegatorsInfo, +} from '../../typechain'; + +type StakingFixture = { + accounts: SignerWithAddress[]; + Token: Token; + Profile: Profile; + Staking: Staking; + StakingStorage: StakingStorage; + ShardingTableStorage: ShardingTableStorage; + ShardingTable: ShardingTable; + ParametersStorage: ParametersStorage; + ProfileStorage: ProfileStorage; + AskStorage: AskStorage; + Hub: Hub; + DelegatorsInfo: DelegatorsInfo; +}; + +async function deployStakingFixture(): Promise { + await hre.deployments.fixture(['Profile', 'Staking', 'EpochStorage']); + const Staking = await hre.ethers.getContract('Staking'); + const Profile = await hre.ethers.getContract('Profile'); + const Token = await hre.ethers.getContract('Token'); + const StakingStorage = + await hre.ethers.getContract('StakingStorage'); + const ShardingTableStorage = + await hre.ethers.getContract('ShardingTableStorage'); + const ShardingTable = + await hre.ethers.getContract('ShardingTable'); + const ParametersStorage = + await hre.ethers.getContract('ParametersStorage'); + const ProfileStorage = + await hre.ethers.getContract('ProfileStorage'); + const AskStorage = await hre.ethers.getContract('AskStorage'); + const Hub = await hre.ethers.getContract('Hub'); + const DelegatorsInfo = + await hre.ethers.getContract('DelegatorsInfo'); + const accounts = await hre.ethers.getSigners(); + + await Hub.setContractAddress('HubOwner', accounts[0].address); + + return { + accounts, + Token, + Profile, + Staking, + StakingStorage, + ShardingTableStorage, + ShardingTable, + ParametersStorage, + ProfileStorage, + AskStorage, + Hub, + DelegatorsInfo, + }; +} + +describe('DelegatorsInfo contract', function () { + let accounts: SignerWithAddress[]; + let Profile: Profile; + let DelegatorsInfo: DelegatorsInfo; + let stakingSigner: any; // eslint-disable-line @typescript-eslint/no-explicit-any + const createProfile = async ( + admin?: SignerWithAddress, + operational?: SignerWithAddress, + initialOperatorFee?: bigint, + ) => { + const node = '0x' + randomBytes(32).toString('hex'); + const tx = await Profile.connect(operational ?? accounts[1]).createProfile( + admin ? admin.address : accounts[0], + [], + `Node ${Math.floor(Math.random() * 1000)}`, + node, + (initialOperatorFee ?? 0n) * 100n, + ); + const receipt = await tx.wait(); + const identityId = Number(receipt?.logs[0].topics[1]); + return { nodeId: node, identityId }; + }; + + beforeEach(async () => { + ({ accounts, Profile, DelegatorsInfo } = + await loadFixture(deployStakingFixture)); + + // Create a signer from the Staking contract address + const stakingContract = await hre.ethers.getContract('Staking'); + const stakingAddress = stakingContract.target.toString(); + stakingSigner = await hre.ethers.getImpersonatedSigner(stakingAddress); + + // Fund the Staking contract address with some ETH for gas + await hre.network.provider.send('hardhat_setBalance', [ + stakingAddress, + '0x' + hre.ethers.parseEther('1.0').toString(16), + ]); + }); + + it('Should have correct name and version', async () => { + expect(await DelegatorsInfo.name()).to.equal('DelegatorsInfo'); + expect(await DelegatorsInfo.version()).to.equal('1.0.0'); + }); + + it('Should add delegator', async () => { + const { identityId } = await createProfile(); + await DelegatorsInfo.addDelegator(identityId, accounts[1].address); + const isDelegator = await DelegatorsInfo.isNodeDelegator( + identityId, + accounts[1].address, + ); + expect(isDelegator).to.equal(true); + }); + + it('Should remove delegator', async () => { + const { identityId } = await createProfile(); + await DelegatorsInfo.addDelegator(identityId, accounts[1].address); + await DelegatorsInfo.removeDelegator(identityId, accounts[1].address); + const isDelegator = await DelegatorsInfo.isNodeDelegator( + identityId, + accounts[1].address, + ); + expect(isDelegator).to.equal(false); + const nodeDelegators = await DelegatorsInfo.getDelegators(identityId); + expect(nodeDelegators.length).to.equal(0); + }); + it('Should remove delegator from end of array', async () => { + const { identityId } = await createProfile(); + await DelegatorsInfo.addDelegator(identityId, accounts[1].address); + await DelegatorsInfo.addDelegator(identityId, accounts[2].address); + await DelegatorsInfo.removeDelegator(identityId, accounts[2].address); + const isDelegator = await DelegatorsInfo.isNodeDelegator( + identityId, + accounts[2].address, + ); + expect(isDelegator).to.equal(false); + const nodeDelegators = await DelegatorsInfo.getDelegators(identityId); + expect(nodeDelegators.length).to.equal(1); + expect(nodeDelegators[0]).to.equal(accounts[1].address); + const removedDelegatorIndex = await DelegatorsInfo.getDelegatorIndex( + identityId, + accounts[2].address, + ); + expect(removedDelegatorIndex).to.equal(0); + const keptDelegatorIndex = await DelegatorsInfo.getDelegatorIndex( + identityId, + accounts[1].address, + ); + expect(keptDelegatorIndex).to.equal(0); + }); + it('Should remove delegator from middle of array', async () => { + const { identityId } = await createProfile(); + await DelegatorsInfo.addDelegator(identityId, accounts[1].address); + await DelegatorsInfo.addDelegator(identityId, accounts[2].address); + await DelegatorsInfo.addDelegator(identityId, accounts[3].address); + + const isDelegator1 = await DelegatorsInfo.isNodeDelegator( + identityId, + accounts[1].address, + ); + expect(isDelegator1).to.equal(true); + const isDelegator2 = await DelegatorsInfo.isNodeDelegator( + identityId, + accounts[2].address, + ); + expect(isDelegator2).to.equal(true); + const isDelegator3 = await DelegatorsInfo.isNodeDelegator( + identityId, + accounts[3].address, + ); + expect(isDelegator3).to.equal(true); + await DelegatorsInfo.removeDelegator(identityId, accounts[2].address); + + const isDelegator = await DelegatorsInfo.isNodeDelegator( + identityId, + accounts[2].address, + ); + expect(isDelegator).to.equal(false); + const nodeDelegators = await DelegatorsInfo.getDelegators(identityId); + expect(nodeDelegators.length).to.equal(2); + expect(nodeDelegators[0]).to.equal(accounts[1].address); + expect(nodeDelegators[1]).to.equal(accounts[3].address); + const removedDelegatorIndex = await DelegatorsInfo.getDelegatorIndex( + identityId, + accounts[2].address, + ); + expect(removedDelegatorIndex).to.equal(0); + const keptDelegatorIndex1 = await DelegatorsInfo.getDelegatorIndex( + identityId, + accounts[1].address, + ); + expect(keptDelegatorIndex1).to.equal(0); + const keptDelegatorIndex3 = await DelegatorsInfo.getDelegatorIndex( + identityId, + accounts[3].address, + ); + expect(keptDelegatorIndex3).to.equal(1); + }); + + it('Should revert when removing non-existent delegator', async () => { + const { identityId } = await createProfile(); + await expect( + DelegatorsInfo.removeDelegator(identityId, accounts[1].address), + ).to.be.revertedWith('Delegator not found'); + }); + + it('Should handle multiple operations on same identity', async () => { + const { identityId } = await createProfile(); + // Add multiple delegators + await DelegatorsInfo.addDelegator(identityId, accounts[1].address); + await DelegatorsInfo.addDelegator(identityId, accounts[2].address); + + // Remove and re-add + await DelegatorsInfo.removeDelegator(identityId, accounts[1].address); + await DelegatorsInfo.addDelegator(identityId, accounts[1].address); + + const delegators = await DelegatorsInfo.getDelegators(identityId); + expect(delegators.length).to.equal(2); + // Check if indices were updated correctly + expect( + await DelegatorsInfo.getDelegatorIndex(identityId, accounts[1].address), + ).to.equal(1); + }); + + it('Should return correct delegator list', async () => { + const { identityId } = await createProfile(); + await DelegatorsInfo.addDelegator(identityId, accounts[1].address); + await DelegatorsInfo.addDelegator(identityId, accounts[2].address); + + const delegators = await DelegatorsInfo.getDelegators(identityId); + expect(delegators).to.deep.equal([ + accounts[1].address, + accounts[2].address, + ]); + }); + + it('Should return empty array for non-existent identity', async () => { + const delegators = await DelegatorsInfo.getDelegators(999); + expect(delegators.length).to.equal(0); + }); + + it('Should set and get lastClaimedEpoch, emit DelegatorLastClaimedEpochUpdated', async () => { + const { identityId } = await createProfile(); + + const delegator = accounts[1].address; + const epoch = 1; + const epoch2 = 2; + + await expect( + DelegatorsInfo.setLastClaimedEpoch(identityId, delegator, epoch), + ) + .to.emit(DelegatorsInfo, 'DelegatorLastClaimedEpochUpdated') + .withArgs(identityId, delegator, epoch); + + expect( + await DelegatorsInfo.getLastClaimedEpoch(identityId, delegator), + ).to.equal(epoch); + + // Make sure it updates the value + await expect( + DelegatorsInfo.setLastClaimedEpoch(identityId, delegator, epoch2), + ) + .to.emit(DelegatorsInfo, 'DelegatorLastClaimedEpochUpdated') + .withArgs(identityId, delegator, epoch2); + + expect( + await DelegatorsInfo.getLastClaimedEpoch(identityId, delegator), + ).to.equal(epoch2); + }); + + it('Should set and get DelegatorRollingRewards, emit DelegatorRollingRewardsUpdated', async () => { + const { identityId } = await createProfile(); + + const delegator = accounts[1].address; + const amount = 500; + const amount2 = 1000; + + await expect( + DelegatorsInfo.setDelegatorRollingRewards(identityId, delegator, amount), + ) + .to.emit(DelegatorsInfo, 'DelegatorRollingRewardsUpdated') + .withArgs(identityId, delegator, amount, amount); + + expect( + await DelegatorsInfo.getDelegatorRollingRewards(identityId, delegator), + ).to.equal(amount); + + // Make sure it updates the value + await expect( + DelegatorsInfo.setDelegatorRollingRewards(identityId, delegator, amount2), + ) + .to.emit(DelegatorsInfo, 'DelegatorRollingRewardsUpdated') + .withArgs(identityId, delegator, amount2, amount2); + + expect( + await DelegatorsInfo.getDelegatorRollingRewards(identityId, delegator), + ).to.equal(amount2); + }); + + it('Should set IsOperatorFeeClaimedForEpoch and emit IsOperatorFeeClaimedForEpochUpdated', async () => { + const { identityId } = await createProfile(); + + const epoch = 1; + const isClaimed = false; + + await expect( + DelegatorsInfo.setIsOperatorFeeClaimedForEpoch( + identityId, + epoch, + isClaimed, + ), + ) + .to.emit(DelegatorsInfo, 'IsOperatorFeeClaimedForEpochUpdated') + .withArgs(identityId, epoch, isClaimed); + }); + + it('Should set and get NetNodeEpochRewards, emit NetNodeEpochRewardsSet', async () => { + const { identityId } = await createProfile(); + + const amount = 500; + const epoch = 1; + + await expect( + DelegatorsInfo.setNetNodeEpochRewards(identityId, epoch, amount), + ) + .to.emit(DelegatorsInfo, 'NetNodeEpochRewardsSet') + .withArgs(identityId, epoch, amount); + + expect( + await DelegatorsInfo.getNetNodeEpochRewards(identityId, epoch), + ).to.equal(amount); + }); + + it('Should set HasDelegatorClaimedEpochRewards and emit HasDelegatorClaimedEpochRewardsUpdated', async () => { + const { identityId } = await createProfile(); + + const claimed = false; + const epoch = 1; + const delegatorKey = ethers.encodeBytes32String('delegator1'); + + await expect( + DelegatorsInfo.setHasDelegatorClaimedEpochRewards( + epoch, + identityId, + delegatorKey, + claimed, + ), + ) + .to.emit(DelegatorsInfo, 'HasDelegatorClaimedEpochRewardsUpdated') + .withArgs(epoch, identityId, delegatorKey, claimed); + }); + + it('Should set setHasEverDelegatedToNode and emit HasEverDelegatedToNodeUpdated', async () => { + const { identityId } = await createProfile(); + + const claimed = false; + const delegator = accounts[1].address; + + await expect( + DelegatorsInfo.setHasEverDelegatedToNode(identityId, delegator, claimed), + ) + .to.emit(DelegatorsInfo, 'HasEverDelegatedToNodeUpdated') + .withArgs(identityId, delegator, claimed); + }); + + it('Should set and get setLastStakeHeldEpoch, emit LastStakeHeldEpochUpdated', async () => { + const { identityId } = await createProfile(); + + const epoch = 1; + const delegator = accounts[1].address; + + await expect( + DelegatorsInfo.setLastStakeHeldEpoch(identityId, delegator, epoch), + ).to.emit(DelegatorsInfo, 'LastStakeHeldEpochUpdated'); + + expect( + await DelegatorsInfo.getLastStakeHeldEpoch(identityId, delegator), + ).to.equal(epoch); + }); + + it('Should set delegator rolling rewards', async () => { + const { identityId } = await createProfile(); + const delegator = accounts[2].address; + const amount = 500; + + await expect(await DelegatorsInfo.addDelegator(identityId, delegator)) + .to.emit(DelegatorsInfo, 'DelegatorAdded') + .withArgs(identityId, delegator); + + await expect( + await DelegatorsInfo.setDelegatorRollingRewards( + identityId, + delegator, + amount, + ), + ) + .to.emit(DelegatorsInfo, 'DelegatorRollingRewardsUpdated') + .withArgs(identityId, delegator, amount, amount); + + expect( + await DelegatorsInfo.getDelegatorRollingRewards(identityId, delegator), + ).to.equal(amount); + }); + + it('Should add to delegator rolling rewards', async () => { + const { identityId } = await createProfile(); + const delegator = accounts[2].address; + const amount = 500; + const amount2 = 1000; + + await expect(await DelegatorsInfo.addDelegator(identityId, delegator)) + .to.emit(DelegatorsInfo, 'DelegatorAdded') + .withArgs(identityId, delegator); + + await expect( + await DelegatorsInfo.setDelegatorRollingRewards( + identityId, + delegator, + amount, + ), + ) + .to.emit(DelegatorsInfo, 'DelegatorRollingRewardsUpdated') + .withArgs(identityId, delegator, amount, amount); + + await expect( + await DelegatorsInfo.addDelegatorRollingRewards( + identityId, + delegator, + amount2, + ), + ) + .to.emit(DelegatorsInfo, 'DelegatorRollingRewardsUpdated') + .withArgs(identityId, delegator, amount2, amount + amount2); + + expect( + await DelegatorsInfo.getDelegatorRollingRewards(identityId, delegator), + ).to.equal(amount + amount2); + }); + + it('Should return zero rolling rewards for non-delegator', async () => { + const { identityId } = await createProfile(); + const delegator = accounts[1].address; + + expect( + await DelegatorsInfo.getDelegatorRollingRewards(identityId, delegator), + ).to.equal(0); + }); + + // Access control tests + describe('Access control', function () { + it('Should allow Staking contract to call addDelegator but revert for unauthorized', async () => { + const { identityId } = await createProfile(); + + await expect( + DelegatorsInfo.connect(stakingSigner).addDelegator( + identityId, + accounts[1].address, + ), + ) + .to.emit(DelegatorsInfo, 'DelegatorAdded') + .withArgs(identityId, accounts[1].address); + + await expect( + DelegatorsInfo.connect(accounts[2]).addDelegator( + identityId, + accounts[3].address, + ), + ).to.be.revertedWithCustomError(DelegatorsInfo, 'UnauthorizedAccess'); + }); + + it('Should allow Staking contract to call removeDelegator but revert for unauthorized', async () => { + const { identityId } = await createProfile(); + + await DelegatorsInfo.connect(stakingSigner).addDelegator( + identityId, + accounts[1].address, + ); + + await expect( + DelegatorsInfo.connect(stakingSigner).removeDelegator( + identityId, + accounts[1].address, + ), + ) + .to.emit(DelegatorsInfo, 'DelegatorRemoved') + .withArgs(identityId, accounts[1].address); + + await expect( + DelegatorsInfo.connect(accounts[2]).removeDelegator( + identityId, + accounts[3].address, + ), + ).to.be.revertedWithCustomError(DelegatorsInfo, 'UnauthorizedAccess'); + }); + + it('Should allow Staking contract to call setLastClaimedEpoch but revert for unauthorized', async () => { + const { identityId } = await createProfile(); + const epoch = 5; + + await expect( + DelegatorsInfo.connect(stakingSigner).setLastClaimedEpoch( + identityId, + accounts[1].address, + epoch, + ), + ) + .to.emit(DelegatorsInfo, 'DelegatorLastClaimedEpochUpdated') + .withArgs(identityId, accounts[1].address, epoch); + + await expect( + DelegatorsInfo.connect(accounts[2]).setLastClaimedEpoch( + identityId, + accounts[1].address, + epoch, + ), + ).to.be.revertedWithCustomError(DelegatorsInfo, 'UnauthorizedAccess'); + }); + + it('Should allow Staking contract to call setDelegatorRollingRewards but revert for unauthorized', async () => { + const { identityId } = await createProfile(); + const amount = 1000; + + await expect( + DelegatorsInfo.connect(stakingSigner).setDelegatorRollingRewards( + identityId, + accounts[1].address, + amount, + ), + ) + .to.emit(DelegatorsInfo, 'DelegatorRollingRewardsUpdated') + .withArgs(identityId, accounts[1].address, amount, amount); + + await expect( + DelegatorsInfo.connect(accounts[2]).setDelegatorRollingRewards( + identityId, + accounts[1].address, + amount, + ), + ).to.be.revertedWithCustomError(DelegatorsInfo, 'UnauthorizedAccess'); + }); + + it('Should allow Staking contract to call addDelegatorRollingRewards but revert for unauthorized', async () => { + const { identityId } = await createProfile(); + const initialAmount = 500; + const additionalAmount = 300; + + await DelegatorsInfo.connect(stakingSigner).setDelegatorRollingRewards( + identityId, + accounts[1].address, + initialAmount, + ); + + await expect( + DelegatorsInfo.connect(stakingSigner).addDelegatorRollingRewards( + identityId, + accounts[1].address, + additionalAmount, + ), + ) + .to.emit(DelegatorsInfo, 'DelegatorRollingRewardsUpdated') + .withArgs( + identityId, + accounts[1].address, + additionalAmount, + initialAmount + additionalAmount, + ); + + await expect( + DelegatorsInfo.connect(accounts[2]).addDelegatorRollingRewards( + identityId, + accounts[1].address, + additionalAmount, + ), + ).to.be.revertedWithCustomError(DelegatorsInfo, 'UnauthorizedAccess'); + }); + + it('Should allow Staking contract to call setIsOperatorFeeClaimedForEpoch but revert for unauthorized', async () => { + const { identityId } = await createProfile(); + const epoch = 3; + const isClaimed = true; + + await expect( + DelegatorsInfo.connect(stakingSigner).setIsOperatorFeeClaimedForEpoch( + identityId, + epoch, + isClaimed, + ), + ) + .to.emit(DelegatorsInfo, 'IsOperatorFeeClaimedForEpochUpdated') + .withArgs(identityId, epoch, isClaimed); + + await expect( + DelegatorsInfo.connect(accounts[2]).setIsOperatorFeeClaimedForEpoch( + identityId, + epoch, + isClaimed, + ), + ).to.be.revertedWithCustomError(DelegatorsInfo, 'UnauthorizedAccess'); + }); + + it('Should allow Staking contract to call setNetNodeEpochRewards but revert for unauthorized', async () => { + const { identityId } = await createProfile(); + const epoch = 2; + const amount = 2000; + + await expect( + DelegatorsInfo.connect(stakingSigner).setNetNodeEpochRewards( + identityId, + epoch, + amount, + ), + ) + .to.emit(DelegatorsInfo, 'NetNodeEpochRewardsSet') + .withArgs(identityId, epoch, amount); + + await expect( + DelegatorsInfo.connect(accounts[2]).setNetNodeEpochRewards( + identityId, + epoch, + amount, + ), + ).to.be.revertedWithCustomError(DelegatorsInfo, 'UnauthorizedAccess'); + }); + + it('Should allow Staking contract to call setHasDelegatorClaimedEpochRewards but revert for unauthorized', async () => { + const { identityId } = await createProfile(); + const epoch = 1; + const delegatorKey = ethers.encodeBytes32String('testDelegatorKey'); + const claimed = true; + + await expect( + DelegatorsInfo.connect( + stakingSigner, + ).setHasDelegatorClaimedEpochRewards( + epoch, + identityId, + delegatorKey, + claimed, + ), + ) + .to.emit(DelegatorsInfo, 'HasDelegatorClaimedEpochRewardsUpdated') + .withArgs(epoch, identityId, delegatorKey, claimed); + + await expect( + DelegatorsInfo.connect(accounts[2]).setHasDelegatorClaimedEpochRewards( + epoch, + identityId, + delegatorKey, + claimed, + ), + ).to.be.revertedWithCustomError(DelegatorsInfo, 'UnauthorizedAccess'); + }); + + it('Should allow Staking contract to call setHasEverDelegatedToNode but revert for unauthorized', async () => { + const { identityId } = await createProfile(); + const hasEverDelegated = true; + + await expect( + DelegatorsInfo.connect(stakingSigner).setHasEverDelegatedToNode( + identityId, + accounts[1].address, + hasEverDelegated, + ), + ) + .to.emit(DelegatorsInfo, 'HasEverDelegatedToNodeUpdated') + .withArgs(identityId, accounts[1].address, hasEverDelegated); + + await expect( + DelegatorsInfo.connect(accounts[2]).setHasEverDelegatedToNode( + identityId, + accounts[1].address, + hasEverDelegated, + ), + ).to.be.revertedWithCustomError(DelegatorsInfo, 'UnauthorizedAccess'); + }); + + it('Should allow Staking contract to call setLastStakeHeldEpoch but revert for unauthorized', async () => { + const { identityId } = await createProfile(); + const epoch = 4; + + await expect( + DelegatorsInfo.connect(stakingSigner).setLastStakeHeldEpoch( + identityId, + accounts[1].address, + epoch, + ), + ) + .to.emit(DelegatorsInfo, 'LastStakeHeldEpochUpdated') + .withArgs(identityId, accounts[1].address, epoch); + + await expect( + DelegatorsInfo.connect(accounts[2]).setLastStakeHeldEpoch( + identityId, + accounts[1].address, + epoch, + ), + ).to.be.revertedWithCustomError(DelegatorsInfo, 'UnauthorizedAccess'); + }); + }); + + // Migration tests + describe('Migration', function () { + it('Should migrate new addresses to delegators for their nodes', async () => { + const { identityId } = await createProfile(); + const { identityId: identityId2 } = await createProfile( + undefined, + accounts[2], + ); // Use different operational account + + // Get StakingStorage contract to set up test data + const stakingStorage = + await hre.ethers.getContract('StakingStorage'); + + // Create delegator keys for the addresses we want to migrate + const delegator1 = accounts[3].address; + const delegator2 = accounts[4].address; + const delegatorKey1 = ethers.keccak256( + ethers.solidityPacked(['address'], [delegator1]), + ); + const delegatorKey2 = ethers.keccak256( + ethers.solidityPacked(['address'], [delegator2]), + ); + + // Set up delegator data in StakingStorage to simulate existing delegations + // We need to make the delegators active in StakingStorage first + await stakingStorage + .connect(stakingSigner) + .setDelegatorStakeBase(identityId, delegatorKey1, 1000); + await stakingStorage + .connect(stakingSigner) + .setDelegatorStakeBase(identityId, delegatorKey2, 2000); + await stakingStorage + .connect(stakingSigner) + .setDelegatorStakeBase(identityId2, delegatorKey1, 1500); + + // Verify the delegators are not yet in DelegatorsInfo + expect( + await DelegatorsInfo.isNodeDelegator(identityId, delegator1), + ).to.equal(false); + expect( + await DelegatorsInfo.isNodeDelegator(identityId, delegator2), + ).to.equal(false); + expect( + await DelegatorsInfo.isNodeDelegator(identityId2, delegator1), + ).to.equal(false); + + // Migrate the addresses + const newAddresses = [delegator1, delegator2]; + await expect(DelegatorsInfo.migrate(newAddresses)) + .to.emit(DelegatorsInfo, 'DelegatorAdded') + .withArgs(identityId, delegator1) + .and.to.emit(DelegatorsInfo, 'DelegatorAdded') + .withArgs(identityId, delegator2) + .and.to.emit(DelegatorsInfo, 'DelegatorAdded') + .withArgs(identityId2, delegator1); + + // Verify the delegators are now in DelegatorsInfo + expect( + await DelegatorsInfo.isNodeDelegator(identityId, delegator1), + ).to.equal(true); + expect( + await DelegatorsInfo.isNodeDelegator(identityId, delegator2), + ).to.equal(true); + expect( + await DelegatorsInfo.isNodeDelegator(identityId2, delegator1), + ).to.equal(true); + + // Verify delegator2 is not in identityId2 (since it wasn't staking there) + expect( + await DelegatorsInfo.isNodeDelegator(identityId2, delegator2), + ).to.equal(false); + + // Verify the delegator lists are correct + const delegators1 = await DelegatorsInfo.getDelegators(identityId); + const delegators2 = await DelegatorsInfo.getDelegators(identityId2); + + expect(delegators1).to.include(delegator1); + expect(delegators1).to.include(delegator2); + expect(delegators2).to.include(delegator1); + expect(delegators2).to.not.include(delegator2); + }); + + it('Should handle duplicate migration gracefully', async () => { + const { identityId } = await createProfile(); + + const stakingStorage = + await hre.ethers.getContract('StakingStorage'); + const delegator = accounts[3].address; + const delegatorKey = ethers.keccak256( + ethers.solidityPacked(['address'], [delegator]), + ); + + // Set up delegator data in StakingStorage + await stakingStorage + .connect(stakingSigner) + .setDelegatorStakeBase(identityId, delegatorKey, 1000); + + // First migration + await DelegatorsInfo.migrate([delegator]); + expect( + await DelegatorsInfo.isNodeDelegator(identityId, delegator), + ).to.equal(true); + + // Second migration of the same address should not add duplicates + await DelegatorsInfo.migrate([delegator]); + + // Verify the delegator is still there and no duplicates + expect( + await DelegatorsInfo.isNodeDelegator(identityId, delegator), + ).to.equal(true); + const delegators = await DelegatorsInfo.getDelegators(identityId); + expect(delegators.filter((d) => d === delegator).length).to.equal(1); + }); + + it('Should handle empty address array', async () => { + // Should not revert with empty array + await expect(DelegatorsInfo.migrate([])).to.not.be.reverted; + }); + + it('Should handle addresses with no delegator nodes', async () => { + const { identityId } = await createProfile(); + + // Use an address that has no delegator nodes in StakingStorage + const addressWithNoNodes = accounts[5].address; + + // Should not revert and should not add the address as a delegator + await expect(DelegatorsInfo.migrate([addressWithNoNodes])).to.not.be + .reverted; + expect( + await DelegatorsInfo.isNodeDelegator(identityId, addressWithNoNodes), + ).to.equal(false); + }); + + it('Should handle mixed addresses (some with nodes, some without)', async () => { + const { identityId } = await createProfile(); + + const stakingStorage = + await hre.ethers.getContract('StakingStorage'); + const delegator = accounts[3].address; + const delegatorKey = ethers.keccak256( + ethers.solidityPacked(['address'], [delegator]), + ); + const addressWithNoNodes = accounts[5].address; + + // Set up delegator data for only one address + await stakingStorage + .connect(stakingSigner) + .setDelegatorStakeBase(identityId, delegatorKey, 1000); + + // Migrate both addresses + await expect(DelegatorsInfo.migrate([delegator, addressWithNoNodes])) + .to.emit(DelegatorsInfo, 'DelegatorAdded') + .withArgs(identityId, delegator); + + // Verify only the address with nodes was added + expect( + await DelegatorsInfo.isNodeDelegator(identityId, delegator), + ).to.equal(true); + expect( + await DelegatorsInfo.isNodeDelegator(identityId, addressWithNoNodes), + ).to.equal(false); + }); + + it('Should maintain correct delegator indices after migration', async () => { + const { identityId } = await createProfile(); + + const stakingStorage = + await hre.ethers.getContract('StakingStorage'); + const delegator1 = accounts[3].address; + const delegator2 = accounts[4].address; + const delegatorKey1 = ethers.keccak256( + ethers.solidityPacked(['address'], [delegator1]), + ); + const delegatorKey2 = ethers.keccak256( + ethers.solidityPacked(['address'], [delegator2]), + ); + + // Set up delegator data in StakingStorage + await stakingStorage + .connect(stakingSigner) + .setDelegatorStakeBase(identityId, delegatorKey1, 1000); + await stakingStorage + .connect(stakingSigner) + .setDelegatorStakeBase(identityId, delegatorKey2, 2000); + + // Migrate the addresses + await DelegatorsInfo.migrate([delegator1, delegator2]); + + // Verify indices are correct + expect( + await DelegatorsInfo.getDelegatorIndex(identityId, delegator1), + ).to.equal(0); + expect( + await DelegatorsInfo.getDelegatorIndex(identityId, delegator2), + ).to.equal(1); + + // Verify delegator list order + const delegators = await DelegatorsInfo.getDelegators(identityId); + expect(delegators[0]).to.equal(delegator1); + expect(delegators[1]).to.equal(delegator2); + }); + }); +}); diff --git a/test/unit/EpochStorage.test.ts b/test/unit/EpochStorage.test.ts index c86d0ff4..8b749d93 100644 --- a/test/unit/EpochStorage.test.ts +++ b/test/unit/EpochStorage.test.ts @@ -76,11 +76,21 @@ describe('@unit EpochStorage', () => { ).to.equal(0); }); - it('Add tokens to epoch range, check pool and remainder', async () => { - await EpochStorage.addTokensToEpochRange(1, 5, 9, 1000); - expect(await EpochStorage.accumulatedRemainder(1)).to.be.lte(100); // some remainder left - expect(await EpochStorage.getEpochPool(1, 5)).to.be.gt(0); - expect(await EpochStorage.getEpochPool(1, 9)).to.be.gt(0); + it('Add tokens to epoch range, check if distributed pool is correct', async () => { + await EpochStorage.addTokensToEpochRange(1, 100, 109, 100); + + expect(await EpochStorage.getEpochPool(1, 99)).to.be.equal(0); + expect(await EpochStorage.getEpochPool(1, 101)).to.be.equal(10); + expect(await EpochStorage.getEpochPool(1, 102)).to.be.equal(10); + expect(await EpochStorage.getEpochPool(1, 103)).to.be.equal(10); + expect(await EpochStorage.getEpochPool(1, 104)).to.be.equal(10); + expect(await EpochStorage.getEpochPool(1, 105)).to.be.equal(10); + expect(await EpochStorage.getEpochPool(1, 106)).to.be.equal(10); + expect(await EpochStorage.getEpochPool(1, 107)).to.be.equal(10); + expect(await EpochStorage.getEpochPool(1, 108)).to.be.equal(10); + expect(await EpochStorage.getEpochPool(1, 109)).to.be.equal(10); + expect(await EpochStorage.getEpochPool(1, 110)).to.be.equal(0); + expect(await EpochStorage.getEpochPool(1, 111)).to.be.equal(0); // expect(await EpochStorage.getEpochPool(1, 9)).to.be.gt(0); }); it('Pay out epoch tokens, verify distribution and nodePaidOut', async () => { diff --git a/test/unit/KnowledgeCollection.test.ts b/test/unit/KnowledgeCollection.test.ts index 8b645e2e..6e228a1e 100644 --- a/test/unit/KnowledgeCollection.test.ts +++ b/test/unit/KnowledgeCollection.test.ts @@ -1,5 +1,6 @@ import { SignerWithAddress } from '@nomicfoundation/hardhat-ethers/signers'; import { loadFixture } from '@nomicfoundation/hardhat-network-helpers'; +import { kcTools } from 'assertion-tools'; import { expect } from 'chai'; import { ethers } from 'ethers'; import hre from 'hardhat'; @@ -144,25 +145,42 @@ describe('@unit KnowledgeCollection', () => { } = await loadFixture(deployKnowledgeCollectionFixture)); }); - it('Should create a knowledge collection successfully', async () => { + it('Should create a KC & distribute tokens fractionally across epochs', async () => { + /* ---------- actors & helpers ---------- */ const kcCreator = getDefaultKCCreator(accounts); const publishingNode = getDefaultPublishingNode(accounts); const receivingNodes = getDefaultReceivingNodes(accounts); - - const contracts = { - Profile, - KnowledgeCollection, - Token, - }; + const contracts = { Profile, KnowledgeCollection, Token }; const { identityId: publishingNodeIdentityId } = await createProfile( - contracts.Profile, + Profile, publishingNode, ); const receivingNodesIdentityIds = ( - await createProfiles(contracts.Profile, receivingNodes) + await createProfiles(Profile, receivingNodes) ).map((p) => p.identityId); + /* ---------- parameters ---------- */ + const tokenAmount = ethers.parseEther('100'); + const numberOfEpochs = 5n; + const merkleRoot = kcTools.calculateMerkleRoot( + [' .'], + 32, + ); + + /* ---------- epoch telemetry BEFORE tx ---------- */ + const currentEpoch = await Chronos.getCurrentEpoch(); + const epochLen = await Chronos.epochLength(); // bigint + const timeLeft0 = await Chronos.timeUntilNextEpoch(); + const elapsed0 = epochLen - timeLeft0; + const pct0 = Number((elapsed0 * 100n) / epochLen); + + console.log( + `\n⏱️ BEFORE | Epoch #${currentEpoch}: ` + + `${elapsed0.toString()}s elapsed / ${epochLen.toString()}s (${pct0}%)`, + ); + + /* ---------- create KC ---------- */ const { collectionId } = await createKnowledgeCollection( kcCreator, publishingNode, @@ -170,24 +188,82 @@ describe('@unit KnowledgeCollection', () => { receivingNodes, receivingNodesIdentityIds, contracts, + merkleRoot, + 'test-operation-id', + 10, + 1000, + Number(numberOfEpochs), + tokenAmount, + false, + ethers.ZeroAddress, ); - expect(collectionId).to.equal(1); - // Verify knowledge collection was created - const metadata = - await KnowledgeCollectionStorage.getKnowledgeCollectionMetadata( - collectionId, - ); + /* ---------- epoch telemetry AFTER tx ---------- */ + const timeLeft1 = await Chronos.timeUntilNextEpoch(); + const elapsed1 = epochLen - timeLeft1; + const pct1 = Number((elapsed1 * 100n) / epochLen); + const delta = elapsed1 - elapsed0; + + console.log( + `⏱️ AFTER | Epoch #${currentEpoch}: ` + + `${elapsed1.toString()}s elapsed / ${epochLen.toString()}s (${pct1}%)`, + ); + console.log( + `🕑 Δ during tx: ${delta.toString()}s (${Number((delta * 100n) / epochLen)}%)`, + ); + + /* ---------- metadata sanity ---------- */ + const meta = + await KnowledgeCollectionStorage.getKnowledgeCollectionMetadata(1); + expect(meta[4]).to.equal(currentEpoch); + expect(meta[5]).to.equal(currentEpoch + numberOfEpochs); + expect(meta[6]).to.equal(tokenAmount); + + /* ---------- expected distribution ---------- */ + const basePer = tokenAmount / numberOfEpochs; + const curPart = (basePer * timeLeft1) / epochLen; + let tailPart = basePer - curPart; + const fullCnt = numberOfEpochs - 1n; + const alloc = curPart + basePer * fullCnt + tailPart; + if (alloc < tokenAmount) tailPart += tokenAmount - alloc; + + console.log('\n🧮 Expected token split'); + console.table({ + 'current (fraction)': curPart.toString(), + 'full per epoch': basePer.toString(), + 'tail (fraction)': tailPart.toString(), + 'sum check': (curPart + basePer * fullCnt + tailPart).toString(), + }); + + /* ---------- on-chain pools & assertions ---------- */ + const pools: bigint[] = []; + for (let i = 0n; i <= numberOfEpochs; i++) { + const ep = currentEpoch + i; + const p = await EpochStorage.getEpochPool(1, ep); + pools.push(p); + console.log(`epoch ${ep} ➜ ${p.toString()}`); + } + + // current epoch + expect(pools[0]).to.equal(curPart); - expect(metadata[0][0].length).to.equal(receivingNodesIdentityIds.length); // merkle roots - expect(metadata[1].length).to.equal(0); // burned - expect(metadata[2]).to.equal(10); // minted - expect(metadata[3]).to.equal(1000); // byteSize - expect(metadata[4]).to.equal(2); // startEpoch - expect(metadata[5]).to.equal(4); // endEpoch - expect(metadata[6]).to.equal(ethers.parseEther('100')); // tokenAmount - expect(metadata[7]).to.equal(false); // isImmutable + // full middle epochs + for (let i = 1; i < Number(numberOfEpochs); i++) { + expect(pools[i]).to.equal(basePer); + } + + // final fractional + expect(pools[Number(numberOfEpochs)]).to.equal(tailPart); + + // beyond final + expect( + await EpochStorage.getEpochPool(1, currentEpoch + numberOfEpochs + 1n), + ).to.equal(0); + + // sum check + const total = pools.reduce((a, v) => a + v, 0n); + expect(total).to.equal(tokenAmount); }); it('Should revert if insufficient signatures provided', async () => { @@ -240,4 +316,253 @@ describe('@unit KnowledgeCollection', () => { 'MinSignaturesRequirementNotMet', ); }); + + it('Should create KC at ~half-epoch mark and distribute tokens correctly', async () => { + /* ---------- actors ---------- */ + const kcCreator = getDefaultKCCreator(accounts); + const publishingNode = getDefaultPublishingNode(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); + const contracts = { Profile, KnowledgeCollection, Token }; + + const { identityId: pubNodeId } = await createProfile( + Profile, + publishingNode, + ); + const recvIds = (await createProfiles(Profile, receivingNodes)).map( + (p) => p.identityId, + ); + + /* ---------- params ---------- */ + const tokenAmount = ethers.parseEther('50'); + const numberOfEpochs = 3n; + const merkleRoot = kcTools.calculateMerkleRoot( + [' .'], + 32, + ); + + /* ---------- warp EVM to ~50 % of next epoch ---------- */ + const epochLen = await Chronos.epochLength(); // bigint + const timeLeftInit = await Chronos.timeUntilNextEpoch(); // bigint + + // Δ = remaining-to-end + half epoch + const delta = timeLeftInit + epochLen / 2n; + await hre.ethers.provider.send('evm_increaseTime', [Number(delta)]); + await hre.ethers.provider.send('evm_mine', []); // mine new block + + /* ---------- telemetry just before tx ---------- */ + const currentEpoch = await Chronos.getCurrentEpoch(); + const timeLeft0 = await Chronos.timeUntilNextEpoch(); + const elapsed0 = epochLen - timeLeft0; + console.log( + `\n⏱️ HALF-EPOCH TEST | Epoch #${currentEpoch}: ` + + `${elapsed0.toString()}s elapsed of ${epochLen.toString()}s ` + + `(~${Number((elapsed0 * 100n) / epochLen)}%)`, + ); + + /* ---------- create KC ---------- */ + const { collectionId } = await createKnowledgeCollection( + kcCreator, + publishingNode, + pubNodeId, + receivingNodes, + recvIds, + contracts, + merkleRoot, + 'half-epoch-op', + 5, // knowledgeAssetsAmount + 500, // byteSize + Number(numberOfEpochs), + tokenAmount, + false, + ethers.ZeroAddress, + ); + expect(collectionId).to.equal(1); + + /* ---------- compute expected parts (use on-chain timeLeft1) ---------- */ + const timeLeft1 = await Chronos.timeUntilNextEpoch(); + const basePer = tokenAmount / numberOfEpochs; + const curPart = (basePer * timeLeft1) / epochLen; + let tailPart = basePer - curPart; + const fullCnt = numberOfEpochs - 1n; + const alloc = curPart + basePer * fullCnt + tailPart; + if (alloc < tokenAmount) tailPart += tokenAmount - alloc; // crumbs + + console.log('\n🧮 Expected split (half-epoch)'); + console.table({ + 'current (fraction)': curPart.toString(), + 'full per epoch': basePer.toString(), + 'tail (fraction)': tailPart.toString(), + }); + + /* ---------- fetch pools ---------- */ + const pools: bigint[] = []; + for (let i = 0n; i <= numberOfEpochs; i++) { + pools.push(await EpochStorage.getEpochPool(1, currentEpoch + i)); + } + pools.forEach((v, i) => + console.log(`epoch ${currentEpoch + BigInt(i)} ➜ ${v.toString()}`), + ); + + /* ---------- assertions ---------- */ + expect(pools[0]).to.equal(curPart); // fractional start + for (let i = 1; i < Number(numberOfEpochs); i++) + expect(pools[i]).to.equal(basePer); // full middles + expect(pools[Number(numberOfEpochs)]).to.equal(tailPart); // fractional end + expect( + await EpochStorage.getEpochPool(1, currentEpoch + numberOfEpochs + 1n), + ).to.equal(0); // nothing beyond + + const sum = pools.reduce((a, v) => a + v, 0n); + expect(sum).to.equal(tokenAmount); // total check + }); + + /* =================================================================== */ + /* 1️⃣ REVERT-PATH: amount *too low* */ + /* =================================================================== */ + it('Should revert when tokenAmount is lower than _validateTokenAmount expects', async () => { + /* ---------- Test-local parameters ---------- */ + const askPerEpoch = ethers.parseEther('20'); // 20 TRAC/epoch + const totalStake = ethers.parseEther('1'); // 1 TRAC stake + await AskStorage.setWeightedActiveAskSum(askPerEpoch * totalStake); + await AskStorage.setTotalActiveStake(totalStake); + + const byteSize = 1024; // 1 KiB + const epochs = 5; + const needTokens = ethers.parseEther('100'); // 20 × 5 + const fewTokens = ethers.parseEther('99'); // deliberately low + + /* ---------- Actors & signatures ---------- */ + const kcCreator = getDefaultKCCreator(accounts); + const publishingNode = getDefaultPublishingNode(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); + + const { identityId: publisherId } = await createProfile( + Profile, + publishingNode, + ); + const receiverIds = (await createProfiles(Profile, receivingNodes)).map( + (p) => p.identityId, + ); + + const sig = await getKCSignaturesData( + publishingNode, + publisherId, + receivingNodes, + ); + + await Token.connect(kcCreator).increaseAllowance( + KnowledgeCollection.getAddress(), + needTokens, + ); + + /* ---------- DEBUG OUTPUT ---------- */ + console.log('\n🔎 [REVERT-TEST] Validation parameters'); + console.log( + ` stakeWeightedAverageAsk : ${ethers.formatEther(askPerEpoch)} TRAC/epoch`, + ); + console.log(` byteSize : ${byteSize} bytes`); + console.log(` epochs : ${epochs}`); + console.log( + ` required tokenAmount : ${ethers.formatEther(needTokens)} TRAC`, + ); + console.log( + ` provided tokenAmount : ${ethers.formatEther(fewTokens)} TRAC (expected to FAIL)`, + ); + + /* ---------- Expect revert ---------- */ + await expect( + KnowledgeCollection.connect(kcCreator).createKnowledgeCollection( + 'validate-fail', + sig.merkleRoot, + 1, + byteSize, + epochs, + fewTokens, // below requirement + false, + ethers.ZeroAddress, + publisherId, + sig.publisherR, + sig.publisherVS, + receiverIds, + sig.receiverRs, + sig.receiverVSs, + ), + ).to.be.revertedWithCustomError(KnowledgeCollection, 'InvalidTokenAmount'); + }); + + /* =================================================================== */ + /* 2️⃣ SUCCESS-PATH: amount equals requirement – should pass */ + /* =================================================================== */ + it('Should create KC when tokenAmount equals the required minimum', async () => { + /* ---------- Test-local parameters ---------- */ + const askPerEpoch = ethers.parseEther('20'); // 20 TRAC/epoch + const totalStake = ethers.parseEther('1'); // 1 TRAC stake + await AskStorage.setWeightedActiveAskSum(askPerEpoch * totalStake); + await AskStorage.setTotalActiveStake(totalStake); + + const byteSize = 1024; // 1 KiB + const epochs = 5; + const exactTokens = ethers.parseEther('100'); // 20 × 5 + + /* ---------- Actors & signatures ---------- */ + const kcCreator = getDefaultKCCreator(accounts); + const publishingNode = getDefaultPublishingNode(accounts); + const receivingNodes = getDefaultReceivingNodes(accounts); + + const { identityId: publisherId } = await createProfile( + Profile, + publishingNode, + ); + const receiverIds = (await createProfiles(Profile, receivingNodes)).map( + (p) => p.identityId, + ); + + const sig = await getKCSignaturesData( + publishingNode, + publisherId, + receivingNodes, + ); + + await Token.connect(kcCreator).increaseAllowance( + KnowledgeCollection.getAddress(), + exactTokens, + ); + + /* ---------- DEBUG OUTPUT ---------- */ + console.log('\n🔎 [SUCCESS-TEST] Validation parameters'); + console.log( + ` stakeWeightedAverageAsk : ${ethers.formatEther(askPerEpoch)} TRAC/epoch`, + ); + console.log(` byteSize : ${byteSize} bytes`); + console.log(` epochs : ${epochs}`); + console.log( + ` required tokenAmount : ${ethers.formatEther(exactTokens)} TRAC`, + ); + console.log( + ` provided tokenAmount : ${ethers.formatEther(exactTokens)} TRAC (expected to PASS)`, + ); + + /* ---------- Expect NO revert ---------- */ + const tx = await KnowledgeCollection.connect( + kcCreator, + ).createKnowledgeCollection( + 'validate-pass', + sig.merkleRoot, + 1, + byteSize, + epochs, + exactTokens, // exactly the minimum + false, + ethers.ZeroAddress, + publisherId, + sig.publisherR, + sig.publisherVS, + receiverIds, + sig.receiverRs, + sig.receiverVSs, + ); + + const receipt = await tx.wait(); + console.log(` ✅ KC created – tx hash: ${receipt?.hash}`); + }); }); diff --git a/test/unit/RandomSampling.test.ts b/test/unit/RandomSampling.test.ts new file mode 100644 index 00000000..b648574d --- /dev/null +++ b/test/unit/RandomSampling.test.ts @@ -0,0 +1,770 @@ +import { SignerWithAddress } from '@nomicfoundation/hardhat-ethers/signers'; +import { loadFixture, time } from '@nomicfoundation/hardhat-network-helpers'; +import { expect } from 'chai'; +import hre from 'hardhat'; + +import { + mineBlocks, + mineProofPeriodBlocks, +} from '../../test/helpers/blockchain-helpers'; +import { + Hub, + RandomSampling, + HubLib, + Chronos, + RandomSamplingStorage, + IdentityStorage, + StakingStorage, + ProfileStorage, + AskStorage, + EpochStorage, + ParametersStorage, + KnowledgeCollectionStorage, + Profile, +} from '../../typechain'; + +type RandomSamplingFixture = { + accounts: SignerWithAddress[]; + RandomSampling: RandomSampling; + Hub: Hub; + HubLib: HubLib; + Chronos: Chronos; + RandomSamplingStorage: RandomSamplingStorage; + IdentityStorage: IdentityStorage; + StakingStorage: StakingStorage; + ProfileStorage: ProfileStorage; + AskStorage: AskStorage; + EpochStorage: EpochStorage; + ParametersStorage: ParametersStorage; + KnowledgeCollectionStorage: KnowledgeCollectionStorage; + Profile: Profile; +}; + +const PANIC_ARITHMETIC_OVERFLOW = 0x11; + +describe('@unit RandomSampling', () => { + let accounts: SignerWithAddress[]; + let RandomSampling: RandomSampling; + let Hub: Hub; + let HubLib: HubLib; + let Chronos: Chronos; + let RandomSamplingStorage: RandomSamplingStorage; + let IdentityStorage: IdentityStorage; + let StakingStorage: StakingStorage; + let ProfileStorage: ProfileStorage; + let AskStorage: AskStorage; + let EpochStorage: EpochStorage; + let ParametersStorage: ParametersStorage; + let KnowledgeCollectionStorage: KnowledgeCollectionStorage; + let Profile: Profile; + + async function deployRandomSamplingFixture(): Promise { + await hre.deployments.fixture([ + 'Token', + 'Hub', + 'ParametersStorage', + 'WhitelistStorage', + 'IdentityStorage', + 'ShardingTableStorage', + 'StakingStorage', + 'ProfileStorage', + 'Chronos', + 'EpochStorage', + 'KnowledgeCollectionStorage', + 'AskStorage', + 'DelegatorsInfo', + 'RandomSamplingStorage', + 'RandomSampling', + 'Profile', + ]); + accounts = await hre.ethers.getSigners(); + Hub = await hre.ethers.getContract('Hub'); + await Hub.setContractAddress('HubOwner', accounts[0].address); + + const hubLibDeployment = await hre.deployments.deploy('HubLib', { + from: accounts[0].address, + log: true, + }); + HubLib = await hre.ethers.getContract( + 'HubLib', + hubLibDeployment.address, + ); + + Chronos = await hre.ethers.getContract('Chronos'); + RandomSamplingStorage = await hre.ethers.getContract( + 'RandomSamplingStorage', + ); + RandomSampling = + await hre.ethers.getContract('RandomSampling'); + IdentityStorage = + await hre.ethers.getContract('IdentityStorage'); + StakingStorage = + await hre.ethers.getContract('StakingStorage'); + ProfileStorage = + await hre.ethers.getContract('ProfileStorage'); + AskStorage = await hre.ethers.getContract('AskStorage'); + EpochStorage = await hre.ethers.getContract('EpochStorageV8'); + ParametersStorage = + await hre.ethers.getContract('ParametersStorage'); + KnowledgeCollectionStorage = + await hre.ethers.getContract( + 'KnowledgeCollectionStorage', + ); + Profile = await hre.ethers.getContract('Profile'); + + return { + accounts, + RandomSampling, + Hub, + HubLib, + Chronos, + RandomSamplingStorage, + IdentityStorage, + StakingStorage, + ProfileStorage, + AskStorage, + EpochStorage, + ParametersStorage, + KnowledgeCollectionStorage, + Profile, + }; + } + + async function updateAndGetActiveProofPeriod() { + const tx = await RandomSampling.updateAndGetActiveProofPeriodStartBlock(); + await tx.wait(); + return await RandomSampling.getActiveProofPeriodStatus(); + } + + beforeEach(async () => { + ({ + accounts, + RandomSampling, + Hub, + HubLib, + Chronos, + RandomSamplingStorage, + IdentityStorage, + StakingStorage, + ProfileStorage, + AskStorage, + EpochStorage, + ParametersStorage, + KnowledgeCollectionStorage, + Profile, + } = await loadFixture(deployRandomSamplingFixture)); + }); + + describe('constructor', () => { + it('Should set correct Hub reference', async () => { + const hubAddress = await RandomSampling.hub(); + expect(hubAddress).to.equal(Hub.target); + }); + }); + + describe('initialize()', () => { + it('Should initialize all contract references correctly', async () => { + // Deploy new instance to test initialization + const RandomSamplingFactory = + await hre.ethers.getContractFactory('RandomSampling'); + const newRandomSampling = await RandomSamplingFactory.deploy(Hub.target); + + await newRandomSampling.initialize(); + + // Verify all storage references are set + expect(await newRandomSampling.identityStorage()).to.equal( + await IdentityStorage.getAddress(), + ); + expect(await newRandomSampling.randomSamplingStorage()).to.equal( + await RandomSamplingStorage.getAddress(), + ); + expect(await newRandomSampling.stakingStorage()).to.equal( + await StakingStorage.getAddress(), + ); + expect(await newRandomSampling.profileStorage()).to.equal( + await ProfileStorage.getAddress(), + ); + expect(await newRandomSampling.askStorage()).to.equal( + await AskStorage.getAddress(), + ); + expect(await newRandomSampling.chronos()).to.equal( + await Chronos.getAddress(), + ); + expect(await newRandomSampling.parametersStorage()).to.equal( + await ParametersStorage.getAddress(), + ); + }); + + it('Should revert if not called by Hub', async () => { + const RandomSamplingFactory = + await hre.ethers.getContractFactory('RandomSampling'); + const newRandomSampling = await RandomSamplingFactory.deploy(Hub.target); + + await expect(newRandomSampling.connect(accounts[1]).initialize()) + .to.be.revertedWithCustomError(newRandomSampling, 'UnauthorizedAccess') + .withArgs('Only Hub'); + }); + }); + + describe('name()', () => { + it('Should return correct name', async () => { + expect(await RandomSampling.name()).to.equal('RandomSampling'); + }); + }); + + describe('version()', () => { + it('Should return correct version', async () => { + expect(await RandomSampling.version()).to.equal('1.0.0'); + }); + }); + + describe('isPendingProofingPeriodDuration()', () => { + it('Should return false when no pending duration', async () => { + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + expect(await RandomSampling.isPendingProofingPeriodDuration()).to.be + .false; + }); + + it('Should return true when pending duration exists', async () => { + await RandomSampling.setProofingPeriodDurationInBlocks(200); + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + expect(await RandomSampling.isPendingProofingPeriodDuration()).to.be.true; + }); + + it('Should return false after pending duration becomes active', async () => { + await RandomSampling.setProofingPeriodDurationInBlocks(200); + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + expect(await RandomSampling.isPendingProofingPeriodDuration()).to.be.true; + + // Move to next epoch + const epochLength = await Chronos.epochLength(); + await time.increase(Number(epochLength)); + + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + expect(await RandomSampling.isPendingProofingPeriodDuration()).to.be + .false; + }); + }); + + describe('setProofingPeriodDurationInBlocks()', () => { + it('Should revert if durationInBlocks is 0', async () => { + await expect( + RandomSampling.setProofingPeriodDurationInBlocks(0), + ).to.be.revertedWith('Duration in blocks must be greater than 0'); + }); + + it('Should add new duration when no pending duration exists', async () => { + const newDuration = 200; + const initialLength = + await RandomSamplingStorage.getProofingPeriodDurationsLength(); + + await RandomSampling.setProofingPeriodDurationInBlocks(newDuration); + + const finalLength = + await RandomSamplingStorage.getProofingPeriodDurationsLength(); + expect(finalLength).to.equal(initialLength + 1n); + + const latestDuration = + await RandomSamplingStorage.getLatestProofingPeriodDurationInBlocks(); + expect(latestDuration).to.equal(newDuration); + }); + + it('Should replace pending duration when pending duration exists', async () => { + const firstDuration = 200; + const secondDuration = 300; + + // Add first duration + await RandomSampling.setProofingPeriodDurationInBlocks(firstDuration); + const lengthAfterFirst = + await RandomSamplingStorage.getProofingPeriodDurationsLength(); + + // Add second duration (should replace) + await RandomSampling.setProofingPeriodDurationInBlocks(secondDuration); + const lengthAfterSecond = + await RandomSamplingStorage.getProofingPeriodDurationsLength(); + + // Length should be same (replacement, not addition) + expect(lengthAfterSecond).to.equal(lengthAfterFirst); + + const latestDuration = + await RandomSamplingStorage.getLatestProofingPeriodDurationInBlocks(); + expect(latestDuration).to.equal(secondDuration); + }); + + it('Should set effective epoch to current epoch + 1', async () => { + const currentEpoch = await Chronos.getCurrentEpoch(); + await RandomSampling.setProofingPeriodDurationInBlocks(200); + + const latestEffectiveEpoch = + await RandomSamplingStorage.getLatestProofingPeriodDurationEffectiveEpoch(); + expect(latestEffectiveEpoch).to.equal(currentEpoch + 1n); + }); + + // TODO: Test access control when multisig is properly set up + // it('Should revert if called by non-owner', async () => { + // await expect( + // RandomSampling.connect(accounts[1]).setProofingPeriodDurationInBlocks(100) + // ).to.be.revertedWithCustomError(HubLib, 'UnauthorizedAccess') + // .withArgs('Only Hub Owner or Multisig Owner'); + // }); + }); + + describe('Access Control Modifiers', () => { + it('Should revert createChallenge if profile does not exist', async () => { + await expect( + RandomSampling.connect(accounts[5]).createChallenge(), + ).to.be.revertedWithCustomError(RandomSampling, 'ProfileDoesntExist'); + }); + + it('Should revert submitProof if profile does not exist', async () => { + await expect( + RandomSampling.connect(accounts[5]).submitProof('chunk', []), + ).to.be.revertedWithCustomError(RandomSampling, 'ProfileDoesntExist'); + }); + }); + + describe('Constants and Public Variables', () => { + it('Should have correct SCALE18 constant', async () => { + expect(await RandomSampling.SCALE18()).to.equal(1000000000000000000n); + }); + + it('Should have initialized storage contract references', async () => { + // Verify that contract references are properly initialized + expect(await RandomSampling.identityStorage()).to.equal( + await IdentityStorage.getAddress(), + ); + expect(await RandomSampling.randomSamplingStorage()).to.equal( + await RandomSamplingStorage.getAddress(), + ); + expect(await RandomSampling.stakingStorage()).to.equal( + await StakingStorage.getAddress(), + ); + expect(await RandomSampling.profileStorage()).to.equal( + await ProfileStorage.getAddress(), + ); + expect(await RandomSampling.askStorage()).to.equal( + await AskStorage.getAddress(), + ); + expect(await RandomSampling.chronos()).to.equal( + await Chronos.getAddress(), + ); + expect(await RandomSampling.parametersStorage()).to.equal( + await ParametersStorage.getAddress(), + ); + expect(await RandomSampling.knowledgeCollectionStorage()).to.equal( + await KnowledgeCollectionStorage.getAddress(), + ); + }); + }); + + // Fails because the hubOwner is not a multisig, but an individual account + describe('setProofingPeriodDurationInBlocks()', () => { + it('Should revert if durationInBlocks is 0', async () => { + await expect( + RandomSampling.setProofingPeriodDurationInBlocks(0), + ).to.be.revertedWith('Duration in blocks must be greater than 0'); + }); + + // // TODO: This test fails because the hub owner is not the multisig owner + // it('Should revert if called by non-contract', async () => { + // await expect( + // RandomSampling.connect(accounts[1]).setProofingPeriodDurationInBlocks( + // 100, + // ), + // ) + // .to.be.revertedWithCustomError(HubLib, 'UnauthorizedAccess') + // .withArgs('Only Hub Owner or Multisig Owner'); + // }); + }); + + describe('Proofing Period Management', () => { + it('Should return the correct proofing period status', async () => { + const { activeProofPeriodStartBlock } = + await updateAndGetActiveProofPeriod(); + const duration = + await RandomSampling.getActiveProofingPeriodDurationInBlocks(); + + // Initial check + const status = await RandomSampling.getActiveProofPeriodStatus(); + expect(status.activeProofPeriodStartBlock).to.be.a('bigint'); + expect(status.isValid).to.be.a('boolean'); + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + expect(status.isValid).to.be.true; + + // Test at middle of period + const middleBlock = activeProofPeriodStartBlock + duration / 2n; + await mineBlocks( + Number( + middleBlock - BigInt(await hre.ethers.provider.getBlockNumber()), + ), + ); + const middleStatus = await RandomSampling.getActiveProofPeriodStatus(); + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + expect(middleStatus.isValid).to.be.true; + + // Test at end of period + const endBlock = activeProofPeriodStartBlock + duration - 1n; + await mineBlocks( + Number(endBlock - BigInt(await hre.ethers.provider.getBlockNumber())), + ); + const endStatus = await RandomSampling.getActiveProofPeriodStatus(); + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + expect(endStatus.isValid).to.be.true; + + // Test after period ends + await mineBlocks(1); + const afterStatus = await RandomSampling.getActiveProofPeriodStatus(); + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + expect(afterStatus.isValid).to.be.false; + }); + + it('Should update start block correctly for different period scenarios', async () => { + // Test when no period has passed + const { activeProofPeriodStartBlock: initialBlock } = + await updateAndGetActiveProofPeriod(); + const statusNoPeriod = await RandomSampling.getActiveProofPeriodStatus(); + expect(statusNoPeriod.activeProofPeriodStartBlock).to.equal(initialBlock); + + // Test when 1 full period has passed + const duration = + await RandomSampling.getActiveProofingPeriodDurationInBlocks(); + await mineBlocks(Number(duration)); + const { activeProofPeriodStartBlock: onePeriodBlock } = + await updateAndGetActiveProofPeriod(); + expect(onePeriodBlock).to.equal(initialBlock + duration); + + // Test when 2 full periods have passed + await mineBlocks(Number(duration)); + const { activeProofPeriodStartBlock: twoPeriodBlock } = + await updateAndGetActiveProofPeriod(); + expect(twoPeriodBlock).to.equal(initialBlock + duration * 2n); + + // Test when n full periods have passed (using n=5 as example) + const n = 5; + for (let i = 0; i < n - 2; i++) { + await mineBlocks(Number(duration)); + } + const { activeProofPeriodStartBlock: nPeriodBlock } = + await updateAndGetActiveProofPeriod(); + expect(nPeriodBlock).to.equal(initialBlock + duration * BigInt(n)); + }); + + it('Should return correct historical proofing period start', async () => { + const { activeProofPeriodStartBlock } = + await updateAndGetActiveProofPeriod(); + const duration = + await RandomSampling.getActiveProofingPeriodDurationInBlocks(); + + // Test invalid inputs + await expect( + RandomSampling.getHistoricalProofPeriodStartBlock(0, 1), + ).to.be.revertedWith('Proof period start block must be greater than 0'); + + await expect( + RandomSampling.getHistoricalProofPeriodStartBlock(100, 0), + ).to.be.revertedWith('Offset must be greater than 0'); + + await expect( + RandomSampling.getHistoricalProofPeriodStartBlock( + activeProofPeriodStartBlock + 10n, + 1, + ), + ).to.be.revertedWith('Proof period start block is not valid'); + + await expect( + RandomSampling.getHistoricalProofPeriodStartBlock( + activeProofPeriodStartBlock, + 999, + ), + ).to.be.revertedWithPanic(PANIC_ARITHMETIC_OVERFLOW); + + // Test valid historical blocks + await mineProofPeriodBlocks(RandomSampling); + const { activeProofPeriodStartBlock: newPeriodStartBlock } = + await updateAndGetActiveProofPeriod(); + + // Test offset 1 + const onePeriodBack = + await RandomSampling.getHistoricalProofPeriodStartBlock( + newPeriodStartBlock, + 1, + ); + expect(onePeriodBack).to.equal(newPeriodStartBlock - duration); + + // Test offset 2 + const twoPeriodsBack = + await RandomSampling.getHistoricalProofPeriodStartBlock( + newPeriodStartBlock, + 2, + ); + expect(twoPeriodsBack).to.equal(newPeriodStartBlock - duration * 2n); + + // Test offset 3 + const threePeriodsBack = + await RandomSampling.getHistoricalProofPeriodStartBlock( + newPeriodStartBlock, + 3, + ); + expect(threePeriodsBack).to.equal(newPeriodStartBlock - duration * 3n); + + // Test that returned block is aligned with period start + expect(threePeriodsBack % duration).to.equal( + 0n, + 'Historical block should be aligned with period start', + ); + }); + + it('Should return correct active proof period', async () => { + const { activeProofPeriodStartBlock, isValid } = + await updateAndGetActiveProofPeriod(); + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + expect(isValid).to.be.equal(true, 'Period should be valid'); + + // Mine blocks up to the last block of the current period + const currentBlock = await hre.ethers.provider.getBlockNumber(); + const blocksToMine = + Number(activeProofPeriodStartBlock) + + Number(await RandomSampling.getActiveProofingPeriodDurationInBlocks()) - + currentBlock - + 1; + await mineBlocks(blocksToMine); + + let statusAfterUpdate = await RandomSampling.getActiveProofPeriodStatus(); + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + expect(statusAfterUpdate.isValid).to.be.equal( + true, + 'Period should still be valid', + ); + + // Mine one more block to reach the end of the period + await mineBlocks(1); + statusAfterUpdate = await RandomSampling.getActiveProofPeriodStatus(); + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + expect(statusAfterUpdate.isValid).to.be.equal( + false, + 'Period should not be valid', + ); + + // Update the period and mine blocks for the new period + await updateAndGetActiveProofPeriod(); + const newStatus = await RandomSampling.getActiveProofPeriodStatus(); + const blocksToMineNew = + Number(newStatus.activeProofPeriodStartBlock) + + Number(await RandomSampling.getActiveProofingPeriodDurationInBlocks()) - + (await hre.ethers.provider.getBlockNumber()) - + 1; + await mineBlocks(blocksToMineNew); + + statusAfterUpdate = await RandomSampling.getActiveProofPeriodStatus(); + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + expect(statusAfterUpdate.isValid).to.be.equal( + true, + 'New period should be valid', + ); + }); + + it('Should pick correct proofing period duration based on epoch', async () => { + const initialDuration = + await RandomSampling.getActiveProofingPeriodDurationInBlocks(); + const epochLength = await Chronos.epochLength(); + + // Test initial duration + expect(initialDuration).to.equal( + BigInt(await RandomSampling.getActiveProofingPeriodDurationInBlocks()), + ); + + // Test duration in middle of epoch + await time.increase(Number(epochLength) / 2); + const midEpochDuration = + await RandomSampling.getActiveProofingPeriodDurationInBlocks(); + expect(midEpochDuration).to.equal( + initialDuration, + 'Duration should not change mid-epoch', + ); + + // Set new duration for next epoch + const newDuration = 1000; + await RandomSampling.setProofingPeriodDurationInBlocks(newDuration); + + // Verify duration hasn't changed yet + const beforeEpochEndDuration = + await RandomSampling.getActiveProofingPeriodDurationInBlocks(); + expect(beforeEpochEndDuration).to.equal( + initialDuration, + 'Duration should not change before epoch end', + ); + + // Move to next epoch + await time.increase(Number(epochLength) + 1); + const nextEpochDuration = + await RandomSampling.getActiveProofingPeriodDurationInBlocks(); + expect(nextEpochDuration).to.equal( + BigInt(newDuration), + 'Duration should change in next epoch', + ); + + // Set another duration for future epoch + const futureDuration = 2000; + await RandomSampling.setProofingPeriodDurationInBlocks(futureDuration); + + // Verify current epoch still has previous duration + const currentEpochDuration = + await RandomSampling.getActiveProofingPeriodDurationInBlocks(); + expect(currentEpochDuration).to.equal( + BigInt(newDuration), + 'Current epoch should keep previous duration', + ); + + // Move to future epoch + await time.increase(Number(epochLength)); + const futureEpochDuration = + await RandomSampling.getActiveProofingPeriodDurationInBlocks(); + expect(futureEpochDuration).to.equal( + BigInt(futureDuration), + 'Future epoch should have new duration', + ); + }); + + it('Should return correct proofing period duration based on epoch history', async () => { + const baseDuration = 100; + const testEpochs = 5; + const currentEpoch = await Chronos.getCurrentEpoch(); + const epochLength = await Chronos.epochLength(); + + // Set up multiple durations with different effective epochs + const durations = []; + for (let i = 0; i < testEpochs; i++) { + const duration = baseDuration + i * 100; + durations.push(duration); + + await RandomSampling.setProofingPeriodDurationInBlocks(duration); + + await time.increase(Number(epochLength)); + } + + const finalEpoch = await Chronos.getCurrentEpoch(); + expect(finalEpoch).to.equal(currentEpoch + BigInt(testEpochs)); + + // Test invalid epoch (before first duration) + await expect( + RandomSamplingStorage.getEpochProofingPeriodDurationInBlocks( + currentEpoch - 1n, + ), + ).to.be.revertedWith('No applicable duration found'); + + // Test each epoch's duration + for (let i = 0; i < testEpochs; i++) { + const targetEpoch = finalEpoch - BigInt(i); + const expectedDuration = durations[testEpochs - 1 - i]; + + const actual = + await RandomSamplingStorage.getEpochProofingPeriodDurationInBlocks( + targetEpoch, + ); + expect(actual).to.equal( + expectedDuration, + `Epoch ${targetEpoch} should have duration ${expectedDuration}`, + ); + } + + // Test edge case - current epoch + const currentEpochDuration = + await RandomSamplingStorage.getEpochProofingPeriodDurationInBlocks( + finalEpoch, + ); + expect(currentEpochDuration).to.equal( + durations[durations.length - 1], + 'Current epoch should have the latest duration', + ); + + // Test edge case - first epoch with duration + const firstEpochWithDuration = currentEpoch; + const firstEpochDuration = + await RandomSamplingStorage.getEpochProofingPeriodDurationInBlocks( + firstEpochWithDuration, + ); + expect(firstEpochDuration).to.equal( + durations[0], + 'First epoch should have the first duration', + ); + }); + + it('Should return same block when no period has passed', async () => { + const { activeProofPeriodStartBlock: initialBlock } = + await updateAndGetActiveProofPeriod(); + + // Mine blocks up to the last block of the current period + const currentBlock = await hre.ethers.provider.getBlockNumber(); + const blocksToMine = + Number(initialBlock) + + Number(await RandomSampling.getActiveProofingPeriodDurationInBlocks()) - + currentBlock - + 2; + await mineBlocks(blocksToMine); + + const tx = await RandomSampling.updateAndGetActiveProofPeriodStartBlock(); + await tx.wait(); + const { activeProofPeriodStartBlock: newBlock } = + await RandomSampling.getActiveProofPeriodStatus(); + + // Should return the same block since we haven't reached the end of the period + expect(newBlock).to.equal(initialBlock); + + // Mine one more block to reach the end of the period + await mineBlocks(1); + + const tx2 = + await RandomSampling.updateAndGetActiveProofPeriodStartBlock(); + await tx2.wait(); + const { activeProofPeriodStartBlock: finalBlock } = + await RandomSampling.getActiveProofPeriodStatus(); + + // Should update the block since we've reached the end of the period + expect(finalBlock).to.be.greaterThan(initialBlock); + }); + + it('Should return correct status for different block numbers', async () => { + const { activeProofPeriodStartBlock } = + await updateAndGetActiveProofPeriod(); + const duration = + await RandomSampling.getActiveProofingPeriodDurationInBlocks(); + + // Test at start block + const statusAtStart = await RandomSampling.getActiveProofPeriodStatus(); + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + expect(statusAtStart.isValid).to.be.true; + expect(statusAtStart.activeProofPeriodStartBlock).to.equal( + activeProofPeriodStartBlock, + ); + + // Test at middle block + const middleBlock = activeProofPeriodStartBlock + duration / 2n; + await mineBlocks( + Number( + middleBlock - BigInt(await hre.ethers.provider.getBlockNumber()), + ), + ); + const statusAtMiddle = await RandomSampling.getActiveProofPeriodStatus(); + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + expect(statusAtMiddle.isValid).to.be.true; + + // Test at last valid block + const lastValidBlock = activeProofPeriodStartBlock + duration - 1n; + await mineBlocks( + Number( + lastValidBlock - BigInt(await hre.ethers.provider.getBlockNumber()), + ), + ); + const statusAtLastValid = + await RandomSampling.getActiveProofPeriodStatus(); + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + expect(statusAtLastValid.isValid).to.be.true; + + // Test at first invalid block + await mineBlocks(1); + const statusAtInvalid = await RandomSampling.getActiveProofPeriodStatus(); + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + expect(statusAtInvalid.isValid).to.be.false; + }); + }); +}); diff --git a/test/unit/RandomSamplingStorage.test.ts b/test/unit/RandomSamplingStorage.test.ts new file mode 100644 index 00000000..eae8143d --- /dev/null +++ b/test/unit/RandomSamplingStorage.test.ts @@ -0,0 +1,2206 @@ +import { SignerWithAddress } from '@nomicfoundation/hardhat-ethers/signers'; +import { loadFixture, time } from '@nomicfoundation/hardhat-network-helpers'; +import { expect } from 'chai'; +import { EventLog } from 'ethers'; +import hre, { ethers } from 'hardhat'; + +import parameters from '../../deployments/parameters.json'; +import { + Hub, + RandomSamplingStorage, + Chronos, + KnowledgeCollectionStorage, + RandomSampling, +} from '../../typechain'; +import { RandomSamplingLib } from '../../typechain/contracts/storage/RandomSamplingStorage'; + +const HUNDRED_ETH = ethers.parseEther('100'); + +// Helper functions for random sampling +async function createMockChallenge( + randomSampling: RandomSampling, + knowledgeCollectionStorage: KnowledgeCollectionStorage, + chronos: Chronos, +): Promise { + const currentEpoch = await chronos.getCurrentEpoch(); + await randomSampling.updateAndGetActiveProofPeriodStartBlock(); + const { activeProofPeriodStartBlock } = + await randomSampling.getActiveProofPeriodStatus(); + const proofingPeriodDuration = + await randomSampling.getActiveProofingPeriodDurationInBlocks(); + + return { + knowledgeCollectionId: 1n, + chunkId: 1n, + knowledgeCollectionStorageContract: + await knowledgeCollectionStorage.getAddress(), + epoch: currentEpoch, + activeProofPeriodStartBlock, + proofingPeriodDurationInBlocks: proofingPeriodDuration, + solved: false, + }; +} + +type RandomStorageFixture = { + accounts: SignerWithAddress[]; + RandomSamplingStorage: RandomSamplingStorage; + Hub: Hub; + Chronos: Chronos; + RandomSampling: RandomSampling; +}; + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +async function impersonateAndFund(contract: any) { + await hre.network.provider.request({ + method: 'hardhat_impersonateAccount', + params: [await contract.getAddress()], + }); + + await hre.network.provider.send('hardhat_setBalance', [ + await contract.getAddress(), + `0x${HUNDRED_ETH.toString(16)}`, + ]); +} + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +async function stopImpersonate(contract: any) { + await hre.network.provider.request({ + method: 'hardhat_stopImpersonatingAccount', + params: [await contract.getAddress()], + }); +} + +describe('@unit RandomSamplingStorage', function () { + let Hub: Hub; + let RandomSamplingStorage: RandomSamplingStorage; + let RandomSampling: RandomSampling; + let Chronos: Chronos; + let KnowledgeCollectionStorage: KnowledgeCollectionStorage; + let MockChallenge: RandomSamplingLib.ChallengeStruct; + let accounts: SignerWithAddress[]; + + const proofingPeriodDurationInBlocks = + parameters.development.RandomSamplingStorage.hardhat + .proofingPeriodDurationInBlocks; + const w1 = parameters.development.RandomSamplingStorage.hardhat.W1; + const w2 = parameters.development.RandomSamplingStorage.hardhat.W2; + + async function deployRandomSamplingFixture(): Promise { + await hre.deployments.fixture([ + 'Token', + 'ParanetKnowledgeCollectionsRegistry', + 'ParanetKnowledgeMinersRegistry', + 'KnowledgeCollectionStorage', + 'KnowledgeCollection', + 'RandomSamplingStorage', + 'RandomSampling', + 'ShardingTableStorage', + 'EpochStorage', + 'Profile', + ]); + + Hub = await hre.ethers.getContract('Hub'); + accounts = await ethers.getSigners(); + Chronos = await hre.ethers.getContract('Chronos'); + + // Use the deployed RandomSamplingStorage instance instead of creating a new one + RandomSamplingStorage = await hre.ethers.getContract( + 'RandomSamplingStorage', + ); + + RandomSampling = + await hre.ethers.getContract('RandomSampling'); + KnowledgeCollectionStorage = + await hre.ethers.getContract( + 'KnowledgeCollectionStorage', + ); + + await RandomSamplingStorage.initialize(); + await RandomSampling.initialize(); + + return { + accounts, + RandomSamplingStorage, + Hub, + Chronos, + RandomSampling, + }; + } + + // async function updateAndGetActiveProofPeriod() { + // const tx = + // await RandomSamplingStorage.updateAndGetActiveProofPeriodStartBlock(); + // await tx.wait(); + // return await RandomSamplingStorage.getActiveProofPeriodStatus(); + // } + + beforeEach(async () => { + hre.helpers.resetDeploymentsJson(); + ({ RandomSamplingStorage, Chronos, RandomSampling } = await loadFixture( + deployRandomSamplingFixture, + )); + + MockChallenge = await createMockChallenge( + RandomSampling, + KnowledgeCollectionStorage, + Chronos, + ); + }); + + describe('constructor', () => { + it('Should set correct initial values', async () => { + // Check initial values set in constructor + expect(await RandomSamplingStorage.hub()).to.equal(Hub.target); + expect( + await RandomSamplingStorage.getLatestProofingPeriodDurationInBlocks(), + ).to.equal(proofingPeriodDurationInBlocks); + expect(await RandomSamplingStorage.w1()).to.equal(w1); + expect(await RandomSamplingStorage.w2()).to.equal(w2); + }); + + it('Should revert if proofingPeriodDurationInBlocks is 0', async () => { + const RandomSamplingStorageFactory = await hre.ethers.getContractFactory( + 'RandomSamplingStorage', + ); + await expect( + RandomSamplingStorageFactory.deploy(Hub.target, 0, w1, w2), + ).to.be.revertedWith( + 'Proofing period duration in blocks must be greater than 0', + ); + }); + }); + + describe('setW1() and W1 getter', () => { + it('Should update W1 correctly and revert for non-owners', async () => { + // Test successful update by owner + const newW1 = hre.ethers.parseUnits('2', 18); + const oldW1 = await RandomSamplingStorage.w1(); + + const tx = await RandomSamplingStorage.setW1(newW1); + await tx.wait(); + + await expect(tx) + .to.emit(RandomSamplingStorage, 'W1Set') + .withArgs(oldW1, newW1); + + // Test getW1() function + expect(await RandomSamplingStorage.getW1()).to.equal(newW1); + + // // TODO: Fails because the hubOwner is not a multisig, but an individual account + // // Test revert for non-owner + // await expect(RandomSamplingStorage.connect(accounts[1]).setW1(newW1)) + // .to.be.revertedWithCustomError(RandomSampling, 'UnauthorizedAccess') + // .withArgs('Only Hub Owner'); + }); + }); + + describe('setW2() and W2 getter', () => { + it('Should update W2 correctly and revert for non-owners', async () => { + // Test successful update by owner + const newW2 = hre.ethers.parseUnits('3', 18); + const oldW2 = await RandomSamplingStorage.w2(); + + const tx = await RandomSamplingStorage.setW2(newW2); + await tx.wait(); + + await expect(tx) + .to.emit(RandomSamplingStorage, 'W2Set') + .withArgs(oldW2, newW2); + + // Test getW2() function + expect(await RandomSamplingStorage.getW2()).to.equal(newW2); + + // TODO: This test fails because the hubOwner is not a multisig, but an individual account + // await expect(RandomSamplingStorage.connect(accounts[1]).setW2(newW2)) + // .to.be.revertedWithCustomError(RandomSampling, 'UnauthorizedAccess') + // .withArgs('Only Hub Owner'); + }); + }); + + describe('Scoring System', () => { + it('Should increment and get epoch node valid proofs count', async () => { + const nodeId = 1n; + const currentEpoch = await Chronos.getCurrentEpoch(); + const epochLength = await Chronos.epochLength(); + + // Test initial state + const initialCount = + await RandomSamplingStorage.getEpochNodeValidProofsCount( + currentEpoch, + nodeId, + ); + expect(initialCount).to.equal(0n, 'Should start with 0 proofs'); + + // Test incrementing in current epoch + await RandomSamplingStorage.incrementEpochNodeValidProofsCount( + currentEpoch, + nodeId, + ); + const countAfterIncrement = + await RandomSamplingStorage.getEpochNodeValidProofsCount( + currentEpoch, + nodeId, + ); + expect(countAfterIncrement).to.equal(1n, 'Should increment to 1'); + + // Test multiple increments + await RandomSamplingStorage.incrementEpochNodeValidProofsCount( + currentEpoch, + nodeId, + ); + const countAfterMultiple = + await RandomSamplingStorage.getEpochNodeValidProofsCount( + currentEpoch, + nodeId, + ); + expect(countAfterMultiple).to.equal(2n, 'Should increment to 2'); + + // Move to next epoch properly + await time.increase(Number(epochLength)); + const nextEpoch = await Chronos.getCurrentEpoch(); + expect(nextEpoch).to.equal(currentEpoch + 1n, 'Should be in next epoch'); + + // Test in next epoch + await RandomSamplingStorage.incrementEpochNodeValidProofsCount( + nextEpoch, + nodeId, + ); + const nextEpochCount = + await RandomSamplingStorage.getEpochNodeValidProofsCount( + nextEpoch, + nodeId, + ); + expect(nextEpochCount).to.equal(1n, 'Should start at 1 in new epoch'); + expect( + await RandomSamplingStorage.getEpochNodeValidProofsCount( + currentEpoch, + nodeId, + ), + ).to.equal(2n, 'Previous epoch count should remain unchanged'); + }); + + it('Should add to node score and get node score', async () => { + const nodeIds = [1n, 2n, 3n]; + const currentEpoch = await Chronos.getCurrentEpoch(); + const proofPeriodIndex = 1n; + + // Test initial state for all nodes + for (const nodeId of nodeIds) { + expect( + await RandomSamplingStorage.getNodeEpochProofPeriodScore( + nodeId, + currentEpoch, + proofPeriodIndex, + ), + ).to.equal(0n, `Node ${nodeId} should start with 0 score`); + } + + // Add scores to different nodes + const scores = [100n, 200n, 300n]; + + for (let i = 0; i < nodeIds.length; i++) { + const nodeId = nodeIds[i]; + const score = scores[i]; + + // Add score to node + await RandomSamplingStorage.addToNodeEpochProofPeriodScore( + currentEpoch, + proofPeriodIndex, + nodeId, + score, + ); + + // Verify individual node score + const nodeScore = + await RandomSamplingStorage.getNodeEpochProofPeriodScore( + nodeId, + currentEpoch, + proofPeriodIndex, + ); + expect(nodeScore).to.equal( + score, + `Node ${nodeId} should have score ${score}`, + ); + } + + // Test adding more score to existing node + const additionalScore = 50n; + await RandomSamplingStorage.addToNodeEpochProofPeriodScore( + currentEpoch, + proofPeriodIndex, + nodeIds[0], + additionalScore, + ); + + // Verify updated individual score + const updatedNodeScore = + await RandomSamplingStorage.getNodeEpochProofPeriodScore( + nodeIds[0], + currentEpoch, + proofPeriodIndex, + ); + expect(updatedNodeScore).to.equal( + scores[0] + additionalScore, + 'Node score should be updated with additional score', + ); + }); + + it('Should accumulate delegator scores correctly', async () => { + const publishingNodeIdentityId = 1n; + const signer = await ethers.getSigner(accounts[0].address); + const currentEpoch = await Chronos.getCurrentEpoch(); + const delegatorKey = ethers.encodeBytes32String('delegator1'); + const score = 100n; + + // Test initial state + expect( + await RandomSamplingStorage.getEpochNodeDelegatorScore( + currentEpoch, + publishingNodeIdentityId, + delegatorKey, + ), + ).to.equal(0n); + + // Add score and verify accumulation + await RandomSamplingStorage.connect(signer).addToEpochNodeDelegatorScore( + currentEpoch, + publishingNodeIdentityId, + delegatorKey, + score, + ); + expect( + await RandomSamplingStorage.getEpochNodeDelegatorScore( + currentEpoch, + publishingNodeIdentityId, + delegatorKey, + ), + ).to.equal(score); + + // Add more score and verify accumulation + await RandomSamplingStorage.connect(signer).addToEpochNodeDelegatorScore( + currentEpoch, + publishingNodeIdentityId, + delegatorKey, + score, + ); + expect( + await RandomSamplingStorage.getEpochNodeDelegatorScore( + currentEpoch, + publishingNodeIdentityId, + delegatorKey, + ), + ).to.equal(score * 2n); + }); + + it('Should add to and get nodeEpochScorePerStake correctly and emit event', async () => { + const nodeId = 1n; + const currentEpoch = await Chronos.getCurrentEpoch(); + const scorePerStakeToAdd = 500n; + const expectedTotalScorePerStake = 500n; + + // Initial state + expect( + await RandomSamplingStorage.getNodeEpochScorePerStake( + currentEpoch, + nodeId, + ), + ).to.equal(0n, 'Initial nodeEpochScorePerStake should be 0'); + + // Add scorePerStake and check event + await expect( + RandomSamplingStorage.addToNodeEpochScorePerStake( + currentEpoch, + nodeId, + scorePerStakeToAdd, + ), + ) + .to.emit(RandomSamplingStorage, 'NodeEpochScorePerStakeAdded') + .withArgs( + currentEpoch, + nodeId, + scorePerStakeToAdd, + expectedTotalScorePerStake, + ); + + // Verify stored value + expect( + await RandomSamplingStorage.getNodeEpochScorePerStake( + currentEpoch, + nodeId, + ), + ).to.equal( + expectedTotalScorePerStake, + `nodeEpochScorePerStake should be ${expectedTotalScorePerStake}`, + ); + + // Add more and verify accumulation + const anotherScorePerStakeToAdd = 300n; + const newExpectedTotalScorePerStake = + expectedTotalScorePerStake + anotherScorePerStakeToAdd; + await expect( + RandomSamplingStorage.addToNodeEpochScorePerStake( + currentEpoch, + nodeId, + anotherScorePerStakeToAdd, + ), + ) + .to.emit(RandomSamplingStorage, 'NodeEpochScorePerStakeAdded') + .withArgs( + currentEpoch, + nodeId, + anotherScorePerStakeToAdd, + newExpectedTotalScorePerStake, + ); + + expect( + await RandomSamplingStorage.getNodeEpochScorePerStake( + currentEpoch, + nodeId, + ), + ).to.equal( + newExpectedTotalScorePerStake, + `nodeEpochScorePerStake should be ${newExpectedTotalScorePerStake}`, + ); + + // Test different node + const anotherNodeId = 2n; + await expect( + RandomSamplingStorage.addToNodeEpochScorePerStake( + currentEpoch, + anotherNodeId, + scorePerStakeToAdd, + ), + ) + .to.emit(RandomSamplingStorage, 'NodeEpochScorePerStakeAdded') + .withArgs( + currentEpoch, + anotherNodeId, + scorePerStakeToAdd, + scorePerStakeToAdd, + ); + expect( + await RandomSamplingStorage.getNodeEpochScorePerStake( + currentEpoch, + anotherNodeId, + ), + ).to.equal(scorePerStakeToAdd); + + // Test different epoch + await time.increase(Number(await Chronos.epochLength())); + const nextEpoch = await Chronos.getCurrentEpoch(); + await expect( + RandomSamplingStorage.addToNodeEpochScorePerStake( + nextEpoch, + nodeId, + scorePerStakeToAdd, + ), + ) + .to.emit(RandomSamplingStorage, 'NodeEpochScorePerStakeAdded') + .withArgs( + nextEpoch, + nodeId, + scorePerStakeToAdd, + expectedTotalScorePerStake, + ); + expect( + await RandomSamplingStorage.getNodeEpochScorePerStake( + nextEpoch, + nodeId, + ), + ).to.equal(scorePerStakeToAdd); + }); + }); + + describe('Initialization', () => { + it('Should have correct name and version', async () => { + expect(await RandomSamplingStorage.name()).to.equal( + 'RandomSamplingStorage', + ); + expect(await RandomSamplingStorage.version()).to.equal('1.0.0'); + }); + + it('Should set the initial parameters correctly', async function () { + const proofingPeriod = + await RandomSamplingStorage.proofingPeriodDurations(0); + expect(proofingPeriod.durationInBlocks).to.equal( + proofingPeriodDurationInBlocks, + ); + const currentEpochTx = await Chronos.getCurrentEpoch(); + const currentEpoch = BigInt(currentEpochTx.toString()); + expect(proofingPeriod.effectiveEpoch).to.equal(currentEpoch); + }); + + it('Should set correct Chronos reference and epoch on initialize', async () => { + const currentEpoch = await Chronos.getCurrentEpoch(); + await RandomSamplingStorage.initialize(); + const proofingPeriod = + await RandomSamplingStorage.proofingPeriodDurations(0); + expect(proofingPeriod.effectiveEpoch).to.equal(currentEpoch); + }); + + it('Should set correct initial values', async () => { + const currentEpoch = await Chronos.getCurrentEpoch(); + + // Deploy a new instance to check initial values before initialization + const RandomSamplingStorageFactory = await hre.ethers.getContractFactory( + 'RandomSamplingStorage', + ); + const newRandomSamplingStorage = + await RandomSamplingStorageFactory.deploy( + Hub.target, + proofingPeriodDurationInBlocks, + w1, + w2, + ); + + // Check initial proofing period duration + const initialDuration = + await newRandomSamplingStorage.proofingPeriodDurations(0); + expect(initialDuration.durationInBlocks).to.equal( + proofingPeriodDurationInBlocks, + ); + expect(initialDuration.effectiveEpoch).to.equal(currentEpoch); + }); + + it('Should update effectiveEpoch to current epoch after initialize', async () => { + const currentEpoch = await Chronos.getCurrentEpoch(); + await RandomSamplingStorage.initialize(); + const initialDuration = + await RandomSamplingStorage.proofingPeriodDurations(0); + expect(initialDuration.effectiveEpoch).to.equal(currentEpoch); + }); + + it('Should set correct CHUNK_BYTE_SIZE constant', async () => { + expect(await RandomSamplingStorage.CHUNK_BYTE_SIZE()).to.equal(32); + }); + }); + + describe('Access Control', () => { + beforeEach(async () => { + // Register RandomSampling in Hub so it can call onlyContracts methods + const currentRandomSampling = + await Hub.getContractAddress('RandomSampling'); + if (currentRandomSampling !== (await RandomSampling.getAddress())) { + await Hub.connect(accounts[0]).setContractAddress( + 'RandomSampling', + await RandomSampling.getAddress(), + ); + } + }); + + it('Should revert contact call if not called by Hub', async () => { + await expect(RandomSamplingStorage.connect(accounts[1]).initialize()) + .to.be.revertedWithCustomError( + RandomSamplingStorage, + 'UnauthorizedAccess', + ) + .withArgs('Only Hub'); + }); + + it('Should revert contact call on onlyContract modifiers', async () => { + await expect( + RandomSamplingStorage.connect( + accounts[1], + ).replacePendingProofingPeriodDuration(0, 0), + ) + .to.be.revertedWithCustomError( + RandomSamplingStorage, + 'UnauthorizedAccess', + ) + .withArgs('Only Contracts in Hub'); + + await expect( + RandomSamplingStorage.connect(accounts[1]).addProofingPeriodDuration( + 0, + 0, + ), + ) + .to.be.revertedWithCustomError( + RandomSamplingStorage, + 'UnauthorizedAccess', + ) + .withArgs('Only Contracts in Hub'); + + await expect( + RandomSamplingStorage.connect(accounts[1]).setNodeChallenge( + 0, + MockChallenge, + ), + ) + .to.be.revertedWithCustomError( + RandomSamplingStorage, + 'UnauthorizedAccess', + ) + .withArgs('Only Contracts in Hub'); + + await expect( + RandomSamplingStorage.connect( + accounts[1], + ).incrementEpochNodeValidProofsCount(0, 0), + ) + .to.be.revertedWithCustomError( + RandomSamplingStorage, + 'UnauthorizedAccess', + ) + .withArgs('Only Contracts in Hub'); + + await expect( + RandomSamplingStorage.connect( + accounts[1], + ).addToNodeEpochProofPeriodScore(0, 0, 0, 0), + ) + .to.be.revertedWithCustomError( + RandomSamplingStorage, + 'UnauthorizedAccess', + ) + .withArgs('Only Contracts in Hub'); + + await expect( + RandomSamplingStorage.connect(accounts[1]).addToNodeEpochScorePerStake( + 0, + 0, + 0, + ), + ) + .to.be.revertedWithCustomError( + RandomSamplingStorage, + 'UnauthorizedAccess', + ) + .withArgs('Only Contracts in Hub'); + + await expect( + RandomSamplingStorage.connect( + accounts[1], + ).setDelegatorLastSettledNodeEpochScorePerStake( + 0, + 0, + ethers.encodeBytes32String('0'), + 0, + ), + ) + .to.be.revertedWithCustomError( + RandomSamplingStorage, + 'UnauthorizedAccess', + ) + .withArgs('Only Contracts in Hub'); + }); + + it('Should allow access when called by Hub', async () => { + await expect(RandomSamplingStorage.connect(accounts[0]).initialize()).to + .not.be.reverted; + + await expect(RandomSamplingStorage.connect(accounts[1]).initialize()).to + .be.reverted; + + // Test contract-only functions with RandomSampling + await impersonateAndFund(RandomSampling); + const rsSigner = await ethers.getSigner( + await RandomSampling.getAddress(), + ); + + await expect( + RandomSamplingStorage.connect(rsSigner).setNodeChallenge( + 0, + MockChallenge, + ), + ).to.not.be.reverted; + + await expect( + RandomSamplingStorage.connect( + rsSigner, + ).replacePendingProofingPeriodDuration(0, 0), + ).to.not.be.reverted; + + await expect( + RandomSamplingStorage.connect(rsSigner).addProofingPeriodDuration(0, 0), + ).to.not.be.reverted; + + await expect( + RandomSamplingStorage.connect( + rsSigner, + ).incrementEpochNodeValidProofsCount(1, 1), + ).to.not.be.reverted; + + await expect( + RandomSamplingStorage.connect(rsSigner).addToNodeEpochProofPeriodScore( + 1, + 1, + 1, + 1000, + ), + ).to.not.be.reverted; + + await expect( + RandomSamplingStorage.connect(rsSigner).addToNodeEpochScorePerStake( + 1, + 1, + 1000, + ), + ).to.not.be.reverted; + + await expect( + RandomSamplingStorage.connect( + rsSigner, + ).setDelegatorLastSettledNodeEpochScorePerStake( + 1, + 1, + ethers.encodeBytes32String('test'), + 1000, + ), + ).to.not.be.reverted; + + await stopImpersonate(RandomSampling); + }); + + it('Should allow access when called by registered contract', async () => { + // Test contract-only functions with RandomSampling + await impersonateAndFund(RandomSampling); + const rsSigner = await ethers.getSigner( + await RandomSampling.getAddress(), + ); + + await expect( + RandomSamplingStorage.connect( + rsSigner, + ).replacePendingProofingPeriodDuration(1000, 1), + ).to.not.be.reverted; + + await expect( + RandomSamplingStorage.connect(rsSigner).addProofingPeriodDuration( + 1000, + 1, + ), + ).to.not.be.reverted; + + await expect( + RandomSamplingStorage.connect(rsSigner).setNodeChallenge( + 1, + MockChallenge, + ), + ).to.not.be.reverted; + + await expect( + RandomSamplingStorage.connect( + rsSigner, + ).incrementEpochNodeValidProofsCount(1, 1), + ).to.not.be.reverted; + + await expect( + RandomSamplingStorage.connect(rsSigner).addToNodeEpochProofPeriodScore( + 1, + 1, + 1, + 1000, + ), + ).to.not.be.reverted; + + await expect( + RandomSamplingStorage.connect(rsSigner).addToNodeEpochScorePerStake( + 1, + 1, + 1000, + ), + ).to.not.be.reverted; + + await expect( + RandomSamplingStorage.connect( + rsSigner, + ).setDelegatorLastSettledNodeEpochScorePerStake( + 1, + 1, + ethers.encodeBytes32String('test'), + 1000, + ), + ).to.not.be.reverted; + + await stopImpersonate(RandomSampling); + }); + }); + + describe('Challenge Handling', () => { + it('Should set and get challenge correctly', async () => { + const publishingNodeIdentityId = 1n; + + const signer = await ethers.getSigner(accounts[0].address); + await RandomSamplingStorage.connect(signer).setNodeChallenge( + publishingNodeIdentityId, + MockChallenge, + ); + + const challenge = await RandomSamplingStorage.getNodeChallenge( + publishingNodeIdentityId, + ); + + expect(challenge.knowledgeCollectionId).to.be.equal( + MockChallenge.knowledgeCollectionId, + ); + expect(challenge.chunkId).to.be.equal(MockChallenge.chunkId); + expect(challenge.epoch).to.be.equal(MockChallenge.epoch); + expect(challenge.proofingPeriodDurationInBlocks).to.be.equal( + MockChallenge.proofingPeriodDurationInBlocks, + ); + expect(challenge.activeProofPeriodStartBlock).to.be.equal( + MockChallenge.activeProofPeriodStartBlock, + ); + expect(challenge.proofingPeriodDurationInBlocks).to.be.equal( + MockChallenge.proofingPeriodDurationInBlocks, + ); + expect(challenge.solved).to.be.equal(MockChallenge.solved); + }); + + it('Should handle multiple challenges and updates correctly', async () => { + const publishingNodeIdentityId = 1n; + + const signer = await ethers.getSigner(accounts[0].address); + + // Test initial state + const initialChallenge = await RandomSamplingStorage.getNodeChallenge( + publishingNodeIdentityId, + ); + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + expect(initialChallenge.solved).to.be.false; + expect(initialChallenge.knowledgeCollectionId).to.be.equal(0n); + + // Set first challenge + await RandomSamplingStorage.connect(signer).setNodeChallenge( + publishingNodeIdentityId, + MockChallenge, + ); + + // Verify first challenge + const firstChallenge = await RandomSamplingStorage.getNodeChallenge( + publishingNodeIdentityId, + ); + expect(firstChallenge.knowledgeCollectionId).to.be.equal( + MockChallenge.knowledgeCollectionId, + ); + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + expect(firstChallenge.solved).to.be.equal(MockChallenge.solved); + + // Create and set second challenge + const secondChallenge = { + ...MockChallenge, + knowledgeCollectionId: BigInt(MockChallenge.knowledgeCollectionId) + 1n, + solved: true, + }; + await RandomSamplingStorage.connect(signer).setNodeChallenge( + publishingNodeIdentityId, + secondChallenge, + ); + + // Verify second challenge overwrote first + const finalChallenge = await RandomSamplingStorage.getNodeChallenge( + publishingNodeIdentityId, + ); + expect(finalChallenge.knowledgeCollectionId).to.be.equal( + secondChallenge.knowledgeCollectionId, + ); + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + expect(finalChallenge.solved).to.be.true; + expect(finalChallenge.chunkId).to.be.equal(secondChallenge.chunkId); + }); + }); + + describe('Proofing Period Duration Management', () => { + it('Should correctly track pending proofing period duration', async () => { + const currentEpoch = await Chronos.getCurrentEpoch(); + + // Initially should be false + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + expect(await RandomSampling.isPendingProofingPeriodDuration()).to.be + .false; + + // Add a new duration + await RandomSamplingStorage.addProofingPeriodDuration( + 1000, + currentEpoch + 1n, + ); + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + expect(await RandomSampling.isPendingProofingPeriodDuration()).to.be.true; + + // Replace pending duration + await RandomSamplingStorage.replacePendingProofingPeriodDuration( + 2000, + currentEpoch + 1n, + ); + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + expect(await RandomSampling.isPendingProofingPeriodDuration()).to.be.true; + + // Move to next epoch + await time.increase(Number(await Chronos.epochLength())); + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + expect(await RandomSampling.isPendingProofingPeriodDuration()).to.be + .false; + }); + + it('Should handle multiple proofing period durations correctly', async () => { + const currentEpoch = await Chronos.getCurrentEpoch(); + + // Add multiple durations + const durations = [1000, 2000, 3000]; + for (let i = 0; i < durations.length; i++) { + await RandomSamplingStorage.addProofingPeriodDuration( + durations[i], + currentEpoch + BigInt(i + 1), + ); + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + expect(await RandomSampling.isPendingProofingPeriodDuration()).to.be + .true; + } + + // Verify durations are set correctly + for (let i = 0; i < durations.length; i++) { + const epoch = currentEpoch + BigInt(i + 1); + const duration = + await RandomSamplingStorage.getEpochProofingPeriodDurationInBlocks( + epoch, + ); + expect(duration).to.equal(BigInt(durations[i])); + } + }); + + it('Should replace pending duration correctly', async () => { + const currentEpoch = await Chronos.getCurrentEpoch(); + + // Add initial duration + await RandomSamplingStorage.addProofingPeriodDuration( + 1000, + currentEpoch + 1n, + ); + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + expect(await RandomSampling.isPendingProofingPeriodDuration()).to.be.true; + + // Replace with new duration + const newDuration = 2000; + await RandomSamplingStorage.replacePendingProofingPeriodDuration( + newDuration, + currentEpoch + 1n, + ); + + // Verify new duration is set + const duration = + await RandomSamplingStorage.getEpochProofingPeriodDurationInBlocks( + currentEpoch + 1n, + ); + expect(duration).to.equal(BigInt(newDuration)); + }); + + it('Should emit ProofingPeriodDurationAdded event with correct parameters', async () => { + const newDuration = 1000; + const effectiveEpoch = (await Chronos.getCurrentEpoch()) + 1n; + + // Add new proofing period duration and capture the event + const tx = await RandomSamplingStorage.addProofingPeriodDuration( + newDuration, + effectiveEpoch, + ); + const receipt = await tx.wait(); + + // Find the ProofingPeriodDurationAdded event + const event = receipt?.logs.find( + (log) => + (log as EventLog).fragment?.name === 'ProofingPeriodDurationAdded', + ) as EventLog; + + // Verify event parameters + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + expect(event).to.not.be.undefined; + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + expect(event?.args).to.not.be.undefined; + expect(event?.args[0]).to.equal(newDuration); + expect(event?.args[1]).to.equal(effectiveEpoch); + }); + + it('Should emit PendingProofingPeriodDurationReplaced event with correct parameters', async () => { + const oldDuration = 1000; + const newDuration = 2000; + const effectiveEpoch = (await Chronos.getCurrentEpoch()) + 1n; + + // First add a duration + await RandomSamplingStorage.addProofingPeriodDuration( + oldDuration, + effectiveEpoch, + ); + + // Then replace it and capture the event + const tx = + await RandomSamplingStorage.replacePendingProofingPeriodDuration( + newDuration, + effectiveEpoch, + ); + const receipt = await tx.wait(); + + // Find the PendingProofingPeriodDurationReplaced event + const event = receipt?.logs.find( + (log) => + (log as EventLog).fragment?.name === + 'PendingProofingPeriodDurationReplaced', + ) as EventLog; + + // Verify event parameters + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + expect(event).to.not.be.undefined; + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + expect(event?.args).to.not.be.undefined; + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + expect(event?.args[0]).to.equal(oldDuration); + expect(event?.args[1]).to.equal(newDuration); + expect(event?.args[2]).to.equal(effectiveEpoch); + }); + }); + + describe('Active Proof Period Management', () => { + it('Should set and get active proof period start block correctly and emit event', async () => { + const newActiveProofPeriodStartBlock = 12345n; + + // Impersonate RandomSampling contract to call onlyContracts function + await impersonateAndFund(RandomSampling); + const rsSigner = await ethers.getSigner( + await RandomSampling.getAddress(), + ); + + // Set active proof period start block and check event + await expect( + RandomSamplingStorage.connect(rsSigner).setActiveProofPeriodStartBlock( + newActiveProofPeriodStartBlock, + ), + ) + .to.emit(RandomSamplingStorage, 'ActiveProofPeriodStartBlockSet') + .withArgs(newActiveProofPeriodStartBlock); + + // Verify stored value + expect( + await RandomSamplingStorage.getActiveProofPeriodStartBlock(), + ).to.equal( + newActiveProofPeriodStartBlock, + `Active proof period start block should be ${newActiveProofPeriodStartBlock}`, + ); + + // Test updating to new value + const anotherBlockNumber = 67890n; + await expect( + RandomSamplingStorage.connect(rsSigner).setActiveProofPeriodStartBlock( + anotherBlockNumber, + ), + ) + .to.emit(RandomSamplingStorage, 'ActiveProofPeriodStartBlockSet') + .withArgs(anotherBlockNumber); + + expect( + await RandomSamplingStorage.getActiveProofPeriodStartBlock(), + ).to.equal( + anotherBlockNumber, + `Active proof period start block should be updated to ${anotherBlockNumber}`, + ); + + await stopImpersonate(RandomSampling); + }); + + it('Should revert if not called by contracts', async () => { + await expect( + RandomSamplingStorage.connect( + accounts[1], + ).setActiveProofPeriodStartBlock(123), + ) + .to.be.revertedWithCustomError( + RandomSamplingStorage, + 'UnauthorizedAccess', + ) + .withArgs('Only Contracts in Hub'); + }); + }); + + describe('Proofing Period Duration Helper Functions', () => { + beforeEach(async () => { + // Add some test durations + await impersonateAndFund(RandomSampling); + const rsSigner = await ethers.getSigner( + await RandomSampling.getAddress(), + ); + + const currentEpoch = await Chronos.getCurrentEpoch(); + await RandomSamplingStorage.connect(rsSigner).addProofingPeriodDuration( + 1000, + currentEpoch + 1n, + ); + await RandomSamplingStorage.connect(rsSigner).addProofingPeriodDuration( + 2000, + currentEpoch + 2n, + ); + + await stopImpersonate(RandomSampling); + }); + + it('Should return correct proofing period durations length', async () => { + // Should have initial duration + 2 added durations = 3 total + expect( + await RandomSamplingStorage.getProofingPeriodDurationsLength(), + ).to.equal(3); + }); + + it('Should return latest proofing period duration effective epoch', async () => { + const currentEpoch = await Chronos.getCurrentEpoch(); + expect( + await RandomSamplingStorage.getLatestProofingPeriodDurationEffectiveEpoch(), + ).to.equal(currentEpoch + 2n); + }); + + it('Should return latest proofing period duration in blocks', async () => { + expect( + await RandomSamplingStorage.getLatestProofingPeriodDurationInBlocks(), + ).to.equal(2000); + }); + + it('Should return proofing period duration from specific index', async () => { + const currentEpoch = await Chronos.getCurrentEpoch(); + + // Test index 0 (initial duration) + const duration0 = + await RandomSamplingStorage.getProofingPeriodDurationFromIndex(0); + expect(duration0.durationInBlocks).to.equal( + proofingPeriodDurationInBlocks, + ); + expect(duration0.effectiveEpoch).to.equal(currentEpoch); + + // Test index 1 (first added duration) + const duration1 = + await RandomSamplingStorage.getProofingPeriodDurationFromIndex(1); + expect(duration1.durationInBlocks).to.equal(1000); + expect(duration1.effectiveEpoch).to.equal(currentEpoch + 1n); + + // Test index 2 (second added duration) + const duration2 = + await RandomSamplingStorage.getProofingPeriodDurationFromIndex(2); + expect(duration2.durationInBlocks).to.equal(2000); + expect(duration2.effectiveEpoch).to.equal(currentEpoch + 2n); + }); + + it('Should revert when accessing invalid index', async () => { + const length = + await RandomSamplingStorage.getProofingPeriodDurationsLength(); + await expect( + RandomSamplingStorage.getProofingPeriodDurationFromIndex(length), + ).to.be.reverted; // Array out of bounds + }); + }); + + describe('Node Epoch Valid Proofs Count Management', () => { + it('Should set epoch node valid proofs count and emit event', async () => { + const nodeId = 1n; + const currentEpoch = await Chronos.getCurrentEpoch(); + const countToSet = 5n; + + // Impersonate RandomSampling contract + await impersonateAndFund(RandomSampling); + const rsSigner = await ethers.getSigner( + await RandomSampling.getAddress(), + ); + + // Set count and check event + await expect( + RandomSamplingStorage.connect(rsSigner).setEpochNodeValidProofsCount( + currentEpoch, + nodeId, + countToSet, + ), + ) + .to.emit(RandomSamplingStorage, 'EpochNodeValidProofsCountSet') + .withArgs(currentEpoch, nodeId, countToSet); + + // Verify stored value + expect( + await RandomSamplingStorage.getEpochNodeValidProofsCount( + currentEpoch, + nodeId, + ), + ).to.equal(countToSet); + + // Test overwriting + const newCount = 10n; + await expect( + RandomSamplingStorage.connect(rsSigner).setEpochNodeValidProofsCount( + currentEpoch, + nodeId, + newCount, + ), + ) + .to.emit(RandomSamplingStorage, 'EpochNodeValidProofsCountSet') + .withArgs(currentEpoch, nodeId, newCount); + + expect( + await RandomSamplingStorage.getEpochNodeValidProofsCount( + currentEpoch, + nodeId, + ), + ).to.equal(newCount); + + await stopImpersonate(RandomSampling); + }); + }); + + describe('Node Epoch Score Management', () => { + it('Should add to node epoch score and emit event', async () => { + const nodeId = 1n; + const currentEpoch = await Chronos.getCurrentEpoch(); + const scoreToAdd = 1000n; + const expectedTotalScore = 1000n; + + // Impersonate RandomSampling contract + await impersonateAndFund(RandomSampling); + const rsSigner = await ethers.getSigner( + await RandomSampling.getAddress(), + ); + + // Initial state + expect( + await RandomSamplingStorage.getNodeEpochScore(currentEpoch, nodeId), + ).to.equal(0n); + + // Add score and check event + await expect( + RandomSamplingStorage.connect(rsSigner).addToNodeEpochScore( + currentEpoch, + nodeId, + scoreToAdd, + ), + ) + .to.emit(RandomSamplingStorage, 'NodeEpochScoreAdded') + .withArgs(currentEpoch, nodeId, scoreToAdd, expectedTotalScore); + + // Verify stored value + expect( + await RandomSamplingStorage.getNodeEpochScore(currentEpoch, nodeId), + ).to.equal(expectedTotalScore); + + // Add more score and verify accumulation + const anotherScore = 500n; + const newExpectedTotal = expectedTotalScore + anotherScore; + await expect( + RandomSamplingStorage.connect(rsSigner).addToNodeEpochScore( + currentEpoch, + nodeId, + anotherScore, + ), + ) + .to.emit(RandomSamplingStorage, 'NodeEpochScoreAdded') + .withArgs(currentEpoch, nodeId, anotherScore, newExpectedTotal); + + expect( + await RandomSamplingStorage.getNodeEpochScore(currentEpoch, nodeId), + ).to.equal(newExpectedTotal); + + await stopImpersonate(RandomSampling); + }); + + it('Should set node epoch score and emit event', async () => { + const nodeId = 1n; + const currentEpoch = await Chronos.getCurrentEpoch(); + const scoreToSet = 2500n; + + // Impersonate RandomSampling contract + await impersonateAndFund(RandomSampling); + const rsSigner = await ethers.getSigner( + await RandomSampling.getAddress(), + ); + + // Set score and check event + await expect( + RandomSamplingStorage.connect(rsSigner).setNodeEpochScore( + currentEpoch, + nodeId, + scoreToSet, + ), + ) + .to.emit(RandomSamplingStorage, 'NodeEpochScoreSet') + .withArgs(currentEpoch, nodeId, scoreToSet); + + // Verify stored value + expect( + await RandomSamplingStorage.getNodeEpochScore(currentEpoch, nodeId), + ).to.equal(scoreToSet); + + // Test overwriting + const newScore = 3000n; + await expect( + RandomSamplingStorage.connect(rsSigner).setNodeEpochScore( + currentEpoch, + nodeId, + newScore, + ), + ) + .to.emit(RandomSamplingStorage, 'NodeEpochScoreSet') + .withArgs(currentEpoch, nodeId, newScore); + + expect( + await RandomSamplingStorage.getNodeEpochScore(currentEpoch, nodeId), + ).to.equal(newScore); + + await stopImpersonate(RandomSampling); + }); + }); + + describe('All Nodes Epoch Score Management', () => { + it('Should add to all nodes epoch score and emit event', async () => { + const currentEpoch = await Chronos.getCurrentEpoch(); + const scoreToAdd = 5000n; + const expectedTotalScore = 5000n; + + // Impersonate RandomSampling contract + await impersonateAndFund(RandomSampling); + const rsSigner = await ethers.getSigner( + await RandomSampling.getAddress(), + ); + + // Initial state + expect( + await RandomSamplingStorage.getAllNodesEpochScore(currentEpoch), + ).to.equal(0n); + + // Add score and check event + await expect( + RandomSamplingStorage.connect(rsSigner).addToAllNodesEpochScore( + currentEpoch, + scoreToAdd, + ), + ) + .to.emit(RandomSamplingStorage, 'AllNodesEpochScoreAdded') + .withArgs(currentEpoch, scoreToAdd, expectedTotalScore); + + // Verify stored value + expect( + await RandomSamplingStorage.getAllNodesEpochScore(currentEpoch), + ).to.equal(expectedTotalScore); + + // Add more score and verify accumulation + const anotherScore = 2000n; + const newExpectedTotal = expectedTotalScore + anotherScore; + await expect( + RandomSamplingStorage.connect(rsSigner).addToAllNodesEpochScore( + currentEpoch, + anotherScore, + ), + ) + .to.emit(RandomSamplingStorage, 'AllNodesEpochScoreAdded') + .withArgs(currentEpoch, anotherScore, newExpectedTotal); + + expect( + await RandomSamplingStorage.getAllNodesEpochScore(currentEpoch), + ).to.equal(newExpectedTotal); + + await stopImpersonate(RandomSampling); + }); + + it('Should set all nodes epoch score and emit event', async () => { + const currentEpoch = await Chronos.getCurrentEpoch(); + const scoreToSet = 10000n; + + // Impersonate RandomSampling contract + await impersonateAndFund(RandomSampling); + const rsSigner = await ethers.getSigner( + await RandomSampling.getAddress(), + ); + + // Set score and check event + await expect( + RandomSamplingStorage.connect(rsSigner).setAllNodesEpochScore( + currentEpoch, + scoreToSet, + ), + ) + .to.emit(RandomSamplingStorage, 'AllNodesEpochScoreSet') + .withArgs(currentEpoch, scoreToSet); + + // Verify stored value + expect( + await RandomSamplingStorage.getAllNodesEpochScore(currentEpoch), + ).to.equal(scoreToSet); + + // Test overwriting + const newScore = 15000n; + await expect( + RandomSamplingStorage.connect(rsSigner).setAllNodesEpochScore( + currentEpoch, + newScore, + ), + ) + .to.emit(RandomSamplingStorage, 'AllNodesEpochScoreSet') + .withArgs(currentEpoch, newScore); + + expect( + await RandomSamplingStorage.getAllNodesEpochScore(currentEpoch), + ).to.equal(newScore); + + await stopImpersonate(RandomSampling); + }); + }); + + describe('Node Epoch Proof Period Score Setting', () => { + it('Should set node epoch proof period score and emit event', async () => { + const nodeId = 1n; + const currentEpoch = await Chronos.getCurrentEpoch(); + const proofPeriodStartBlock = 100n; + const scoreToSet = 3500n; + + // Impersonate RandomSampling contract + await impersonateAndFund(RandomSampling); + const rsSigner = await ethers.getSigner( + await RandomSampling.getAddress(), + ); + + // Set score and check event + await expect( + RandomSamplingStorage.connect(rsSigner).setNodeEpochProofPeriodScore( + currentEpoch, + proofPeriodStartBlock, + nodeId, + scoreToSet, + ), + ) + .to.emit(RandomSamplingStorage, 'NodeEpochProofPeriodScoreSet') + .withArgs(currentEpoch, proofPeriodStartBlock, nodeId, scoreToSet); + + // Verify stored value + expect( + await RandomSamplingStorage.getNodeEpochProofPeriodScore( + nodeId, + currentEpoch, + proofPeriodStartBlock, + ), + ).to.equal(scoreToSet); + + // Test overwriting + const newScore = 4000n; + await expect( + RandomSamplingStorage.connect(rsSigner).setNodeEpochProofPeriodScore( + currentEpoch, + proofPeriodStartBlock, + nodeId, + newScore, + ), + ) + .to.emit(RandomSamplingStorage, 'NodeEpochProofPeriodScoreSet') + .withArgs(currentEpoch, proofPeriodStartBlock, nodeId, newScore); + + expect( + await RandomSamplingStorage.getNodeEpochProofPeriodScore( + nodeId, + currentEpoch, + proofPeriodStartBlock, + ), + ).to.equal(newScore); + + await stopImpersonate(RandomSampling); + }); + }); + + describe('Epoch Node Delegator Score Management', () => { + it('Should set epoch node delegator score and emit event', async () => { + const nodeId = 1n; + const currentEpoch = await Chronos.getCurrentEpoch(); + const delegatorKey = ethers.encodeBytes32String('delegatorTest'); + const scoreToSet = 750n; + + // Impersonate RandomSampling contract + await impersonateAndFund(RandomSampling); + const rsSigner = await ethers.getSigner( + await RandomSampling.getAddress(), + ); + + // Set score and check event + await expect( + RandomSamplingStorage.connect(rsSigner).setEpochNodeDelegatorScore( + currentEpoch, + nodeId, + delegatorKey, + scoreToSet, + ), + ) + .to.emit(RandomSamplingStorage, 'EpochNodeDelegatorScoreSet') + .withArgs(currentEpoch, nodeId, delegatorKey, scoreToSet); + + // Verify stored value + expect( + await RandomSamplingStorage.getEpochNodeDelegatorScore( + currentEpoch, + nodeId, + delegatorKey, + ), + ).to.equal(scoreToSet); + + // Test overwriting + const newScore = 1200n; + await expect( + RandomSamplingStorage.connect(rsSigner).setEpochNodeDelegatorScore( + currentEpoch, + nodeId, + delegatorKey, + newScore, + ), + ) + .to.emit(RandomSamplingStorage, 'EpochNodeDelegatorScoreSet') + .withArgs(currentEpoch, nodeId, delegatorKey, newScore); + + expect( + await RandomSamplingStorage.getEpochNodeDelegatorScore( + currentEpoch, + nodeId, + delegatorKey, + ), + ).to.equal(newScore); + + await stopImpersonate(RandomSampling); + }); + }); + + describe('Node Epoch Score Per Stake Setting', () => { + it('Should set node epoch score per stake and emit event', async () => { + const nodeId = 1n; + const currentEpoch = await Chronos.getCurrentEpoch(); + const scorePerStakeToSet = 25000n; + + // Impersonate RandomSampling contract + await impersonateAndFund(RandomSampling); + const rsSigner = await ethers.getSigner( + await RandomSampling.getAddress(), + ); + + // Set score per stake and check event + await expect( + RandomSamplingStorage.connect(rsSigner).setNodeEpochScorePerStake( + currentEpoch, + nodeId, + scorePerStakeToSet, + ), + ) + .to.emit(RandomSamplingStorage, 'NodeEpochScorePerStakeSet') + .withArgs(currentEpoch, nodeId, scorePerStakeToSet); + + // Verify stored value + expect( + await RandomSamplingStorage.getNodeEpochScorePerStake( + currentEpoch, + nodeId, + ), + ).to.equal(scorePerStakeToSet); + + // Test overwriting + const newScorePerStake = 35000n; + await expect( + RandomSamplingStorage.connect(rsSigner).setNodeEpochScorePerStake( + currentEpoch, + nodeId, + newScorePerStake, + ), + ) + .to.emit(RandomSamplingStorage, 'NodeEpochScorePerStakeSet') + .withArgs(currentEpoch, nodeId, newScorePerStake); + + expect( + await RandomSamplingStorage.getNodeEpochScorePerStake( + currentEpoch, + nodeId, + ), + ).to.equal(newScorePerStake); + + await stopImpersonate(RandomSampling); + }); + }); + + describe('Delegator Last Settled Node Epoch Score Per Stake Management', () => { + it('Should set and get delegatorLastSettledNodeEpochScorePerStake correctly and emit event', async () => { + const nodeId = 1n; + const delegatorKey = ethers.encodeBytes32String('delegatorTest'); + const currentEpoch = await Chronos.getCurrentEpoch(); + const scorePerStakeToSet = 12345n; + + // Impersonate RandomSampling contract + await impersonateAndFund(RandomSampling); + const rsSigner = await ethers.getSigner( + await RandomSampling.getAddress(), + ); + + // Initial state + expect( + await RandomSamplingStorage.getDelegatorLastSettledNodeEpochScorePerStake( + currentEpoch, + nodeId, + delegatorKey, + ), + ).to.equal( + 0n, + 'Initial delegatorLastSettledNodeEpochScorePerStake should be 0', + ); + + // Set score per stake and check event + await expect( + RandomSamplingStorage.connect( + rsSigner, + ).setDelegatorLastSettledNodeEpochScorePerStake( + currentEpoch, + nodeId, + delegatorKey, + scorePerStakeToSet, + ), + ) + .to.emit( + RandomSamplingStorage, + 'DelegatorLastSettledNodeEpochScorePerStakeSet', + ) + .withArgs(currentEpoch, nodeId, delegatorKey, scorePerStakeToSet); + + // Verify stored value + expect( + await RandomSamplingStorage.getDelegatorLastSettledNodeEpochScorePerStake( + currentEpoch, + nodeId, + delegatorKey, + ), + ).to.equal( + scorePerStakeToSet, + `delegatorLastSettledNodeEpochScorePerStake should be ${scorePerStakeToSet}`, + ); + + // Test overwriting + const newScorePerStake = 54321n; + await expect( + RandomSamplingStorage.connect( + rsSigner, + ).setDelegatorLastSettledNodeEpochScorePerStake( + currentEpoch, + nodeId, + delegatorKey, + newScorePerStake, + ), + ) + .to.emit( + RandomSamplingStorage, + 'DelegatorLastSettledNodeEpochScorePerStakeSet', + ) + .withArgs(currentEpoch, nodeId, delegatorKey, newScorePerStake); + + expect( + await RandomSamplingStorage.getDelegatorLastSettledNodeEpochScorePerStake( + currentEpoch, + nodeId, + delegatorKey, + ), + ).to.equal( + newScorePerStake, + `delegatorLastSettledNodeEpochScorePerStake should be ${newScorePerStake} after overwrite`, + ); + + // Test different delegator key + const anotherDelegatorKey = ethers.encodeBytes32String('delegatorTest2'); + await expect( + RandomSamplingStorage.connect( + rsSigner, + ).setDelegatorLastSettledNodeEpochScorePerStake( + currentEpoch, + nodeId, + anotherDelegatorKey, + scorePerStakeToSet, + ), + ) + .to.emit( + RandomSamplingStorage, + 'DelegatorLastSettledNodeEpochScorePerStakeSet', + ) + .withArgs( + currentEpoch, + nodeId, + anotherDelegatorKey, + scorePerStakeToSet, + ); + + expect( + await RandomSamplingStorage.getDelegatorLastSettledNodeEpochScorePerStake( + currentEpoch, + nodeId, + anotherDelegatorKey, + ), + ).to.equal(scorePerStakeToSet); + + // Test different node + const anotherNodeId = 2n; + await expect( + RandomSamplingStorage.connect( + rsSigner, + ).setDelegatorLastSettledNodeEpochScorePerStake( + currentEpoch, + anotherNodeId, + delegatorKey, + scorePerStakeToSet, + ), + ) + .to.emit( + RandomSamplingStorage, + 'DelegatorLastSettledNodeEpochScorePerStakeSet', + ) + .withArgs( + currentEpoch, + anotherNodeId, + delegatorKey, + scorePerStakeToSet, + ); + + expect( + await RandomSamplingStorage.getDelegatorLastSettledNodeEpochScorePerStake( + currentEpoch, + anotherNodeId, + delegatorKey, + ), + ).to.equal(scorePerStakeToSet); + + // Test different epoch + await time.increase(Number(await Chronos.epochLength())); + const nextEpoch = await Chronos.getCurrentEpoch(); + await expect( + RandomSamplingStorage.connect( + rsSigner, + ).setDelegatorLastSettledNodeEpochScorePerStake( + nextEpoch, + nodeId, + delegatorKey, + scorePerStakeToSet, + ), + ) + .to.emit( + RandomSamplingStorage, + 'DelegatorLastSettledNodeEpochScorePerStakeSet', + ) + .withArgs(nextEpoch, nodeId, delegatorKey, scorePerStakeToSet); + + expect( + await RandomSamplingStorage.getDelegatorLastSettledNodeEpochScorePerStake( + nextEpoch, + nodeId, + delegatorKey, + ), + ).to.equal(scorePerStakeToSet); + + await stopImpersonate(RandomSampling); + }); + + it('Should maintain separate delegator last settled values for different combinations', async () => { + const nodeIds = [1n, 2n]; + const delegatorKeys = [ + ethers.encodeBytes32String('delegator1'), + ethers.encodeBytes32String('delegator2'), + ]; + const currentEpoch = await Chronos.getCurrentEpoch(); + const baseScorePerStake = 1000n; + + // Impersonate RandomSampling contract + await impersonateAndFund(RandomSampling); + const rsSigner = await ethers.getSigner( + await RandomSampling.getAddress(), + ); + + // Set different values for each combination + let expectedValue = baseScorePerStake; + for (let i = 0; i < nodeIds.length; i++) { + for (let j = 0; j < delegatorKeys.length; j++) { + const nodeId = nodeIds[i]; + const delegatorKey = delegatorKeys[j]; + expectedValue += BigInt(i * 10 + j); + + await RandomSamplingStorage.connect( + rsSigner, + ).setDelegatorLastSettledNodeEpochScorePerStake( + currentEpoch, + nodeId, + delegatorKey, + expectedValue, + ); + + // Verify the value was set correctly + expect( + await RandomSamplingStorage.getDelegatorLastSettledNodeEpochScorePerStake( + currentEpoch, + nodeId, + delegatorKey, + ), + ).to.equal( + expectedValue, + `Value should be ${expectedValue} for node ${nodeId} and delegator ${j}`, + ); + } + } + + // Verify all values are still correctly stored + expectedValue = baseScorePerStake; + for (let i = 0; i < nodeIds.length; i++) { + for (let j = 0; j < delegatorKeys.length; j++) { + const nodeId = nodeIds[i]; + const delegatorKey = delegatorKeys[j]; + expectedValue += BigInt(i * 10 + j); + + expect( + await RandomSamplingStorage.getDelegatorLastSettledNodeEpochScorePerStake( + currentEpoch, + nodeId, + delegatorKey, + ), + ).to.equal( + expectedValue, + `Final verification: Value should be ${expectedValue} for node ${nodeId} and delegator ${j}`, + ); + } + } + + await stopImpersonate(RandomSampling); + }); + + it('Should revert when not called by contracts', async () => { + const currentEpoch = await Chronos.getCurrentEpoch(); + const nodeId = 1n; + const delegatorKey = ethers.encodeBytes32String('test'); + + await expect( + RandomSamplingStorage.connect( + accounts[1], + ).setDelegatorLastSettledNodeEpochScorePerStake( + currentEpoch, + nodeId, + delegatorKey, + 1000, + ), + ) + .to.be.revertedWithCustomError( + RandomSamplingStorage, + 'UnauthorizedAccess', + ) + .withArgs('Only Contracts in Hub'); + }); + }); + + describe('Enhanced Access Control Tests', () => { + it('Should revert all new setter functions when not called by contracts', async () => { + const currentEpoch = await Chronos.getCurrentEpoch(); + const nodeId = 1n; + const delegatorKey = ethers.encodeBytes32String('test'); + + // Test all new setter functions for proper access control + await expect( + RandomSamplingStorage.connect(accounts[1]).setEpochNodeValidProofsCount( + currentEpoch, + nodeId, + 5, + ), + ) + .to.be.revertedWithCustomError( + RandomSamplingStorage, + 'UnauthorizedAccess', + ) + .withArgs('Only Contracts in Hub'); + + await expect( + RandomSamplingStorage.connect(accounts[1]).addToNodeEpochScore( + currentEpoch, + nodeId, + 1000, + ), + ) + .to.be.revertedWithCustomError( + RandomSamplingStorage, + 'UnauthorizedAccess', + ) + .withArgs('Only Contracts in Hub'); + + await expect( + RandomSamplingStorage.connect(accounts[1]).setNodeEpochScore( + currentEpoch, + nodeId, + 1000, + ), + ) + .to.be.revertedWithCustomError( + RandomSamplingStorage, + 'UnauthorizedAccess', + ) + .withArgs('Only Contracts in Hub'); + + await expect( + RandomSamplingStorage.connect(accounts[1]).addToAllNodesEpochScore( + currentEpoch, + 1000, + ), + ) + .to.be.revertedWithCustomError( + RandomSamplingStorage, + 'UnauthorizedAccess', + ) + .withArgs('Only Contracts in Hub'); + + await expect( + RandomSamplingStorage.connect(accounts[1]).setAllNodesEpochScore( + currentEpoch, + 1000, + ), + ) + .to.be.revertedWithCustomError( + RandomSamplingStorage, + 'UnauthorizedAccess', + ) + .withArgs('Only Contracts in Hub'); + + await expect( + RandomSamplingStorage.connect(accounts[1]).setNodeEpochProofPeriodScore( + currentEpoch, + 100, + nodeId, + 1000, + ), + ) + .to.be.revertedWithCustomError( + RandomSamplingStorage, + 'UnauthorizedAccess', + ) + .withArgs('Only Contracts in Hub'); + + await expect( + RandomSamplingStorage.connect(accounts[1]).setEpochNodeDelegatorScore( + currentEpoch, + nodeId, + delegatorKey, + 1000, + ), + ) + .to.be.revertedWithCustomError( + RandomSamplingStorage, + 'UnauthorizedAccess', + ) + .withArgs('Only Contracts in Hub'); + + await expect( + RandomSamplingStorage.connect(accounts[1]).setNodeEpochScorePerStake( + currentEpoch, + nodeId, + 1000, + ), + ) + .to.be.revertedWithCustomError( + RandomSamplingStorage, + 'UnauthorizedAccess', + ) + .withArgs('Only Contracts in Hub'); + + await expect( + RandomSamplingStorage.connect( + accounts[1], + ).setDelegatorLastSettledNodeEpochScorePerStake( + currentEpoch, + nodeId, + delegatorKey, + 1000, + ), + ) + .to.be.revertedWithCustomError( + RandomSamplingStorage, + 'UnauthorizedAccess', + ) + .withArgs('Only Contracts in Hub'); + }); + }); + + describe('Missing Event Assertions (Adder/Setter Helpers)', () => { + let rsSigner: SignerWithAddress; + const nodeId = 1n; + const delegatorKey = ethers.encodeBytes32String('delegatorEvent'); + + beforeEach(async () => { + // Impersonate RandomSampling (registered in Hub) for onlyContracts funcs + await impersonateAndFund(RandomSampling); + rsSigner = await ethers.getSigner(await RandomSampling.getAddress()); + }); + + afterEach(async () => { + await stopImpersonate(RandomSampling); + }); + + it('emits NodeChallengeSet when a challenge is stored', async () => { + await expect( + RandomSamplingStorage.connect(rsSigner).setNodeChallenge( + nodeId, + MockChallenge, + ), + ) + .to.emit(RandomSamplingStorage, 'NodeChallengeSet') + .withArgs(nodeId, Object.values(MockChallenge)); // Struct is indexed as tuple + }); + + it('emits EpochNodeValidProofsCountIncremented on increment', async () => { + const currentEpoch = await Chronos.getCurrentEpoch(); + await expect( + RandomSamplingStorage.connect( + rsSigner, + ).incrementEpochNodeValidProofsCount(currentEpoch, nodeId), + ) + .to.emit(RandomSamplingStorage, 'EpochNodeValidProofsCountIncremented') + .withArgs(currentEpoch, nodeId, 1n); + }); + + it('emits NodeEpochProofPeriodScoreAdded', async () => { + const currentEpoch = await Chronos.getCurrentEpoch(); + const proofPeriodStartBlock = 777n; + const score = 1234n; + + await expect( + RandomSamplingStorage.connect(rsSigner).addToNodeEpochProofPeriodScore( + currentEpoch, + proofPeriodStartBlock, + nodeId, + score, + ), + ) + .to.emit(RandomSamplingStorage, 'NodeEpochProofPeriodScoreAdded') + .withArgs( + currentEpoch, + proofPeriodStartBlock, + nodeId, + score, + score, // total after first add + ); + }); + + it('emits EpochNodeDelegatorScoreAdded when delegator score is accumulated', async () => { + const currentEpoch = await Chronos.getCurrentEpoch(); + const score = 555n; + + await expect( + RandomSamplingStorage.connect(rsSigner).addToEpochNodeDelegatorScore( + currentEpoch, + nodeId, + delegatorKey, + score, + ), + ) + .to.emit(RandomSamplingStorage, 'EpochNodeDelegatorScoreAdded') + .withArgs( + currentEpoch, + nodeId, + delegatorKey, + score, + score, // first accumulation + ); + }); + }); + + describe('getEpochProofingPeriodDurationInBlocks() Edge-Case Reverts', () => { + it('reverts when epoch precedes the earliest effectiveEpoch', async () => { + // Advance Chronos one epoch so the earliest effectiveEpoch will be > 0 + await time.increase(Number(await Chronos.epochLength())); + + // Deploy a fresh storage instance *after* epoch advanced + const RSFactory = await hre.ethers.getContractFactory( + 'RandomSamplingStorage', + ); + const freshStorage = await RSFactory.deploy( + Hub.target, + proofingPeriodDurationInBlocks, + w1, + w2, + ); + + // Earliest effectiveEpoch is now 1; querying 0 must revert + await expect( + freshStorage.getEpochProofingPeriodDurationInBlocks(0n), + ).to.be.revertedWith('No applicable duration found'); + }); + }); + + describe('Cross-Function Integration Tests', () => { + it('Should handle complex scoring scenarios with multiple functions', async () => { + const nodeId = 1n; + const currentEpoch = await Chronos.getCurrentEpoch(); + const proofPeriodStartBlock = 200n; + const delegatorKey = ethers.encodeBytes32String('integrationTest'); + + // Impersonate RandomSampling contract + await impersonateAndFund(RandomSampling); + const rsSigner = await ethers.getSigner( + await RandomSampling.getAddress(), + ); + + // Set up a complete scoring scenario + // 1. Set valid proofs count + await RandomSamplingStorage.connect( + rsSigner, + ).setEpochNodeValidProofsCount(currentEpoch, nodeId, 10); + + // 2. Add node epoch score + await RandomSamplingStorage.connect(rsSigner).addToNodeEpochScore( + currentEpoch, + nodeId, + 5000, + ); + + // 3. Add to all nodes score + await RandomSamplingStorage.connect(rsSigner).addToAllNodesEpochScore( + currentEpoch, + 5000, + ); + + // 4. Set proof period specific score + await RandomSamplingStorage.connect( + rsSigner, + ).setNodeEpochProofPeriodScore( + currentEpoch, + proofPeriodStartBlock, + nodeId, + 2000, + ); + + // 5. Set delegator score + await RandomSamplingStorage.connect(rsSigner).setEpochNodeDelegatorScore( + currentEpoch, + nodeId, + delegatorKey, + 1500, + ); + + // 6. Set score per stake + await RandomSamplingStorage.connect(rsSigner).setNodeEpochScorePerStake( + currentEpoch, + nodeId, + 50000, + ); + + // Verify all values are set correctly + expect( + await RandomSamplingStorage.getEpochNodeValidProofsCount( + currentEpoch, + nodeId, + ), + ).to.equal(10); + expect( + await RandomSamplingStorage.getNodeEpochScore(currentEpoch, nodeId), + ).to.equal(5000); + expect( + await RandomSamplingStorage.getAllNodesEpochScore(currentEpoch), + ).to.equal(5000); + expect( + await RandomSamplingStorage.getNodeEpochProofPeriodScore( + nodeId, + currentEpoch, + proofPeriodStartBlock, + ), + ).to.equal(2000); + expect( + await RandomSamplingStorage.getEpochNodeDelegatorScore( + currentEpoch, + nodeId, + delegatorKey, + ), + ).to.equal(1500); + expect( + await RandomSamplingStorage.getNodeEpochScorePerStake( + currentEpoch, + nodeId, + ), + ).to.equal(50000); + + await stopImpersonate(RandomSampling); + }); + }); +}); diff --git a/test/unit/Staking.test.ts b/test/unit/Staking.test.ts index 9337b6bf..57ab83fc 100644 --- a/test/unit/Staking.test.ts +++ b/test/unit/Staking.test.ts @@ -16,6 +16,10 @@ import { AskStorage, Hub, Staking, + Chronos, + RandomSamplingStorage, + EpochStorage, + DelegatorsInfo, } from '../../typechain'; type StakingFixture = { @@ -30,10 +34,21 @@ type StakingFixture = { ProfileStorage: ProfileStorage; AskStorage: AskStorage; Hub: Hub; + Chronos: Chronos; + RandomSamplingStorage: RandomSamplingStorage; + EpochStorage: EpochStorage; + DelegatorsInfo: DelegatorsInfo; }; async function deployStakingFixture(): Promise { - await hre.deployments.fixture(['Profile', 'Staking']); + await hre.deployments.fixture([ + 'Profile', + 'Staking', + 'EpochStorage', + 'Chronos', + 'RandomSamplingStorage', + 'DelegatorsInfo', + ]); const Staking = await hre.ethers.getContract('Staking'); const Profile = await hre.ethers.getContract('Profile'); const Token = await hre.ethers.getContract('Token'); @@ -49,6 +64,15 @@ async function deployStakingFixture(): Promise { await hre.ethers.getContract('ProfileStorage'); const AskStorage = await hre.ethers.getContract('AskStorage'); const Hub = await hre.ethers.getContract('Hub'); + const Chronos = await hre.ethers.getContract('Chronos'); + const RandomSamplingStorage = + await hre.ethers.getContract( + 'RandomSamplingStorage', + ); + const EpochStorage = + await hre.ethers.getContract('EpochStorageV8'); + const DelegatorsInfo = + await hre.ethers.getContract('DelegatorsInfo'); const accounts = await hre.ethers.getSigners(); await Hub.setContractAddress('HubOwner', accounts[0].address); @@ -65,6 +89,10 @@ async function deployStakingFixture(): Promise { ProfileStorage, AskStorage, Hub, + Chronos, + RandomSamplingStorage, + EpochStorage, + DelegatorsInfo, }; } @@ -76,6 +104,10 @@ describe('Staking contract', function () { let StakingStorage: StakingStorage; let ShardingTableStorage: ShardingTableStorage; let ParametersStorage: ParametersStorage; + let RandomSamplingStorage: RandomSamplingStorage; + let Chronos: Chronos; + let EpochStorage: EpochStorage; + let DelegatorsInfo: DelegatorsInfo; const createProfile = async ( admin?: SignerWithAddress, @@ -104,14 +136,25 @@ describe('Staking contract', function () { StakingStorage, ShardingTableStorage, ParametersStorage, + RandomSamplingStorage, + Chronos, + EpochStorage, + DelegatorsInfo, } = await loadFixture(deployStakingFixture)); }); + /********************************************************************** + * Sanity checks * + **********************************************************************/ it('Should have correct name and version', async () => { expect(await Staking.name()).to.equal('Staking'); - expect(await Staking.version()).to.equal('1.0.0'); + expect(await Staking.version()).to.equal('1.0.1'); }); + /********************************************************************** + * Staking tests * + **********************************************************************/ + it('Should revert if staking 0 tokens', async () => { const { identityId } = await createProfile(); await expect(Staking.stake(identityId, 0)).to.be.revertedWithCustomError( @@ -162,6 +205,42 @@ describe('Staking contract', function () { }); it('Should stake successfully and reflect on node stake', async () => { + const { identityId } = await createProfile(); + const amount = hre.ethers.parseEther('100'); + await Token.mint(accounts[0].address, amount); + await Token.connect(accounts[0]).approve( + await Staking.getAddress(), + amount, + ); + const stakingBalanceBefore = await Token.balanceOf( + await StakingStorage.getAddress(), + ); + await Staking.stake(identityId, amount); + const stakingBalanceAfter = await Token.balanceOf( + await StakingStorage.getAddress(), + ); + expect(stakingBalanceAfter - stakingBalanceBefore).to.equal( + amount, + 'StakingStorage contract balance increase by staked amount', + ); + expect(await StakingStorage.getNodeStake(identityId)).to.equal( + amount, + 'Node stake should be equal to the staked amount', + ); + expect( + await StakingStorage.getDelegatorStakeBase( + identityId, + hre.ethers.keccak256( + hre.ethers.solidityPacked(['address'], [accounts[0].address]), + ), + ), + ).to.equal(amount, 'Delegator stake should be equal to the staked amount'); + }); + /********************************************************************** + * Sharding table tests * + **********************************************************************/ + + it('Should NOT add the node to the sharding table when below minimum stake', async () => { const { identityId } = await createProfile(); const amount = hre.ethers.parseEther('100'); await Token.mint(accounts[0].address, amount); @@ -170,7 +249,10 @@ describe('Staking contract', function () { amount, ); await Staking.stake(identityId, amount); - expect(await StakingStorage.getNodeStake(identityId)).to.equal(amount); + expect(await ShardingTableStorage.nodeExists(identityId)).to.equal( + false, + 'Node should not be added to the sharding table', + ); }); it('Should add node to sharding table when above minimum stake', async () => { @@ -182,25 +264,137 @@ describe('Staking contract', function () { minStake, ); await Staking.stake(identityId, minStake); - expect(await ShardingTableStorage.nodeExists(identityId)).to.equal(true); + expect(await ShardingTableStorage.nodeExists(identityId)).to.equal( + true, + 'Node should be added to the sharding table', + ); + }); + + it('Should have node enter / exit sharding table when stake changes below / above minimum stake', async () => { + const { identityId } = await createProfile(); + const minStake = await ParametersStorage.minimumStake(); + // stake minStake - 1 → should not enter table + const almost = minStake - 1n; + await Token.mint(accounts[0].address, almost + 1n); + await Token.connect(accounts[0]).approve( + await Staking.getAddress(), + almost + 1n, + ); + await Staking.stake(identityId, almost); + expect(await ShardingTableStorage.nodeExists(identityId)).to.equal( + false, + 'Node should not be added to the sharding table', + ); + + // add +1 wei to reach exact minStake → should enter table + await Staking.stake(identityId, 1n); + expect(await ShardingTableStorage.nodeExists(identityId)).to.equal( + true, + 'Node should be added to the sharding table', + ); + + // Request withdrawal of 1 wei to fall below minStake + await Staking.requestWithdrawal(identityId, 1n); + const req = await StakingStorage.getDelegatorWithdrawalRequest( + identityId, + hre.ethers.keccak256( + hre.ethers.solidityPacked(['address'], [accounts[0].address]), + ), + ); + await time.increaseTo(req[2]); + await Staking.finalizeWithdrawal(identityId); + expect(await ShardingTableStorage.nodeExists(identityId)).to.equal( + false, + 'Node should not be added to the sharding table', + ); + }); + + it('Should have node be removed then re-enter sharding table after drop below / above threshold', async () => { + const { identityId } = await createProfile(); + const minStake = await ParametersStorage.minimumStake(); + + // Stake exactly minimum → node enters table + await Token.mint(accounts[0].address, minStake); + await Token.connect(accounts[0]).approve( + await Staking.getAddress(), + minStake, + ); + await Staking.stake(identityId, minStake); + expect(await ShardingTableStorage.nodeExists(identityId)).to.equal( + true, + 'Node should be added to the sharding table', + ); + + // Request withdrawal of 1 wei so node drops below minimum + await Staking.requestWithdrawal(identityId, 1n); + const dKey = hre.ethers.keccak256( + hre.ethers.solidityPacked(['address'], [accounts[0].address]), + ); + const [, , ts] = await StakingStorage.getDelegatorWithdrawalRequest( + identityId, + dKey, + ); + await time.increaseTo(ts); + await Staking.finalizeWithdrawal(identityId); + expect(await ShardingTableStorage.nodeExists(identityId)).to.equal( + false, + 'Node should not be added to the sharding table', + ); + + // Restake 1 wei to cross back above minimum + await Token.mint(accounts[0].address, 1n); + await Token.connect(accounts[0]).approve(await Staking.getAddress(), 1n); + await Staking.stake(identityId, 1n); + expect(await ShardingTableStorage.nodeExists(identityId)).to.equal( + true, + 'Node should be added to the sharding table', + ); }); + /********************************************************************** + * Redelegation tests * + **********************************************************************/ + it('Should redelegate stake to another identity', async () => { const node1 = await createProfile(); const node2 = await createProfile(accounts[0], accounts[2]); - - const initialStake = hre.ethers.parseEther('1000'); + const initialStake = hre.ethers.parseEther('100000'); await Token.mint(accounts[0].address, initialStake); await Token.connect(accounts[0]).approve( await Staking.getAddress(), initialStake, ); await Staking.stake(node1.identityId, initialStake); - // redelegate half const halfStake = initialStake / 2n; await Staking.redelegate(node1.identityId, node2.identityId, halfStake); + // check that the stake is correctly updated + expect(await StakingStorage.getNodeStake(node1.identityId)).to.equal( + halfStake, + 'Node1 stake should be equal to the half stake', + ); + expect(await StakingStorage.getNodeStake(node2.identityId)).to.equal( + halfStake, + 'Node2 stake should be equal to the half stake', + ); + expect( + await StakingStorage.getDelegatorStakeBase( + node1.identityId, + hre.ethers.keccak256( + hre.ethers.solidityPacked(['address'], [accounts[0].address]), + ), + ), + ).to.equal(halfStake, 'Delegator1 stake should be equal to the half stake'); + expect( + await StakingStorage.getDelegatorStakeBase( + node2.identityId, + hre.ethers.keccak256( + hre.ethers.solidityPacked(['address'], [accounts[0].address]), + ), + ), + ).to.equal(halfStake, 'Delegator2 stake should be equal to the half stake'); + // Additional tests for redelegation: // 1) Redelegate zero tokens await expect( @@ -216,6 +410,137 @@ describe('Staking contract', function () { ).to.be.revertedWithCustomError(Staking, 'ProfileDoesntExist'); }); + it('Should NOT BE ABLE to redelegate more stake to another identity than the delegator has', async () => { + const node1 = await createProfile(); + const node2 = await createProfile(accounts[0], accounts[2]); + const initialStake = hre.ethers.parseEther('100000'); + await Token.mint(accounts[0].address, initialStake); + await Token.connect(accounts[0]).approve( + await Staking.getAddress(), + initialStake, + ); + await Staking.stake(node1.identityId, initialStake); + await expect( + Staking.redelegate(node1.identityId, node2.identityId, initialStake + 1n), + ).to.be.revertedWithCustomError(Staking, 'WithdrawalExceedsStake'); + }); + /********************************************************************** + * Redelegation Nuances + **********************************************************************/ + + it('⛔️ Redelegate to the SAME node should revert', async () => { + const { identityId } = await createProfile(); + const stakeAmt = hre.ethers.parseEther('10'); + await Token.mint(accounts[0].address, stakeAmt); + await Token.connect(accounts[0]).approve( + await Staking.getAddress(), + stakeAmt, + ); + await Staking.stake(identityId, stakeAmt); + await expect( + Staking.redelegate(identityId, identityId, stakeAmt), + ).to.be.revertedWith('Cannot redelegate to the same node'); + }); + + it('⛔️ Redelegate that would overflow maximumStake on destination node should revert', async () => { + const max = await ParametersStorage.maximumStake(); + // create two nodes + const nodeSrc = await createProfile(); + const nodeDst = await createProfile(accounts[0], accounts[2]); + + // Stake maxStake – 5 to destination node via admin for simplicity + const nearMax = max - 5n; + await Token.mint(accounts[0].address, nearMax); + await Token.connect(accounts[0]).approve( + await Staking.getAddress(), + nearMax, + ); + await Staking.stake(nodeDst.identityId, nearMax); + + // Stake 10 on source node (so redelegating 10 would exceed by 5) + const stakeSrc = 10n; + await Token.mint(accounts[0].address, stakeSrc); + await Token.connect(accounts[0]).approve( + await Staking.getAddress(), + stakeSrc, + ); + await Staking.stake(nodeSrc.identityId, stakeSrc); + await expect( + Staking.redelegate(nodeSrc.identityId, nodeDst.identityId, stakeSrc), + ).to.be.revertedWithCustomError(Staking, 'MaximumStakeExceeded'); + }); + + it('✅ Redelegating full stake removes delegator from source node and adds to destination node', async () => { + const node1 = await createProfile(); + const node2 = await createProfile(accounts[0], accounts[2]); + + const amount = hre.ethers.parseEther('100'); + await Token.mint(accounts[0].address, amount); + await Token.connect(accounts[0]).approve( + await Staking.getAddress(), + amount, + ); + await Staking.stake(node1.identityId, amount); + + const dKey = hre.ethers.keccak256( + hre.ethers.solidityPacked(['address'], [accounts[0].address]), + ); + + // Preconditions + expect( + await DelegatorsInfo.isNodeDelegator( + node1.identityId, + accounts[0].address, + ), + ).to.equal(true, 'Delegator should be present on node1'); + expect( + await DelegatorsInfo.isNodeDelegator( + node2.identityId, + accounts[0].address, + ), + ).to.equal(false, 'Delegator should not be present on node2'); + expect( + await StakingStorage.getDelegatorStakeBase(node1.identityId, dKey), + ).to.equal(amount, 'Delegator stake should be equal to the amount'); + expect( + await StakingStorage.getDelegatorStakeBase(node2.identityId, dKey), + ).to.equal(0n, 'Delegator stake should be equal to 0'); + + // Redelegation + await Staking.redelegate(node1.identityId, node2.identityId, amount); + // Source node: delegator removed and stake zero + expect( + await StakingStorage.getDelegatorStakeBase(node1.identityId, dKey), + ).to.equal(0n, 'Delegator stake should be equal to 0'); + expect( + await DelegatorsInfo.isNodeDelegator( + node1.identityId, + accounts[0].address, + ), + ).to.equal(false, 'Delegator should not be present on node1'); + + // Destination node: delegator present and stake amount + expect( + await StakingStorage.getDelegatorStakeBase(node2.identityId, dKey), + ).to.equal(amount, 'Delegator stake should be equal to the amount '); + expect( + await DelegatorsInfo.isNodeDelegator( + node2.identityId, + accounts[0].address, + ), + ).to.equal(true, 'Delegator should be present on node2'); + }); + /********************************************************************** + * Withdrawal tests * + **********************************************************************/ + + it('Should revert finalizeWithdrawal if not requested', async () => { + const { identityId } = await createProfile(); + await expect( + Staking.finalizeWithdrawal(identityId), + ).to.be.revertedWithCustomError(Staking, 'WithdrawalWasntInitiated'); + }); + it('Should handle requestWithdrawal with zero tokens', async () => { const { identityId } = await createProfile(); await expect( @@ -237,7 +562,7 @@ describe('Staking contract', function () { ).to.be.revertedWithCustomError(Staking, 'WithdrawalExceedsStake'); }); - it('Should create a withdrawal request', async () => { + it('Should create a withdrawal request, and not be able to finalize it immediately', async () => { const { identityId } = await createProfile(); const amount = hre.ethers.parseEther('100'); await Token.mint(accounts[0].address, amount); @@ -247,17 +572,35 @@ describe('Staking contract', function () { ); await Staking.stake(identityId, amount); const delay = await ParametersStorage.stakeWithdrawalDelay(); - await Staking.requestWithdrawal(identityId, amount / 2n); + const tx = await Staking.requestWithdrawal(identityId, amount / 2n); + const block = await hre.ethers.provider.getBlock( + (await tx.wait())!.blockNumber, + ); + const requestTimestamp = block!.timestamp; const req = await StakingStorage.getDelegatorWithdrawalRequest( identityId, hre.ethers.keccak256( hre.ethers.solidityPacked(['address'], [accounts[0].address]), ), ); - expect(req[0]).to.equal(amount / 2n); - expect(req[2]).to.be.gte( - BigInt((await hre.ethers.provider.getBlock('latest'))!.timestamp) + delay, + expect(req[0]).to.equal( + amount / 2n, + 'Withdrawal amount should be equal to the half of the staked amount', + ); + expect(req[2]).to.equal( + BigInt(requestTimestamp) + delay, + 'Withdrawal request timestamp should be correct', ); + await expect( + Staking.finalizeWithdrawal(identityId), + ).to.be.revertedWithCustomError(Staking, 'WithdrawalPeriodPending'); + }); + + it('should not be able to finalize withdrawal if the request was not initiated', async () => { + const { identityId } = await createProfile(); + await expect( + Staking.finalizeWithdrawal(identityId), + ).to.be.revertedWithCustomError(Staking, 'WithdrawalWasntInitiated'); }); it('Should finalize withdrawal after delay', async () => { @@ -280,14 +623,10 @@ describe('Staking contract', function () { const balanceBefore = await Token.balanceOf(accounts[0].address); await Staking.finalizeWithdrawal(identityId); const balanceAfter = await Token.balanceOf(accounts[0].address); - expect(balanceAfter - balanceBefore).to.equal(amount / 2n); - }); - - it('Should revert finalizeWithdrawal if not requested', async () => { - const { identityId } = await createProfile(); - await expect( - Staking.finalizeWithdrawal(identityId), - ).to.be.revertedWithCustomError(Staking, 'WithdrawalWasntInitiated'); + expect(balanceAfter - balanceBefore).to.equal( + amount / 2n, + 'Balance should be equal to the half of the staked amount', + ); }); it('Should revert finalizeWithdrawal if too early', async () => { @@ -300,6 +639,13 @@ describe('Staking contract', function () { ); await Staking.stake(identityId, amount); await Staking.requestWithdrawal(identityId, amount / 2n); + const req = await StakingStorage.getDelegatorWithdrawalRequest( + identityId, + hre.ethers.keccak256( + hre.ethers.solidityPacked(['address'], [accounts[0].address]), + ), + ); + await time.increaseTo(req[2] - 10n); await expect( Staking.finalizeWithdrawal(identityId), ).to.be.revertedWithCustomError(Staking, 'WithdrawalPeriodPending'); @@ -322,7 +668,7 @@ describe('Staking contract', function () { hre.ethers.solidityPacked(['address'], [accounts[0].address]), ), ); - expect(req[0]).to.equal(0); + expect(req[0]).to.equal(0, 'Withdrawal amount should be equal to 0'); }); it('Should revert cancelWithdrawal if no request', async () => { @@ -332,745 +678,2081 @@ describe('Staking contract', function () { ).to.be.revertedWithCustomError(Staking, 'WithdrawalWasntInitiated'); }); - it('Should distribute rewards correctly', async () => { - const { identityId } = await createProfile(); - const amount = hre.ethers.parseEther('1000'); - await Token.mint(StakingStorage.getAddress(), amount); - await StakingStorage.setNodeStake(identityId, amount); - await expect( - Staking.distributeRewards(identityId, 0), - ).to.be.revertedWithCustomError(Staking, 'ZeroTokenAmount'); - await expect( - Staking.connect(accounts[1]).distributeRewards(identityId, 100), - ).to.be.reverted; // onlyContracts test depends on setup; skipping - }); + /********************************************************************** + * Operator fee tests * + **********************************************************************/ - it('Should restake operator fee', async () => { + it('Should revert if restake operator fee called with 0 tokens', async () => { const { identityId } = await createProfile(); await expect( Staking.restakeOperatorFee(identityId, 0), ).to.be.revertedWithCustomError(Staking, 'ZeroTokenAmount'); - // Additional logic for operator fee testing requires operator fee accumulation. - // Skipping a full operator fee integration test due to complexity. }); - it('Should request operator fee withdrawal', async () => { + it('Should revert restakeOperatorFee when amount exceeds operator fee balance', async () => { const { identityId } = await createProfile(); + // Seed small operator fee balance + await StakingStorage.setOperatorFeeBalance(identityId, 10n); + // Attempt to restake more than balance await expect( - Staking.requestOperatorFeeWithdrawal(identityId, 0), - ).to.be.revertedWithCustomError(Staking, 'ZeroTokenAmount'); - // Additional operator fee tests require accumulated fees; skipping full scenario. - }); - - it('Should finalize operator fee withdrawal', async () => { - const { identityId } = await createProfile(); - await expect( - Staking.finalizeOperatorFeeWithdrawal(identityId), - ).to.be.revertedWithCustomError(Staking, 'WithdrawalWasntInitiated'); + Staking.restakeOperatorFee(identityId, 11n), + ).to.be.revertedWithCustomError(Staking, 'AmountExceedsOperatorFeeBalance'); }); - it('Should cancel operator fee withdrawal', async () => { + it('Should restake operator fee successfully', async () => { + // 1. Create a node profile where msg.sender (accounts[0]) is admin const { identityId } = await createProfile(); - await expect( - Staking.cancelOperatorFeeWithdrawal(identityId), - ).to.be.revertedWithCustomError(Staking, 'WithdrawalWasntInitiated'); - }); - - it('Should revert if non-admin tries to restake operator fee or request operator fee withdrawal', async () => { - const { identityId } = await createProfile(); - await expect( - Staking.connect(accounts[1]).restakeOperatorFee(identityId, 100), - ).to.be.reverted; - await expect( - Staking.connect(accounts[1]).requestOperatorFeeWithdrawal( - identityId, - 100, - ), - ).to.be.reverted; - }); - - it('Should revert stake, requestWithdrawal, etc. on a non-existent profile', async () => { - await expect(Staking.stake(9999, 100)).to.be.revertedWithCustomError( - Staking, - 'ProfileDoesntExist', - ); - await expect( - Staking.requestWithdrawal(9999, 50), - ).to.be.revertedWithCustomError(Staking, 'ProfileDoesntExist'); - await expect( - Staking.finalizeWithdrawal(9999), - ).to.be.revertedWithCustomError(Staking, 'ProfileDoesntExist'); - await expect(Staking.cancelWithdrawal(9999)).to.be.revertedWithCustomError( - Staking, - 'ProfileDoesntExist', + // 2. Manually set operator fee balance via the Hub owner (onlyContracts passes for hub owner) + const feeBalance = hre.ethers.parseEther('100'); + await StakingStorage.connect(accounts[0]).setOperatorFeeBalance( + identityId, + feeBalance, ); - }); - it('Should simulateStakeInfoUpdate correctly', async () => { - const { identityId } = await createProfile(); - const amount = hre.ethers.parseEther('100'); + // 3. Stake 50000 tokens to the node + const amount = hre.ethers.parseEther('50000'); await Token.mint(accounts[0].address, amount); await Token.connect(accounts[0]).approve( await Staking.getAddress(), amount, ); await Staking.stake(identityId, amount); + expect(await StakingStorage.getNodeStake(identityId)).to.equal( + amount, + 'Node stake should be equal to the staked amount', + ); + expect( + await StakingStorage.getDelegatorStakeBase( + identityId, + hre.ethers.keccak256( + hre.ethers.solidityPacked(['address'], [accounts[0].address]), + ), + ), + ).to.equal(amount, 'Delegator stake should be equal to the staked amount'); + + // 4. Snapshot before restake + const nodeStakeBefore = await StakingStorage.getNodeStake(identityId); const delegatorKey = hre.ethers.keccak256( hre.ethers.solidityPacked(['address'], [accounts[0].address]), ); - const result = await Staking.simulateStakeInfoUpdate( + const delegatorStakeBefore = await StakingStorage.getDelegatorStakeBase( identityId, delegatorKey, ); - expect(result[0] + result[1]).to.be.gt(0); - }); - - it('Full scenario: Multiple nodes, delegators, operator fees, redelegations, partial withdrawals, cancellations, rewards', async () => { - console.log('--- START FULL SCENARIO TEST ---'); - - const admin1 = accounts[0]; - const op1 = accounts[1]; - const admin2 = accounts[2]; - const op2 = accounts[3]; - - console.log('Creating Node A with operator fee = 20%'); - const NodeA = await createProfile(admin1, op1, 20n); - console.log(`NodeA ID: ${NodeA.identityId}, operator fee: 20%`); - - console.log('Creating Node B with operator fee = 50%'); - const NodeB = await createProfile(admin2, op2, 50n); - console.log(`NodeB ID: ${NodeB.identityId}, operator fee: 50%`); - - const nodes = { - [NodeA.identityId]: 'A', - [NodeB.identityId]: 'B', - }; - - const d1 = accounts[4]; - const d2 = accounts[5]; - const d3 = accounts[6]; - const d4 = accounts[7]; - - const delegators = { - [d1.address]: 'd1', - [d2.address]: 'd2', - [d3.address]: 'd3', - [d4.address]: 'd4', - }; - - const delay = await ParametersStorage.stakeWithdrawalDelay(); - const minStake = await ParametersStorage.minimumStake(); - const maxStake = await ParametersStorage.maximumStake(); - const toEth = (amount: bigint) => Number(amount) / 1e18; - - const logNodeData = async (identityId: number) => { - const [ - stake, - rewardIndex, - cEarned, - cPaid, - opFeeBal, - opFeeEarned, - opFeePaid, - dCount, - ] = await StakingStorage.getNodeData(identityId); - console.log('----------------------------------------------------------'); - console.log(`Node${nodes[identityId]} Data: - Stake: ${toEth(BigInt(stake))} ETH, - RewardIndex: ${rewardIndex}, - CumulativeEarnedRewards: ${toEth(BigInt(cEarned))} ETH, - CumulativePaidOutRewards: ${toEth(BigInt(cPaid))} ETH, - OperatorFeeBalance: ${toEth(BigInt(opFeeBal))} ETH, - OperatorFeeCumulativeEarnedRewards: ${toEth(BigInt(opFeeEarned))} ETH, - OperatorFeeCumulativePaidOutRewards: ${toEth(BigInt(opFeePaid))} ETH, - DelegatorCount: ${dCount}`); - console.log('----------------------------------------------------------'); - }; - - const logDelegatorData = async ( - identityId: number, - delegator: SignerWithAddress, - ) => { - const dKey = hre.ethers.keccak256( - hre.ethers.solidityPacked(['address'], [delegator.address]), - ); - const [dBase, dIndexed, dLastIndex, dEarned, dPaid] = - await StakingStorage.getDelegatorData(identityId, dKey); - console.log('----------------------------------------------------------'); - console.log(`Delegator ${delegators[delegator.address]} on Node${nodes[identityId]}: - BaseStake: ${toEth(BigInt(dBase))} ETH, - IndexedStake: ${toEth(BigInt(dIndexed))} ETH, - LastRewardIndex: ${dLastIndex}, - CumulativeEarnedRewards: ${toEth(BigInt(dEarned))} ETH, - CumulativePaidOutRewards: ${toEth(BigInt(dPaid))} ETH`); - console.log('----------------------------------------------------------'); - }; - - console.log( - `Minimum stake: ${toEth(minStake)} ETH, Maximum stake: ${toEth(maxStake)} ETH, Delay: ${delay}s`, - ); - - const stakeA = minStake * 2n; - console.log(`Minting ${toEth(stakeA)} ETH to d1 and staking on NodeA`); - await Token.mint(d1.address, stakeA); - await Token.connect(d1).approve(Staking.getAddress(), stakeA); - console.log(`d1 stakes ${toEth(stakeA)} ETH on NodeA`); - await Staking.connect(d1).stake(NodeA.identityId, stakeA); - - await logNodeData(NodeA.identityId); - await logDelegatorData(NodeA.identityId, d1); - - const stakeB = minStake - 1n; - console.log( - `Minting ${toEth(stakeB)} ETH to d3 and staking on NodeB (just below min)`, + const opFeeBalanceBefore = + await StakingStorage.getOperatorFeeBalance(identityId); + const stakingBalanceBefore = await Token.balanceOf( + await StakingStorage.getAddress(), ); - await Token.mint(d3.address, stakeB); - await Token.connect(d3).approve(Staking.getAddress(), stakeB); - console.log(`d3 stakes ${toEth(stakeB)} ETH on NodeB`); - await Staking.connect(d3).stake(NodeB.identityId, stakeB); - await logNodeData(NodeB.identityId); - await logDelegatorData(NodeB.identityId, d3); + // 4. Restake a portion of the operator fee + const restakeAmount = hre.ethers.parseEther('40'); + await Staking.restakeOperatorFee(identityId, restakeAmount); - console.log('Distributing 100 tokens reward to NodeA'); - const rewardA1 = hre.ethers.parseEther('100'); - await Token.mint(StakingStorage.getAddress(), rewardA1); - console.log(`Distributing reward: ${toEth(rewardA1)} ETH to NodeA`); - await Staking.distributeRewards(NodeA.identityId, rewardA1); - - await logNodeData(NodeA.identityId); - await logDelegatorData(NodeA.identityId, d1); - - const partialWithdraw = hre.ethers.parseEther('10'); - console.log( - `d1 requests withdrawal of ${toEth(partialWithdraw)} ETH from NodeA`, + // 5. Snapshot after restake + const nodeStakeAfter = await StakingStorage.getNodeStake(identityId); + const delegatorStakeAfter = await StakingStorage.getDelegatorStakeBase( + identityId, + delegatorKey, ); - await Staking.connect(d1).requestWithdrawal( - NodeA.identityId, - partialWithdraw, + const opFeeBalanceAfter = + await StakingStorage.getOperatorFeeBalance(identityId); + const stakingBalanceAfter = await Token.balanceOf( + await StakingStorage.getAddress(), ); - await time.increase(Number(delay)); - const d1BalanceBefore = await Token.balanceOf(d1.address); - console.log( - `Finalizing withdrawal for d1. d1 balance before: ${toEth(d1BalanceBefore)} ETH`, - ); - await Staking.connect(d1).finalizeWithdrawal(NodeA.identityId); - const d1BalanceAfter = await Token.balanceOf(d1.address); - console.log( - `Withdrawal finalized. d1 balance after: ${toEth(d1BalanceAfter)} ETH, diff: ${toEth(d1BalanceAfter - d1BalanceBefore)} ETH`, + // 6. Assertions + expect(opFeeBalanceAfter).to.equal( + opFeeBalanceBefore - restakeAmount, + 'Operator fee balance should be reduced by the restaked amount', ); - - await logNodeData(NodeA.identityId); - await logDelegatorData(NodeA.identityId, d1); - - console.log('d2 increases stake on NodeA so it has more to redelegate'); - await Token.mint(d2.address, minStake); - await Token.connect(d2).approve(Staking.getAddress(), minStake); - console.log(`d2 stakes ${toEth(minStake)} ETH on NodeA`); - await Staking.connect(d2).stake(NodeA.identityId, minStake); - - await logNodeData(NodeA.identityId); - await logDelegatorData(NodeA.identityId, d2); - - const nodeBCurrentStake = await StakingStorage.getNodeStake( - NodeB.identityId, + expect(nodeStakeAfter).to.equal( + nodeStakeBefore + restakeAmount, + 'Node stake should be increased by the restaked amount', ); - const neededForMin = minStake - nodeBCurrentStake; - console.log( - `Redelegating from NodeA to NodeB by d2, needed for min: ${toEth(neededForMin)} ETH`, + expect(delegatorStakeAfter).to.equal( + delegatorStakeBefore + restakeAmount, + 'Delegator stake should be increased by the restaked amount', ); - await Staking.connect(d2).redelegate( - NodeA.identityId, - NodeB.identityId, - neededForMin, + expect(stakingBalanceAfter - stakingBalanceBefore).to.equal( + 0, + 'StakingStorage contract balance should not change', ); + }); - await logNodeData(NodeA.identityId); - await logNodeData(NodeB.identityId); - await logDelegatorData(NodeA.identityId, d2); - // For brevity, not logging all delegators after every single operation, - // but in practice, do it for all delegators to ensure full overview. - - console.log('Distributing 200 tokens reward to NodeB with 50% fee'); - const rewardB1 = hre.ethers.parseEther('200'); - await Token.mint(StakingStorage.getAddress(), rewardB1); - console.log(`Distributing reward: ${toEth(rewardB1)} ETH to NodeB`); - await Staking.distributeRewards(NodeB.identityId, rewardB1); + /********************************************************************** + * Operator fee withdrawal tests + **********************************************************************/ - await logNodeData(NodeB.identityId); + it('Should request and finalize operator fee withdrawal successfully', async () => { + const { identityId } = await createProfile(); - const d3Key = hre.ethers.keccak256( - hre.ethers.solidityPacked(['address'], [d3.address]), - ); - const [d3BaseB, d3IndexedB] = await StakingStorage.getDelegatorStakeInfo( - NodeB.identityId, - d3Key, - ); - const d3TotalB = d3BaseB + d3IndexedB; - const largeWithdraw = d3TotalB / 2n; - console.log( - `d3 tries to withdraw large amount: ${toEth(largeWithdraw)} ETH from NodeB`, - ); - await Staking.connect(d3).requestWithdrawal( - NodeB.identityId, - largeWithdraw, + // Seed operator fee balance directly + const initialFeeBalance = hre.ethers.parseEther('100'); + await StakingStorage.connect(accounts[0]).setOperatorFeeBalance( + identityId, + initialFeeBalance, ); + // Also mint equivalent tokens to the StakingStorage contract so it can transfer them out + await Token.mint(await StakingStorage.getAddress(), initialFeeBalance); - await logDelegatorData(NodeB.identityId, d3); + // Request withdrawal for half of the balance + const withdrawalAmount = hre.ethers.parseEther('50'); + const delay = await ParametersStorage.stakeWithdrawalDelay(); + const tx = await Staking.requestOperatorFeeWithdrawal( + identityId, + withdrawalAmount, + ); + const tsReq = (await hre.ethers.provider.getBlock( + (await tx.wait()).blockNumber, + ))!.timestamp; - console.log('d3 cancels withdrawal before finalizing'); - await Staking.connect(d3).cancelWithdrawal(NodeB.identityId); - const canceledReq = await StakingStorage.getDelegatorWithdrawalRequest( - NodeB.identityId, - d3Key, + const [storedAmount, , releaseTs] = + await StakingStorage.getOperatorFeeWithdrawalRequest(identityId); + expect(storedAmount).to.equal( + withdrawalAmount, + 'Stored amount should be equal to the withdrawal amount', ); - console.log( - `Withdrawal request for d3 after cancel: ${canceledReq[0]} (should be 0)`, + expect(releaseTs).to.equal( + tsReq + Number(delay), + 'Release timestamp should be equal to the request timestamp plus the delay', ); - await logDelegatorData(NodeB.identityId, d3); - - console.log('Operator fee withdrawal on NodeA'); - const operatorFeeBalanceBefore = await StakingStorage.getOperatorFeeBalance( - NodeA.identityId, - ); - const opFeeWithdrawAmount = operatorFeeBalanceBefore / 2n; - console.log( - `Requesting operator fee withdrawal on NodeA: ${toEth(opFeeWithdrawAmount)} ETH from total ${toEth(operatorFeeBalanceBefore)} ETH`, + // Advance time and finalize + await time.increaseTo(BigInt(releaseTs)); + const balanceBefore = await Token.balanceOf(accounts[0].address); + const stakingStorageBalanceBefore = await Token.balanceOf( + await StakingStorage.getAddress(), ); - await Staking.connect(admin1).requestOperatorFeeWithdrawal( - NodeA.identityId, - opFeeWithdrawAmount, + await Staking.finalizeOperatorFeeWithdrawal(identityId); + const balanceAfter = await Token.balanceOf(accounts[0].address); + const stakingStorageBalanceAfter = await Token.balanceOf( + await StakingStorage.getAddress(), ); - await time.increase(Number(delay)); - const admin1BalanceBefore = await Token.balanceOf(admin1.address); - console.log( - `Finalizing operator fee withdrawal for NodeA. admin1 balance before: ${toEth(admin1BalanceBefore)} ETH`, + expect(balanceAfter - balanceBefore).to.equal( + withdrawalAmount, + 'Balance should be equal to the withdrawal amount', ); - await Staking.connect(admin1).finalizeOperatorFeeWithdrawal( - NodeA.identityId, + expect(await StakingStorage.getOperatorFeeBalance(identityId)).to.equal( + initialFeeBalance - withdrawalAmount, + 'Operator fee balance should be reduced by the withdrawal amount', ); - const admin1BalanceAfter = await Token.balanceOf(admin1.address); - console.log( - `Operator fee withdrawal finalized. admin1 balance after: ${toEth(admin1BalanceAfter)} ETH, diff: ${toEth(admin1BalanceAfter - admin1BalanceBefore)} ETH`, + expect(stakingStorageBalanceBefore - stakingStorageBalanceAfter).to.equal( + withdrawalAmount, + 'StakingStorage contract balance should be lowered by the withdrawal amount', ); + }); + + it('Should revert finalizeOperatorFeeWithdrawal if called too early', async () => { + const { identityId } = await createProfile(); + const feeBal = hre.ethers.parseEther('20'); + // set operator fee balance + await StakingStorage.connect(accounts[0]).setOperatorFeeBalance( + identityId, + feeBal, + ); + // request withdrawal + const withdrawAmt = hre.ethers.parseEther('10'); + await Staking.requestOperatorFeeWithdrawal(identityId, withdrawAmt); + await expect( + Staking.finalizeOperatorFeeWithdrawal(identityId), + ).to.be.revertedWithCustomError(Staking, 'WithdrawalPeriodPending'); + }); + + it('Should revert requestOperatorFeeWithdrawal when amount exceeds balance', async () => { + const { identityId } = await createProfile(); + const feeBal = hre.ethers.parseEther('30'); + // set operator fee balance + await StakingStorage.connect(accounts[0]).setOperatorFeeBalance( + identityId, + feeBal, + ); + // mint tokens to the StakingStorage contract + await Token.mint(await StakingStorage.getAddress(), feeBal); + // attempt to request withdrawal with amount exceeding balance -> should revert + await expect( + Staking.requestOperatorFeeWithdrawal(identityId, feeBal + 1n), + ).to.be.revertedWithCustomError(Staking, 'AmountExceedsOperatorFeeBalance'); + }); + + it('Should revert requestOperatorFeeWithdrawal with zero amount', async () => { + const { identityId } = await createProfile(); + // attempt to request withdrawal with zero amount -> should revert + await expect( + Staking.requestOperatorFeeWithdrawal(identityId, 0), + ).to.be.revertedWithCustomError(Staking, 'ZeroTokenAmount'); + }); + + it('Should allow restake of remaining operator fee while a withdrawal is pending', async () => { + const { identityId } = await createProfile(); + const feeBal = hre.ethers.parseEther('60'); + await StakingStorage.connect(accounts[0]).setOperatorFeeBalance( + identityId, + feeBal, + ); + await Token.mint(await StakingStorage.getAddress(), feeBal); + // initiate withdrawal of 40 + const withdrawFirst = hre.ethers.parseEther('40'); + await Staking.requestOperatorFeeWithdrawal(identityId, withdrawFirst); + + // Remaining operator fee balance is 20; restake 10 + const restakeAmt = hre.ethers.parseEther('10'); + const nodeStakeBefore = await StakingStorage.getNodeStake(identityId); + const delegatorKey = hre.ethers.keccak256( + hre.ethers.solidityPacked(['address'], [accounts[0].address]), + ); + const delegatorStakeBefore = await StakingStorage.getDelegatorStakeBase( + identityId, + delegatorKey, + ); + + // restake + await Staking.restakeOperatorFee(identityId, restakeAmt); + + // assertions + expect(await StakingStorage.getOperatorFeeBalance(identityId)).to.equal( + feeBal - withdrawFirst - restakeAmt, + 'Operator fee balance should be reduced by the withdrawal amount and the restaked amount', + ); + expect(await StakingStorage.getNodeStake(identityId)).to.equal( + nodeStakeBefore + restakeAmt, + 'Node stake should be increased by the restaked amount', + ); + expect( + await StakingStorage.getDelegatorStakeBase(identityId, delegatorKey), + ).to.equal( + delegatorStakeBefore + restakeAmt, + 'Delegator stake should be increased by the restaked amount', + ); + }); + + it('finalizeOperatorFeeWithdrawal second call reverts', async () => { + const { identityId } = await createProfile(); + const feeBal = hre.ethers.parseEther('20'); + // set operator fee balance + await StakingStorage.connect(accounts[0]).setOperatorFeeBalance( + identityId, + feeBal, + ); + // request withdrawal + const withdrawAmt = hre.ethers.parseEther('10'); + await Staking.requestOperatorFeeWithdrawal(identityId, withdrawAmt); + const [, , ts] = + await StakingStorage.getOperatorFeeWithdrawalRequest(identityId); + await Token.mint(await StakingStorage.getAddress(), feeBal); + await time.increaseTo(BigInt(ts)); + await Staking.finalizeOperatorFeeWithdrawal(identityId); + expect(await StakingStorage.getOperatorFeeBalance(identityId)).to.equal( + feeBal - withdrawAmt, + 'Balance should be equal to feeBal - withdrawAmt', + ); + const [reqAmount] = + await StakingStorage.getOperatorFeeWithdrawalRequest(identityId); + expect(reqAmount).to.equal(0n, 'Withdrawal request should be cleared'); + + await expect( + Staking.finalizeOperatorFeeWithdrawal(identityId), + ).to.be.revertedWithCustomError(Staking, 'WithdrawalWasntInitiated'); + }); + + /********************************************************************** + * Staking before claiming rewards tests * + **********************************************************************/ + + it('Should revert additional staking if previous epoch rewards not claimed', async () => { + // create profile + const { identityId } = await createProfile(); + const stakeAmt = hre.ethers.parseEther('1000'); + // mint and stake + await Token.mint(accounts[0].address, stakeAmt); + await Token.connect(accounts[0]).approve( + await Staking.getAddress(), + stakeAmt, + ); + await Staking.stake(identityId, stakeAmt); + + // move to next epoch + const Chronos = await hre.ethers.getContract('Chronos'); + const ttn = await Chronos.timeUntilNextEpoch(); + await time.increase(ttn + 1n); + const currentEpoch = await Chronos.getCurrentEpoch(); + const prevEpoch = currentEpoch - 1n; + + // Add delegator score to simulate earnings in prev epoch + const delegatorKey = hre.ethers.keccak256( + hre.ethers.solidityPacked(['address'], [accounts[0].address]), + ); + await RandomSamplingStorage.addToEpochNodeDelegatorScore( + prevEpoch, + identityId, + delegatorKey, + 1, + ); + + // attempt to stake more -> should revert + await Token.mint(accounts[0].address, 1n); + await Token.connect(accounts[0]).approve(await Staking.getAddress(), 1n); + await expect(Staking.stake(identityId, 1n)).to.be.revertedWith( + 'Must claim the previous epoch rewards before changing stake', + ); + }); + + it('Should revert withdrawal request if previous epoch rewards not claimed', async () => { + const { identityId } = await createProfile(); + const stakeAmt = hre.ethers.parseEther('1000'); + // mint and stake + await Token.mint(accounts[0].address, stakeAmt); + await Token.connect(accounts[0]).approve( + await Staking.getAddress(), + stakeAmt, + ); + await Staking.stake(identityId, stakeAmt); + // move to next epoch + const Chronos = await hre.ethers.getContract('Chronos'); + const ttn = await Chronos.timeUntilNextEpoch(); + await time.increase(ttn + 1n); + const currentEpoch = await Chronos.getCurrentEpoch(); + const prevEpoch = currentEpoch - 1n; + + const delegatorKey = hre.ethers.keccak256( + hre.ethers.solidityPacked(['address'], [accounts[0].address]), + ); + await RandomSamplingStorage.addToEpochNodeDelegatorScore( + prevEpoch, + identityId, + delegatorKey, + 1, + ); + // attempt to request withdrawal -> should revert + await expect(Staking.requestWithdrawal(identityId, 1n)).to.be.revertedWith( + 'Must claim the previous epoch rewards before changing stake', + ); + }); + + /********************************************************************** + * Epoch-claim dependency tests + **********************************************************************/ + + it('⛔️ Should revert stake change when previous epochs rewards are unclaimed', async () => { + const { identityId } = await createProfile(); + const initialStake = hre.ethers.parseEther('500'); + // mint and stake + await Token.mint(accounts[0].address, initialStake); + await Token.connect(accounts[0]).approve( + await Staking.getAddress(), + initialStake, + ); + await Staking.stake(identityId, initialStake); + let currentEpoch = await Chronos.getCurrentEpoch(); + + // Add delegator score to simulate earnings in prev epoch + const delegatorKey = hre.ethers.keccak256( + hre.ethers.solidityPacked(['address'], [accounts[0].address]), + ); + await RandomSamplingStorage.addToEpochNodeDelegatorScore( + currentEpoch, + identityId, + delegatorKey, + 1, + ); + + // Fast-forward 3 epochs ➡️ currentEpoch = 4 + const tlen = await Chronos.epochLength(); + await time.increase(tlen * 3n + 3n); + currentEpoch = await Chronos.getCurrentEpoch(); + + // Attempt to stake +1 wei without having claimed + await Token.mint(accounts[0].address, 1n); + await Token.connect(accounts[0]).approve(await Staking.getAddress(), 1n); + await expect(Staking.stake(identityId, 1n)).to.be.revertedWith( + 'Must claim all previous epoch rewards before changing stake', + ); + }); + + it('⛔️ Should revert adding stake when only some epochs are claimed', async () => { + const { identityId } = await createProfile(); + const amount = hre.ethers.parseEther('500'); + const initialEpoch = await Chronos.getCurrentEpoch(); + // mint and stake + await Token.mint(accounts[0].address, amount); + await Token.connect(accounts[0]).approve( + await Staking.getAddress(), + amount, + ); + await Staking.stake(identityId, amount); + + // Add delegator score to simulate earnings in initial epoch and next epoch + const delegatorKey = hre.ethers.keccak256( + hre.ethers.solidityPacked(['address'], [accounts[0].address]), + ); + await RandomSamplingStorage.addToEpochNodeDelegatorScore( + initialEpoch, + identityId, + delegatorKey, + 1, + ); + await RandomSamplingStorage.addToEpochNodeDelegatorScore( + initialEpoch + 1n, + identityId, + delegatorKey, + 2, + ); + + // Fast-forward 3 epochs + const len = await Chronos.epochLength(); + await time.increase(len * 3n + 3n); + + // Claim rewards for initial epoch + await Staking.claimDelegatorRewards( + identityId, + initialEpoch, + accounts[0].address, + ); + + // Try to stake — should still revert + await Token.mint(accounts[0].address, 1n); + await Token.connect(accounts[0]).approve(await Staking.getAddress(), 1n); + await expect(Staking.stake(identityId, 1n)).to.be.revertedWith( + 'Must claim all previous epoch rewards before changing stake', + ); + + // Claim all rewards, then staking should succeed + await Staking.claimDelegatorRewards( + identityId, + initialEpoch + 1n, + accounts[0].address, + ); + + // Try to stake — should still revert + await Token.mint(accounts[0].address, 1n); + await Token.connect(accounts[0]).approve(await Staking.getAddress(), 1n); + await Staking.stake(identityId, 1n); + expect(await StakingStorage.getNodeStake(identityId)).to.equal( + amount + 1n, + 'staking successful after claiming all rewards', + ); + }); + + it('⛔️ Should revert restaking operator fee when only some epochs are claimed', async () => { + const { identityId } = await createProfile(); + const { identityId: destId } = await createProfile(undefined, accounts[3]); + const stakeBase = hre.ethers.parseEther('500'); + // Stake base so node exists + await Token.mint(accounts[0].address, stakeBase); + await Token.connect(accounts[0]).approve( + await Staking.getAddress(), + stakeBase, + ); + await Staking.stake(identityId, stakeBase); + + // create rewards in epoch0 and epoch1 + const startEpoch = await Chronos.getCurrentEpoch(); + const dKey = hre.ethers.keccak256( + hre.ethers.solidityPacked(['address'], [accounts[0].address]), + ); + await RandomSamplingStorage.addToEpochNodeDelegatorScore( + startEpoch, + identityId, + dKey, + 1, + ); + await RandomSamplingStorage.addToNodeEpochScore(startEpoch, identityId, 1); + await RandomSamplingStorage.addToAllNodesEpochScore(startEpoch, 1); + await EpochStorage.addTokensToEpochRange( + 1, + startEpoch, + startEpoch, + hre.ethers.parseEther('10'), + ); + + // advance one epoch and add more rewards + const len = await Chronos.epochLength(); + await time.increase(len + 2n); + const secondEpoch = await Chronos.getCurrentEpoch(); + await RandomSamplingStorage.addToEpochNodeDelegatorScore( + secondEpoch, + identityId, + dKey, + 2, + ); + await RandomSamplingStorage.addToNodeEpochScore(secondEpoch, identityId, 2); + await RandomSamplingStorage.addToAllNodesEpochScore(secondEpoch, 2); + await EpochStorage.addTokensToEpochRange( + 1, + secondEpoch, + secondEpoch, + hre.ethers.parseEther('10'), + ); + + // advance another epoch so both epochs are claimable + await time.increase(len + 2n); + + // Claim only first epoch + await Staking.claimDelegatorRewards( + identityId, + startEpoch, + accounts[0].address, + ); + + // Attempt to redelegate 1 wei – expect revert due to unclaimed second epoch + await expect(Staking.redelegate(identityId, destId, 1n)).to.be.revertedWith( + 'Must claim the previous epoch rewards before changing stake', + ); + + // Claim remaining epoch and then redelegation should succeed + await Staking.claimDelegatorRewards( + identityId, + secondEpoch, + accounts[0].address, + ); + + const sourceBefore = await StakingStorage.getNodeStake(identityId); + const destBefore = await StakingStorage.getNodeStake(destId); + + await expect(Staking.redelegate(identityId, destId, 1n)).to.not.be.reverted; + + expect(await StakingStorage.getNodeStake(identityId)).to.equal( + sourceBefore - 1n, + ); + expect(await StakingStorage.getNodeStake(destId)).to.equal(destBefore + 1n); + }); + + it('✅ Should allow stake change after all previous rewards claimed', async () => { + const { identityId } = await createProfile(); + const baseStake = hre.ethers.parseEther('500'); + await Token.mint(accounts[0].address, baseStake); + await Token.connect(accounts[0]).approve( + await Staking.getAddress(), + baseStake, + ); + // stake + await Staking.stake(identityId, baseStake); + const initialEpoch = await Chronos.getCurrentEpoch(); + + const delegatorKey = hre.ethers.keccak256( + hre.ethers.solidityPacked(['address'], [accounts[0].address]), + ); + await RandomSamplingStorage.addToEpochNodeDelegatorScore( + initialEpoch + 1n, + identityId, + delegatorKey, + 1, + ); + + const epochLen = await Chronos.epochLength(); + // fast-forward 3 epochs + await time.increase(epochLen * 3n + 3n); + + // Pretend all rewards claimed up to prevEp + await Staking.claimDelegatorRewards( + identityId, + initialEpoch, + accounts[0].address, + ); + await Staking.claimDelegatorRewards( + identityId, + initialEpoch + 1n, + accounts[0].address, + ); + + // Stake additional 1 wei – should pass + await Token.mint(accounts[0].address, 1n); + await Token.connect(accounts[0]).approve(await Staking.getAddress(), 1n); + await expect(Staking.stake(identityId, 1n)).to.not.be.reverted; + expect(await StakingStorage.getNodeStake(identityId)).to.equal( + baseStake + 1n, + ); + }); + + /********************************************************************** + * Boundary & Limit tests + **********************************************************************/ + + it('✅ Stake exactly maximumStake should succeed, +1 wei should revert', async () => { + const { identityId } = await createProfile(); + const maxStake = await ParametersStorage.maximumStake(); + + await Token.mint(accounts[0].address, maxStake); + await Token.connect(accounts[0]).approve( + await Staking.getAddress(), + maxStake, + ); + await expect(Staking.stake(identityId, maxStake)).to.not.be.reverted; + expect(await StakingStorage.getNodeStake(identityId)).to.equal(maxStake); + + await Token.mint(accounts[0].address, 1n); + await Token.connect(accounts[0]).approve(await Staking.getAddress(), 1n); + await expect(Staking.stake(identityId, 1n)).to.be.revertedWithCustomError( + Staking, + 'MaximumStakeExceeded', + ); + }); + + it('⛔️ Restake operator fee that pushes above maximumStake should revert', async () => { + const { identityId } = await createProfile(); + const maxStake = await ParametersStorage.maximumStake(); + + // stake maxStake - 5 + const base = maxStake - 5n; + await Token.mint(accounts[0].address, base); + await Token.connect(accounts[0]).approve(await Staking.getAddress(), base); + await Staking.stake(identityId, base); + // set operator fee balance to 10 TRAC + const opFee = 10n; + await StakingStorage.connect(accounts[0]).setOperatorFeeBalance( + identityId, + opFee, + ); + + await expect( + Staking.restakeOperatorFee(identityId, 6n), + ).to.be.revertedWithCustomError(Staking, 'MaximumStakeExceeded'); + }); + + /********************************************************************** + * rollingRewards & cumulativeEarned / cumulativePaidOut + **********************************************************************/ + + it('📊 rollingRewards accumulate & auto-restake; earned / paidOut updated', async () => { + const { identityId } = await createProfile(); + const SCALE18 = hre.ethers.parseUnits('1', 18); + + /* 1️⃣ Stake once in epoch-1 */ + const stakeBase = hre.ethers.parseEther('1000'); + await Token.mint(accounts[0].address, stakeBase); + await Token.connect(accounts[0]).approve( + await Staking.getAddress(), + stakeBase, + ); + await Staking.stake(identityId, stakeBase); + + const dKey = hre.ethers.keccak256( + hre.ethers.solidityPacked(['address'], [accounts[0].address]), + ); + + /* helper to create "rewards" for an epoch */ + // Inject rewards for epoch-1 immediately so first claim yields rolling rewards + const epoch1 = await Chronos.getCurrentEpoch(); + await RandomSamplingStorage.addToNodeEpochScore( + epoch1, + identityId, + SCALE18, + ); + await RandomSamplingStorage.addToAllNodesEpochScore(epoch1, SCALE18); + await RandomSamplingStorage.addToEpochNodeDelegatorScore( + epoch1, + identityId, + dKey, + SCALE18, + ); + const tokenRewards1 = hre.ethers.parseEther('20'); + await EpochStorage.addTokensToEpochRange(1, epoch1, epoch1, tokenRewards1); + + /* 2️⃣ Produce rewards for epoch-2 and epoch-3 */ + const len = await Chronos.epochLength(); + await time.increase(len + 2n); // -> epoch-2 + const epoch2 = await Chronos.getCurrentEpoch(); + await RandomSamplingStorage.addToNodeEpochScore( + epoch2, + identityId, + SCALE18, + ); + await RandomSamplingStorage.addToAllNodesEpochScore(epoch2, SCALE18); + await RandomSamplingStorage.addToEpochNodeDelegatorScore( + epoch2, + identityId, + dKey, + SCALE18, + ); + const tokenRewards2 = hre.ethers.parseEther('30'); + await EpochStorage.addTokensToEpochRange(1, epoch2, epoch2, tokenRewards2); + + await time.increase(len + 2n); // -> epoch-3 + const epoch3 = await Chronos.getCurrentEpoch(); + await RandomSamplingStorage.addToNodeEpochScore( + epoch3, + identityId, + SCALE18, + ); + await RandomSamplingStorage.addToAllNodesEpochScore(epoch3, SCALE18); + await RandomSamplingStorage.addToEpochNodeDelegatorScore( + epoch3, + identityId, + dKey, + SCALE18, + ); + const tokenRewards3 = hre.ethers.parseEther('40'); + await EpochStorage.addTokensToEpochRange(1, epoch3, epoch3, tokenRewards3); + + /* 3️⃣ Move to epoch-4 so gap > 1 and claim epoch-3-1 (= epoch-3?) Actually previousEpoch will be 3 */ + await time.increase(len + 2n); // -> epoch-4 + const epoch4 = await Chronos.getCurrentEpoch(); // claim epoch-1 first (oldest unclaimed) + + await Staking.claimDelegatorRewards( + identityId, + epoch1, + accounts[0].address, + ); + const rolling1 = await DelegatorsInfo.getDelegatorRollingRewards( + identityId, + accounts[0].address, + ); + + expect(rolling1).to.equal( + tokenRewards1, + 'Rolling rewards should be equal to tokenRewards1', + ); + + /* cumulativeEarned should have grown, cumulativePaidOut unchanged (0) */ + const [earned1, paid1] = await StakingStorage.getDelegatorRewardsInfo( + identityId, + dKey, + ); + expect(earned1).to.equal( + tokenRewards1, + 'Earned rewards should equal rewards from epoch 1 after first claim', + ); + expect(paid1).to.equal(0n, 'Paid should be 0'); + + /* 4️⃣ Claim next epoch (gap ≤ 1) – rollingRewards should auto-restake */ + const secondClaimEpoch = epoch2; // claim epoch-2 next (gap ≤1) + await Staking.claimDelegatorRewards( + identityId, + secondClaimEpoch, + accounts[0].address, + ); + + const rolling2 = await DelegatorsInfo.getDelegatorRollingRewards( + identityId, + accounts[0].address, + ); + expect(rolling2).to.be.gt( + 0n, + 'rollingRewards should still be accumulating', + ); + console.log(' Rolling rewards still accumulating'); + + /* 5️⃣ Claim epoch3 now (prev epoch) — triggers auto-restake */ + const thirdClaimEpoch = epoch4 - 1n; // == epoch3 + console.log( + '🌱 Claiming epoch', + thirdClaimEpoch, + 'to trigger auto-restake', + ); + await Staking.claimDelegatorRewards( + identityId, + thirdClaimEpoch, + accounts[0].address, + ); + + const rolling3 = await DelegatorsInfo.getDelegatorRollingRewards( + identityId, + accounts[0].address, + ); + expect(rolling3).to.equal( + 0n, + 'rollingRewards must be zero after auto-restake', + ); + console.log(' Rolling rewards reset to zero'); + + const finalStake = await StakingStorage.getDelegatorStakeBase( + identityId, + dKey, + ); + expect(finalStake).to.be.gt( + stakeBase, + 'Final stake should grow after auto-restake', + ); + + const [earned2, paid2] = await StakingStorage.getDelegatorRewardsInfo( + identityId, + dKey, + ); + expect(earned2).to.be.gt(earned1, 'Earned should grow'); + expect(paid2).to.equal(0n, 'Paid stays zero'); + + /* 6️⃣ restakeOperatorFee does NOT touch earned/paidOut */ + console.log(' Setting operator fee balance to 10 TRAC'); + await StakingStorage.setOperatorFeeBalance(identityId, 10n); + console.log(' Restaking operator fee'); + await Staking.restakeOperatorFee(identityId, 5n); + const [earned3, paid3] = await StakingStorage.getDelegatorRewardsInfo( + identityId, + dKey, + ); + console.log(' Earned assertion passed'); + expect(earned3).to.equal(earned2, 'Earned should be equal to earned2'); + console.log(' Paid assertion passed'); + expect(paid3).to.equal(paid2, 'Paid should be equal to paid2'); + console.log(' Paid assertion passed'); + }); + + /******************* rolling rewards accumulate then flush ***********/ + it('rolling rewards accumulate over multiple epochs then flush into stake', async () => { + const { identityId } = await createProfile(); + const stakeAmt = hre.ethers.parseEther('100'); + await Token.mint(accounts[0].address, stakeAmt); + await Token.connect(accounts[0]).approve( + await Staking.getAddress(), + stakeAmt, + ); + await Staking.stake(identityId, stakeAmt); + + const dKey = hre.ethers.keccak256( + hre.ethers.solidityPacked(['address'], [accounts[0].address]), + ); + const SCALE18 = hre.ethers.parseUnits('1', 18); + // epoch1 & epoch2 add scores + const ep1 = await Chronos.getCurrentEpoch(); + await RandomSamplingStorage.addToEpochNodeDelegatorScore( + ep1, + identityId, + dKey, + SCALE18, + ); + await RandomSamplingStorage.addToAllNodesEpochScore(ep1, SCALE18); + await RandomSamplingStorage.addToNodeEpochScore(ep1, identityId, SCALE18); + await EpochStorage.addTokensToEpochRange( + 1, + ep1, + ep1, + hre.ethers.parseEther('10'), + ); + // advance epoch + await time.increase((await Chronos.timeUntilNextEpoch()) + 1n); + const ep2 = await Chronos.getCurrentEpoch(); + await RandomSamplingStorage.addToEpochNodeDelegatorScore( + ep2, + identityId, + dKey, + SCALE18, + ); + await RandomSamplingStorage.addToAllNodesEpochScore(ep2, SCALE18); + await RandomSamplingStorage.addToNodeEpochScore(ep2, identityId, SCALE18); + await EpochStorage.addTokensToEpochRange( + 1, + ep2, + ep2, + hre.ethers.parseEther('10'), + ); + await time.increase((await Chronos.timeUntilNextEpoch()) + 1n); + + // Claim epoch2 only (epoch1 older) should revert first + await expect( + Staking.claimDelegatorRewards(identityId, ep2, accounts[0].address), + ).to.be.revertedWith('Must claim older epochs first'); + + // Claim epoch1 → rolling should accumulate (but not restake) + await Staking.claimDelegatorRewards(identityId, ep1, accounts[0].address); + expect( + await DelegatorsInfo.getDelegatorRollingRewards( + identityId, + accounts[0].address, + ), + ).to.be.gt(0); + + // Claim epoch2 now – rolling flushed to stake + await Staking.claimDelegatorRewards(identityId, ep2, accounts[0].address); + expect( + await DelegatorsInfo.getDelegatorRollingRewards( + identityId, + accounts[0].address, + ), + ).to.equal(0); + }); + + /********************************************************************** + * Operator-Fee Corner-Case tests + **********************************************************************/ + it('🔄 Two consecutive operator-fee withdrawal requests accumulate', async () => { + const { identityId } = await createProfile(); + const feeBal = hre.ethers.parseEther('100'); + // seed operator-fee balance + await StakingStorage.setOperatorFeeBalance(identityId, feeBal); + + // 1️⃣ first request 40 TRAC + const first = hre.ethers.parseEther('40'); + await Staking.requestOperatorFeeWithdrawal(identityId, first); + + expect(await StakingStorage.getOperatorFeeBalance(identityId)).to.equal( + feeBal - first, + 'Balance should be equal to feeBal - first', + ); + + // 2️⃣ second request 30 TRAC – should accumulate + const second = hre.ethers.parseEther('30'); + await Staking.requestOperatorFeeWithdrawal(identityId, second); + + expect(await StakingStorage.getOperatorFeeBalance(identityId)).to.equal( + feeBal - first - second, + 'Balance should reflect both deductions', + ); + const [amount, , release] = + await StakingStorage.getOperatorFeeWithdrawalRequest(identityId); + expect(amount).to.equal( + first + second, + 'Second request should be added to the first one', + ); + expect(release).to.be.gt(0, 'Release timestamp set'); + }); + + it('cancelOperatorFeeWithdrawal replenishes balance and deletes request', async () => { + const { identityId } = await createProfile(); + await StakingStorage.setOperatorFeeBalance(identityId, 40n); + await Staking.requestOperatorFeeWithdrawal(identityId, 30n); + await Staking.cancelOperatorFeeWithdrawal(identityId); + expect(await StakingStorage.getOperatorFeeBalance(identityId)).to.equal( + 40n, + 'Balance should be equal to 40', + ); + const [amt] = + await StakingStorage.getOperatorFeeWithdrawalRequest(identityId); + expect(amt).to.equal(0n, 'Amount should be 0'); + }); + + it('✅ Cancel withdrawal then restake pending operator fee', async () => { + const { identityId } = await createProfile(); + const feeBal = hre.ethers.parseEther('50'); + await StakingStorage.setOperatorFeeBalance(identityId, feeBal); + const withdrawAmt = hre.ethers.parseEther('20'); + await Staking.requestOperatorFeeWithdrawal(identityId, withdrawAmt); + + // Cancel it + await Staking.cancelOperatorFeeWithdrawal(identityId); + const [amountAfter] = + await StakingStorage.getOperatorFeeWithdrawalRequest(identityId); + expect(amountAfter).to.equal( + 0, + 'Withdrawal request should be cleared after cancel', + ); + // balance back to original + expect(await StakingStorage.getOperatorFeeBalance(identityId)).to.equal( + feeBal, + ); + + // Restake the same 20 + const delegatorKey = hre.ethers.keccak256( + hre.ethers.solidityPacked(['address'], [accounts[0].address]), + ); + const stakeBefore = await StakingStorage.getNodeStake(identityId); + await Staking.restakeOperatorFee(identityId, withdrawAmt); + expect(await StakingStorage.getOperatorFeeBalance(identityId)).to.equal( + feeBal - withdrawAmt, + 'Balance should be equal to feeBal - withdrawAmt', + ); + expect(await StakingStorage.getNodeStake(identityId)).to.equal( + stakeBefore + withdrawAmt, + 'Stake should be equal to stakeBefore + withdrawAmt', + ); + expect( + await StakingStorage.getDelegatorStakeBase(identityId, delegatorKey), + ).to.equal(withdrawAmt, 'Delegator stake should be equal to withdrawAmt'); + }); + + it('⛔️ Restake 0 operator-fee while withdrawal pending should revert', async () => { + const { identityId } = await createProfile(); + const feeBal = hre.ethers.parseEther('10'); + await StakingStorage.setOperatorFeeBalance(identityId, feeBal); + const withdrawAmt = hre.ethers.parseEther('5'); + await Staking.requestOperatorFeeWithdrawal(identityId, withdrawAmt); + await expect( + Staking.restakeOperatorFee(identityId, 0), + ).to.be.revertedWithCustomError(Staking, 'ZeroTokenAmount'); + }); + + it('🔒 Only profile admin can access operator-fee functions', async () => { + // admin = accounts[0], operational = accounts[1] + const { identityId } = await createProfile(accounts[0], accounts[1]); + await StakingStorage.setOperatorFeeBalance( + identityId, + hre.ethers.parseEther('10'), + ); + const other = accounts[2]; + + const expectOnlyAdmin = async ( + promise: Promise, // eslint-disable-line @typescript-eslint/no-explicit-any + ) => + expect(promise).to.be.revertedWithCustomError( + Staking, + 'OnlyProfileAdminFunction', + ); + + await expectOnlyAdmin( + Staking.connect(other).requestOperatorFeeWithdrawal(identityId, 1), + ); + await expectOnlyAdmin( + Staking.connect(other).cancelOperatorFeeWithdrawal(identityId), + ); + await expectOnlyAdmin( + Staking.connect(other).restakeOperatorFee(identityId, 1), + ); + }); + + it('📈 Operator-fee percentage path: fee credited once and only once', async () => { + // 0️⃣ setup profile with 10% operator fee + const { identityId } = await createProfile(); + // update operator fee to 10% (1000 ‱) + await Profile.updateOperatorFee(identityId, 1000); + + // Delegator addresses + const deleg1 = accounts[0]; + const deleg2 = accounts[1]; + + // 1️⃣ both delegators stake 1 000 TRAC each + const stakeAmt = hre.ethers.parseEther('1000'); + for (const d of [deleg1, deleg2]) { + await Token.mint(d.address, stakeAmt); + await Token.connect(d).approve(await Staking.getAddress(), stakeAmt); + await Staking.connect(d).stake(identityId, stakeAmt); + } + // 2️⃣ create rewards for current epoch + const SCALE18 = hre.ethers.parseUnits('1', 18); + const epochNow = await Chronos.getCurrentEpoch(); + const dKey1 = hre.ethers.keccak256( + hre.ethers.solidityPacked(['address'], [deleg1.address]), + ); + const dKey2 = hre.ethers.keccak256( + hre.ethers.solidityPacked(['address'], [deleg2.address]), + ); + const rewardPool = hre.ethers.parseEther('100'); + + await RandomSamplingStorage.addToNodeEpochScore( + epochNow, + identityId, + SCALE18, + ); + await RandomSamplingStorage.addToAllNodesEpochScore(epochNow, SCALE18); + await RandomSamplingStorage.addToEpochNodeDelegatorScore( + epochNow, + identityId, + dKey1, + SCALE18 / 2n, + ); + await RandomSamplingStorage.addToEpochNodeDelegatorScore( + epochNow, + identityId, + dKey2, + SCALE18 / 2n, + ); + await EpochStorage.addTokensToEpochRange(1, epochNow, epochNow, rewardPool); + + // 3️⃣ advance to next epoch so epochNow < currentEpoch + const ttn = await Chronos.timeUntilNextEpoch(); + await time.increase(ttn + 1n); + // operator fee balance before claims + const opBalBefore = await StakingStorage.getOperatorFeeBalance(identityId); + // 4️⃣ first delegator claims → fee credited once + await Staking.connect(deleg1).claimDelegatorRewards( + identityId, + epochNow, + deleg1.address, + ); + const opBalAfterFirst = + await StakingStorage.getOperatorFeeBalance(identityId); + const expectedFee = rewardPool / 10n; // 10% + expect(opBalAfterFirst - opBalBefore).to.equal( + expectedFee, + 'Operator-fee balance should increase by 10% of pool', + ); + // flag must be set + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + expect( + await DelegatorsInfo.isOperatorFeeClaimedForEpoch(identityId, epochNow), + ).to.be.true; + // 5️⃣ second delegator claims → fee NOT added again + await Staking.connect(deleg2).claimDelegatorRewards( + identityId, + epochNow, + deleg2.address, + ); + const opBalAfterSecond = + await StakingStorage.getOperatorFeeBalance(identityId); + expect(opBalAfterSecond).to.equal( + opBalAfterFirst, + 'Operator-fee balance should not change on second claim', + ); + // Leftover rewards recorded for delegators should be 90% of pool + const leftover = await DelegatorsInfo.getNetNodeEpochRewards( + identityId, + epochNow, + ); + expect(leftover).to.equal( + rewardPool - expectedFee, + 'Leftover rewards for delegators should be 90% of pool', + ); + }); + + /********************************************************************** + * Claim guards & batch claiming + **********************************************************************/ + + it('⛔️ Double-claim guard: second claim reverts', async () => { + const { identityId } = await createProfile(); + const deleg = accounts[0]; + const stake = hre.ethers.parseEther('100'); + await Token.mint(deleg.address, stake); + await Token.connect(deleg).approve(await Staking.getAddress(), stake); + await Staking.connect(deleg).stake(identityId, stake); + + // produce rewards for epoch E + const SCALE18 = hre.ethers.parseUnits('1', 18); + const epochE = await Chronos.getCurrentEpoch(); + const dKey = hre.ethers.keccak256( + hre.ethers.solidityPacked(['address'], [deleg.address]), + ); + await RandomSamplingStorage.addToNodeEpochScore( + epochE, + identityId, + SCALE18, + ); + await RandomSamplingStorage.addToAllNodesEpochScore(epochE, SCALE18); + await RandomSamplingStorage.addToEpochNodeDelegatorScore( + epochE, + identityId, + dKey, + SCALE18, + ); + + await EpochStorage.addTokensToEpochRange( + 1, + epochE, + epochE, + hre.ethers.parseEther('10'), + ); + + // advance to next epoch so claims are allowed + const ttn = await Chronos.timeUntilNextEpoch(); + await time.increase(ttn + 1n); + + // first claim succeeds + await Staking.connect(deleg).claimDelegatorRewards( + identityId, + epochE, + deleg.address, + ); + // second claim should revert + await expect( + Staking.connect(deleg).claimDelegatorRewards( + identityId, + epochE, + deleg.address, + ), + ).to.be.revertedWith('Already claimed all finalised epochs'); + }); + + it('✅ batchClaimDelegatorRewards happy-path (2 epochs × 2 delegators)', async () => { + const { identityId } = await createProfile(); + const deleg1 = accounts[0]; + const deleg2 = accounts[1]; + + const stake = hre.ethers.parseEther('50'); + for (const d of [deleg1, deleg2]) { + await Token.mint(d.address, stake); + await Token.connect(d).approve(await Staking.getAddress(), stake); + await Staking.connect(d).stake(identityId, stake); + } + const SCALE18 = hre.ethers.parseUnits('1', 18); + // epochs E1 and E2 + const epoch1 = await Chronos.getCurrentEpoch(); + const epoch2 = epoch1 + 1n; + + const makeRewards = async (ep: bigint) => { + for (const d of [deleg1, deleg2]) { + const dKey = hre.ethers.keccak256( + hre.ethers.solidityPacked(['address'], [d.address]), + ); + await RandomSamplingStorage.addToEpochNodeDelegatorScore( + ep, + identityId, + dKey, + SCALE18 / 2n, + ); + } + await RandomSamplingStorage.addToNodeEpochScore(ep, identityId, SCALE18); + await RandomSamplingStorage.addToAllNodesEpochScore(ep, SCALE18); + await EpochStorage.addTokensToEpochRange( + 1, + ep, + ep, + hre.ethers.parseEther('10'), + ); + }; + + await makeRewards(epoch1); + // advance to epoch2 + let inc = await Chronos.timeUntilNextEpoch(); + await time.increase(inc + 1n); + await makeRewards(epoch2); + // advance to epoch3 so both epochs are claimable + inc = await Chronos.timeUntilNextEpoch(); + await time.increase(inc + 1n); + // batch claim + await Staking.batchClaimDelegatorRewards( + identityId, + [epoch1, epoch2], + [deleg1.address, deleg2.address], + ); + // verify lastClaimedEpoch for both delegators == epoch2 + for (const d of [deleg1, deleg2]) { + const last = await DelegatorsInfo.getLastClaimedEpoch( + identityId, + d.address, + ); + expect(last).to.equal( + epoch2, + 'Last claimed epoch should be equal to epoch2', + ); + } + }); + + /********************************************************************** + * Withdrawal corner-cases + **********************************************************************/ + + it('🔀 Multiple withdrawal requests merge amounts', async () => { + const { identityId } = await createProfile(); + const stakeAmt = hre.ethers.parseEther('1000'); + await Token.mint(accounts[0].address, stakeAmt); + await Token.connect(accounts[0]).approve( + await Staking.getAddress(), + stakeAmt, + ); + await Staking.stake(identityId, stakeAmt); + + // first request 300 + const req1 = hre.ethers.parseEther('300'); + await Staking.requestWithdrawal(identityId, req1); + // second request 200 + const req2 = hre.ethers.parseEther('200'); + await Staking.requestWithdrawal(identityId, req2); + + const dKey = hre.ethers.keccak256( + hre.ethers.solidityPacked(['address'], [accounts[0].address]), + ); + const [pending, ,] = await StakingStorage.getDelegatorWithdrawalRequest( + identityId, + dKey, + ); + expect(pending).to.equal(req1 + req2, 'Request amount should accumulate'); + + // node stake reduced by 500 + expect(await StakingStorage.getNodeStake(identityId)).to.equal( + stakeAmt - req1 - req2, + ); + }); + + it('↩️ cancelWithdrawal partially restakes when near maximumStake', async () => { + // shrink maximumStake for easier maths + const smallMax = hre.ethers.parseEther('20'); + await ParametersStorage.setMaximumStake(smallMax); + + const { identityId } = await createProfile(); + + // Delegator A stakes maxStake (20) + await Token.mint(accounts[0].address, smallMax); + await Token.connect(accounts[0]).approve( + await Staking.getAddress(), + smallMax, + ); + await Staking.stake(identityId, smallMax); + + // Delegator A requests withdrawal 10 → node stake becomes 10 + const withdrawAmt = hre.ethers.parseEther('10'); + await Staking.requestWithdrawal(identityId, withdrawAmt); + + // Delegator B stakes 8 so node stake becomes 18 + await Token.mint(accounts[2].address, hre.ethers.parseEther('8')); + await Token.connect(accounts[2]).approve( + await Staking.getAddress(), + hre.ethers.parseEther('8'), + ); + await Staking.connect(accounts[2]).stake( + identityId, + hre.ethers.parseEther('8'), + ); + + // Snapshot before cancel + const dKeyA = hre.ethers.keccak256( + hre.ethers.solidityPacked(['address'], [accounts[0].address]), + ); + const dKeyB = hre.ethers.keccak256( + hre.ethers.solidityPacked(['address'], [accounts[2].address]), + ); + const [, , tsBefore] = await StakingStorage.getDelegatorWithdrawalRequest( + identityId, + dKeyA, + ); + const stakeBefore = await StakingStorage.getNodeStake(identityId); // should be 18 + + await Staking.cancelWithdrawal(identityId); + + // After cancel: 2 restaked, 8 pending + const [pendingAfter, , tsAfter] = + await StakingStorage.getDelegatorWithdrawalRequest(identityId, dKeyA); + expect(pendingAfter).to.equal( + hre.ethers.parseEther('8'), + 'Delegator 1 still has 8 pending in withdrawal', + ); + expect(await StakingStorage.getNodeStake(identityId)).to.equal( + stakeBefore + hre.ethers.parseEther('2'), + 'Node stake should be 18 + 2 = 20', + ); + expect( + await StakingStorage.getDelegatorStakeBase(identityId, dKeyA), + ).to.equal(hre.ethers.parseEther('12'), 'Delegator A stake should be 12'); + expect( + await StakingStorage.getDelegatorStakeBase(identityId, dKeyB), + ).to.equal(hre.ethers.parseEther('8'), 'Delegator B stake should be 8'); + expect(tsAfter).to.equal(tsBefore, 'Release timestamp must stay unchanged'); + }); + + /********************************************************************** + * Maximum / Minimum stake edge behaviours + **********************************************************************/ + + it('🎯 Restake operator-fee hits maximumStake exactly, +1 wei reverts', async () => { + const { identityId } = await createProfile(); + const maxStake = await ParametersStorage.maximumStake(); + + // Stake maxStake - 2 + const base = maxStake - 2n; + await Token.mint(accounts[0].address, base); + await Token.connect(accounts[0]).approve(await Staking.getAddress(), base); + await Staking.stake(identityId, base); + + // Put operator-fee balance 3 wei (2 to reach max, 1 to exceed) + await StakingStorage.setOperatorFeeBalance(identityId, 3n); + + // Restake 2 – should succeed and hit the cap exactly + await expect(Staking.restakeOperatorFee(identityId, 2n)).to.not.be.reverted; + expect(await StakingStorage.getNodeStake(identityId)).to.equal( + maxStake, + 'Node stake should be equal to maxStake', + ); + + // Restake +1 wei – should revert + await expect( + Staking.restakeOperatorFee(identityId, 1n), + ).to.be.revertedWithCustomError(Staking, 'MaximumStakeExceeded'); + }); + + it('↩️ cancelWithdrawal fully restakes when node well below maximumStake', async () => { + const { identityId } = await createProfile(); - await logNodeData(NodeA.identityId); + // Use current maximumStake as cap reference + const maxStake = await ParametersStorage.maximumStake(); - console.log('Operator tries to restake operator fee on NodeB'); - const operatorFeeBalanceB = await StakingStorage.getOperatorFeeBalance( - NodeB.identityId, + // Stake a small fraction of the cap (10%) so there is ample head-room + const baseStake = maxStake / 10n; + await Token.mint(accounts[0].address, baseStake); + await Token.connect(accounts[0]).approve( + await Staking.getAddress(), + baseStake, ); - console.log( - `Operator fee balance on NodeB: ${toEth(operatorFeeBalanceB)} ETH`, - ); - if (operatorFeeBalanceB > 0n) { - const restakeAmount = - operatorFeeBalanceB < hre.ethers.parseEther('10') - ? operatorFeeBalanceB - : hre.ethers.parseEther('10'); - console.log( - `Restaking ${toEth(restakeAmount)} ETH operator fee on NodeB`, - ); - await Staking.connect(admin2).restakeOperatorFee( - NodeB.identityId, - restakeAmount, - ); - const nodeBStakeAfterRestake = await StakingStorage.getNodeStake( - NodeB.identityId, - ); - console.log( - `NodeB stake after restake: ${toEth(nodeBStakeAfterRestake)} ETH, should be >= minStake`, - ); - } + await Staking.stake(identityId, baseStake); - console.log('d4 stakes on NodeB to push it close to max'); - const nodeBStakeNow = await StakingStorage.getNodeStake(NodeB.identityId); - const pushToMax = maxStake - nodeBStakeNow; - console.log(`Amount to push NodeB close to max: ${toEth(pushToMax)} ETH`); - if (pushToMax > 0n) { - const stakeD4 = pushToMax / 2n; - console.log(`Minting ${toEth(stakeD4)} ETH to d4`); - await Token.mint(d4.address, stakeD4); - await Token.connect(d4).approve(Staking.getAddress(), stakeD4); - console.log(`d4 stakes ${toEth(stakeD4)} ETH on NodeB`); - await Staking.connect(d4).stake(NodeB.identityId, stakeD4); - console.log( - `NodeB stake after d4 stakes: ${toEth(await StakingStorage.getNodeStake(NodeB.identityId))} ETH`, - ); - } + // Request withdrawal of half that stake + const withdrawAmt = baseStake / 2n; + await Staking.requestWithdrawal(identityId, withdrawAmt); - const d1Key = hre.ethers.keccak256( - hre.ethers.solidityPacked(['address'], [d1.address]), + // Snapshot state before cancel + const dKey = hre.ethers.keccak256( + hre.ethers.solidityPacked(['address'], [accounts[0].address]), + ); + const [pendingBefore] = await StakingStorage.getDelegatorWithdrawalRequest( + identityId, + dKey, ); - const [d1BaseA, d1IndexedA] = await StakingStorage.getDelegatorStakeInfo( - NodeA.identityId, - d1Key, + + // Sanity – pending equals requested amount + expect(pendingBefore).to.equal( + withdrawAmt, + 'Pending should be equal to requested amount', ); - const d1TotalA = d1BaseA + d1IndexedA; - const bigRedelegateAmount = d1TotalA > minStake ? minStake : d1TotalA; - console.log( - `d1 tries big redelegation from NodeA to NodeB: ${toEth(bigRedelegateAmount)} ETH`, - ); - const nodeBStakeFinalCheck = await StakingStorage.getNodeStake( - NodeB.identityId, - ); - if (nodeBStakeFinalCheck + bigRedelegateAmount > maxStake) { - console.log('This would exceed maximum stake on NodeB, expecting revert'); - await expect( - Staking.connect(d1).redelegate( - NodeA.identityId, - NodeB.identityId, - bigRedelegateAmount, - ), - ).to.be.reverted; - } - console.log('d1 does a small redelegation below max limit'); - const safeAmount = - (maxStake - (await StakingStorage.getNodeStake(NodeB.identityId))) / 2n; - if (safeAmount > 0n && safeAmount <= d1TotalA) { - console.log( - `Redelegating ${toEth(safeAmount)} ETH from NodeA to NodeB by d1`, - ); - await Staking.connect(d1).redelegate( - NodeA.identityId, - NodeB.identityId, - safeAmount, - ); - const nodeBStakeFinal = await StakingStorage.getNodeStake( - NodeB.identityId, - ); - console.log( - `NodeB stake after safe redelegation: ${toEth(nodeBStakeFinal)} ETH, should be < maxStake`, - ); - } + // Cancel the withdrawal – should restake full amount (pending becomes 0) + await Staking.cancelWithdrawal(identityId); - // Validate that no negative values appear, node stakes are consistent: - const nodeAStakeFinal = await StakingStorage.getNodeStake(NodeA.identityId); - const nodeBStakeFinal2 = await StakingStorage.getNodeStake( - NodeB.identityId, + // After cancel + const [pendingAfter] = await StakingStorage.getDelegatorWithdrawalRequest( + identityId, + dKey, ); - console.log( - `Final NodeA stake: ${toEth(nodeAStakeFinal)} ETH, Final NodeB stake: ${toEth(nodeBStakeFinal2)} ETH`, + expect(pendingAfter).to.equal( + 0n, + 'All pending amount should have been restaked', + ); + expect(await StakingStorage.getNodeStake(identityId)).to.equal( + baseStake, + 'Node stake should be equal to stakeBefore + withdrawAmt', + ); + expect(await StakingStorage.getTotalStake()).to.equal( + baseStake, + 'Total stake should be equal to totalBefore + withdrawAmt', ); - expect(nodeAStakeFinal).to.be.at.least(0n); - expect(nodeBStakeFinal2).to.be.at.least(0n); - console.log('--- END FULL SCENARIO TEST ---'); + // Delegator should still be registered for the node + expect( + await DelegatorsInfo.isNodeDelegator(identityId, accounts[0].address), + ).to.equal(true, 'Delegator should still be registered for the node'); }); - it('Stress test: Rapid stake/un-stake cycles, redelegations, operator fee changes, trying to break invariants', async () => { - console.log('--- START STRESS TEST SCENARIO ---'); - // Track user balances and stakes - let d1Balance = 0n; - let d2Balance = 0n; - let opFeeBalanceB = 0n; + it('↩️ cancelWithdrawal does NOT restake when node already at maximumStake', async () => { + // Shrink maximumStake for deterministic maths + const smallMax = hre.ethers.parseEther('20'); + await ParametersStorage.setMaximumStake(smallMax); + + const { identityId } = await createProfile(); - const admin1 = accounts[0]; - const op1 = accounts[1]; - const admin2 = accounts[2]; - const op2 = accounts[3]; + // Delegator A stakes the full max + await Token.mint(accounts[0].address, smallMax); + await Token.connect(accounts[0]).approve( + await Staking.getAddress(), + smallMax, + ); + await Staking.stake(identityId, smallMax); - const NodeA = await createProfile(admin1, op1, 10n); - console.log(`NodeA ID: ${NodeA.identityId}, fee: 10%`); - const NodeB = await createProfile(admin2, op2, 90n); - console.log(`NodeB ID: ${NodeB.identityId}, fee: 90%`); + // Delegator A requests withdrawal of 10 + const withdrawAmt = hre.ethers.parseEther('10'); + await Staking.requestWithdrawal(identityId, withdrawAmt); - const nodes = { - [NodeA.identityId]: 'A', - [NodeB.identityId]: 'B', - }; + // Delegator B fills the gap so node stake is back at the cap + await Token.mint(accounts[2].address, withdrawAmt); + await Token.connect(accounts[2]).approve( + await Staking.getAddress(), + withdrawAmt, + ); + await Staking.connect(accounts[2]).stake(identityId, withdrawAmt); - const d1 = accounts[4]; - const d2 = accounts[5]; - const d3 = accounts[6]; + // Ensure node stake equals the maximum before cancel + expect(await StakingStorage.getNodeStake(identityId)).to.equal(smallMax); - const delegators = { - [d1.address]: 'd1', - [d2.address]: 'd2', - [d3.address]: 'd3', - }; + // Snapshot state + const dKey = hre.ethers.keccak256( + hre.ethers.solidityPacked(['address'], [accounts[0].address]), + ); + const [pendingBefore, , tsBefore] = + await StakingStorage.getDelegatorWithdrawalRequest(identityId, dKey); + const totalBefore = await StakingStorage.getTotalStake(); - const delay = await ParametersStorage.stakeWithdrawalDelay(); - const minStake = await ParametersStorage.minimumStake(); - const maxStake = await ParametersStorage.maximumStake(); - const toEth = (amount: bigint) => Number(amount) / 1e18; - - const logNodeData = async (identityId: number) => { - const [ - stake, - rewardIndex, - cEarned, - cPaid, - opFeeBal, - opFeeEarned, - opFeePaid, - dCount, - ] = await StakingStorage.getNodeData(identityId); - console.log('----------------------------------------------------------'); - console.log(`Node${nodes[identityId]} Data: - Stake: ${toEth(BigInt(stake))} ETH, - RewardIndex: ${rewardIndex}, - CumulativeEarnedRewards: ${toEth(BigInt(cEarned))} ETH, - CumulativePaidOutRewards: ${toEth(BigInt(cPaid))} ETH, - OperatorFeeBalance: ${toEth(BigInt(opFeeBal))} ETH, - OperatorFeeCumulativeEarnedRewards: ${toEth(BigInt(opFeeEarned))} ETH, - OperatorFeeCumulativePaidOutRewards: ${toEth(BigInt(opFeePaid))} ETH, - DelegatorCount: ${dCount}`); - console.log('----------------------------------------------------------'); - }; + // Cancel withdrawal – should NOT restake anything + await Staking.cancelWithdrawal(identityId); - const logDelegatorData = async ( - identityId: number, - delegator: SignerWithAddress, - ) => { - const dKey = hre.ethers.keccak256( - hre.ethers.solidityPacked(['address'], [delegator.address]), - ); - const [dBase, dIndexed, dLastIndex, dEarned, dPaid] = - await StakingStorage.getDelegatorData(identityId, dKey); - console.log('----------------------------------------------------------'); - console.log(`Delegator ${delegators[delegator.address]} on Node${nodes[identityId]}: - BaseStake: ${toEth(BigInt(dBase))} ETH, - IndexedStake: ${toEth(BigInt(dIndexed))} ETH, - LastRewardIndex: ${dLastIndex}, - CumulativeEarnedRewards: ${toEth(BigInt(dEarned))} ETH, - CumulativePaidOutRewards: ${toEth(BigInt(dPaid))} ETH`); - console.log('----------------------------------------------------------'); - }; + const [pendingAfter, , tsAfter] = + await StakingStorage.getDelegatorWithdrawalRequest(identityId, dKey); + expect(pendingAfter).to.equal( + pendingBefore, + 'Pending amount should remain unchanged', + ); + expect(await StakingStorage.getNodeStake(identityId)).to.equal( + smallMax, + 'Node stake should remain at maximum', + ); + expect(await StakingStorage.getTotalStake()).to.equal( + totalBefore, + 'Total stake should be unchanged', + ); + expect(tsAfter).to.equal( + tsBefore, + 'Release timestamp should stay the same', + ); - console.log( - `MinStake: ${toEth(minStake)} ETH, MaxStake: ${toEth(maxStake)} ETH, Delay: ${delay}s`, - ); - - const mintAmountD1 = maxStake * 2n; - await Token.mint(d1.address, mintAmountD1); - d1Balance += mintAmountD1; - console.log(`d1 initial minted balance: ${toEth(d1Balance)} ETH`); - await Token.connect(d1).approve(Staking.getAddress(), mintAmountD1); - - const stakeA = minStake + 10n; - console.log(`d1 stakes ${toEth(stakeA)} ETH on NodeA`); - await Staking.connect(d1).stake(NodeA.identityId, stakeA); - d1Balance -= stakeA; - - await logNodeData(NodeA.identityId); - await logDelegatorData(NodeA.identityId, d1); - - console.log(`d1 requests full withdrawal: ${toEth(stakeA)} ETH from NodeA`); - await Staking.connect(d1).requestWithdrawal(NodeA.identityId, stakeA); - await expect(Staking.connect(d1).finalizeWithdrawal(NodeA.identityId)).to.be - .reverted; - console.log('Early finalize reverted as expected'); - await time.increase(Number(delay)); - const d1BeforeFinal = await Token.balanceOf(d1.address); - console.log(`d1 before finalizing: ${toEth(d1BeforeFinal)} ETH`); - await Staking.connect(d1).finalizeWithdrawal(NodeA.identityId); - const d1AfterFinal = await Token.balanceOf(d1.address); - const withdrawn = d1AfterFinal - d1BeforeFinal; - d1Balance += withdrawn; - console.log( - `d1 got back ${toEth(withdrawn)} ETH, balance now: ${toEth(d1Balance)} ETH`, + // Delegator remains registered + expect( + await DelegatorsInfo.isNodeDelegator(identityId, accounts[0].address), + ).to.equal(true, 'Delegator should still be registered for the node'); + }); + + /********************************************************************** + * Claim-pointer auto-advance & delegator-removal behaviours + **********************************************************************/ + + it('🚦 _validateDelegatorEpochClaims auto-advances when previous epoch has no score', async () => { + const { identityId } = await createProfile(); + // Stake some amount in the current epoch + const amount = hre.ethers.parseEther('100'); + await Token.mint(accounts[0].address, amount); + await Token.connect(accounts[0]).approve( + await Staking.getAddress(), + amount, ); + await Staking.stake(identityId, amount); - await logNodeData(NodeA.identityId); - await logDelegatorData(NodeA.identityId, d1); + // Snapshot lastClaimedEpoch after initial stake + const lastClaimedBefore = await DelegatorsInfo.getLastClaimedEpoch( + identityId, + accounts[0].address, + ); - if (minStake > d1Balance) - throw new Error('Not enough balance for d1 to restake'); - console.log(`d1 stakes again ${toEth(minStake)} ETH on NodeA`); - await Staking.connect(d1).stake(NodeA.identityId, minStake); - d1Balance -= minStake; + // Advance to the next epoch WITHOUT adding any scores + const inc = await Chronos.timeUntilNextEpoch(); + await time.increase(inc + 1n); + // Current and previous epoch values + const currentEpoch = await Chronos.getCurrentEpoch(); + const prevEpoch = currentEpoch - 1n; - await logNodeData(NodeA.identityId); - await logDelegatorData(NodeA.identityId, d1); + // Attempt to change stake (add 10) – should NOT revert because helper auto-advances + const addAmt = hre.ethers.parseEther('10'); + await Token.mint(accounts[0].address, addAmt); + await Token.connect(accounts[0]).approve( + await Staking.getAddress(), + addAmt, + ); + await expect(Staking.stake(identityId, addAmt)).to.not.be.reverted; + expect(await StakingStorage.getNodeStake(identityId)).to.equal( + amount + addAmt, + 'Node stake should be equal to amount + addAmt', + ); - const d1Key = hre.ethers.keccak256( - hre.ethers.solidityPacked(['address'], [d1.address]), + // Verify the claim pointer was auto-advanced to prevEpoch + const lastClaimedAfter = await DelegatorsInfo.getLastClaimedEpoch( + identityId, + accounts[0].address, ); - let [d1BaseA, d1IndexedA] = await StakingStorage.getDelegatorStakeInfo( - NodeA.identityId, - d1Key, + expect(lastClaimedAfter).to.equal( + prevEpoch, + 'Last claimed epoch should auto-advance to previous epoch', ); - let d1TotalA = d1BaseA + d1IndexedA; - console.log(`d1 total stake on NodeA: ${toEth(d1TotalA)} ETH`); - await expect( - Staking.connect(d1).redelegate( - NodeA.identityId, - NodeB.identityId, - d1TotalA + 1n, + expect(lastClaimedAfter).to.be.gt( + lastClaimedBefore, + 'Pointer must advance', + ); + }); + + it('👤 _handleDelegatorRemovalOnZeroStake keeps delegator when they earned score in epoch', async () => { + const { identityId } = await createProfile(); + // Stake + const stakeAmt = hre.ethers.parseEther('50'); + await Token.mint(accounts[0].address, stakeAmt); + await Token.connect(accounts[0]).approve( + await Staking.getAddress(), + stakeAmt, + ); + await Staking.stake(identityId, stakeAmt); + + // Add some score for the current epoch so delegatorEpochScore18 > 0 + const epoch = await Chronos.getCurrentEpoch(); + const dKey = hre.ethers.keccak256( + hre.ethers.solidityPacked(['address'], [accounts[0].address]), + ); + const SCALE18 = hre.ethers.parseUnits('1', 18); + await RandomSamplingStorage.addToEpochNodeDelegatorScore( + epoch, + identityId, + dKey, + SCALE18, + ); + + // Withdraw ALL stake + await Staking.requestWithdrawal(identityId, stakeAmt); + + // Delegator should still be registered & lastStakeHeldEpoch == currentEpoch + const lastStakeHeld = await DelegatorsInfo.getLastStakeHeldEpoch( + identityId, + accounts[0].address, + ); + expect(lastStakeHeld).to.equal( + epoch, + 'lastStakeHeldEpoch must be set to current epoch', + ); + expect( + await DelegatorsInfo.isNodeDelegator(identityId, accounts[0].address), + ).to.equal(true, 'Delegator should still be registered for the node'); + expect( + await StakingStorage.getDelegatorStakeBase(identityId, dKey), + ).to.equal(0n, 'Delegator stake should be 0'); + }); + + it('👥 _handleDelegatorRemovalOnZeroStake removes delegator when no score earned in epoch', async () => { + const { identityId } = await createProfile(); + // Stake + const stakeAmt = hre.ethers.parseEther('40'); + const dKey = hre.ethers.keccak256( + hre.ethers.solidityPacked(['address'], [accounts[0].address]), + ); + await Token.mint(accounts[0].address, stakeAmt); + await Token.connect(accounts[0]).approve( + await Staking.getAddress(), + stakeAmt, + ); + await Staking.stake(identityId, stakeAmt); + + // No score added for current epoch + + // Withdraw ALL stake + await Staking.requestWithdrawal(identityId, stakeAmt); + + // Delegator should be removed immediately (isNodeDelegator == false) and lastStakeHeldEpoch == 0 + const lastStakeHeld = await DelegatorsInfo.getLastStakeHeldEpoch( + identityId, + accounts[0].address, + ); + expect(lastStakeHeld).to.equal(0n, 'lastStakeHeldEpoch must stay zero'); + expect( + await DelegatorsInfo.isNodeDelegator(identityId, accounts[0].address), + ).to.equal(false, 'Delegator should be removed'); + expect( + await StakingStorage.getDelegatorStakeBase(identityId, dKey), + ).to.equal(0n, 'Delegator stake should be 0'); + }); + + it('🪫 zero-stake restake bumps index without adding score', async () => { + const { identityId } = await createProfile(); + const stakeAmt = hre.ethers.parseEther('10'); + // Stake initial amount + await Token.mint(accounts[0].address, stakeAmt); + await Token.connect(accounts[0]).approve( + await Staking.getAddress(), + stakeAmt, + ); + await Staking.stake(identityId, stakeAmt); + + // Withdraw full stake and finalise so stakeBase becomes 0 + await Staking.requestWithdrawal(identityId, stakeAmt); + // advance time to let withdrawal finalise + const dKey = hre.ethers.keccak256( + hre.ethers.solidityPacked(['address'], [accounts[0].address]), + ); + const [, , ts] = await StakingStorage.getDelegatorWithdrawalRequest( + identityId, + dKey, + ); + await time.increaseTo(BigInt(ts)); + await Staking.finalizeWithdrawal(identityId); + expect(await StakingStorage.getNodeStake(identityId)).to.equal( + 0n, + 'Node stake should be 0', + ); + expect( + await StakingStorage.getDelegatorStakeBase(identityId, dKey), + ).to.equal(0n, 'Delegator stake should be 0'); + + // Move to next epoch + const inc = await Chronos.timeUntilNextEpoch(); + await time.increase(inc + 1n); + const epoch = await Chronos.getCurrentEpoch(); + + // Manually set a non-zero nodeScorePerStake so prepare branches + const perStake = 123n; + await RandomSamplingStorage.addToNodeEpochScorePerStake( + epoch, + identityId, + perStake, + ); + + // Sanity: delegator score for epoch should be zero + expect( + await RandomSamplingStorage.getEpochNodeDelegatorScore( + epoch, + identityId, + dKey, ), - ).to.be.reverted; - console.log('Redelegation exceeding stake reverted as expected'); + ).to.equal(0n); - const nodeBStakeBefore = await StakingStorage.getNodeStake( - NodeB.identityId, + // Restake 1 wei (will invoke _prepareForStakeChange with stakeBase==0) + await Token.mint(accounts[0].address, 1n); + await Token.connect(accounts[0]).approve(await Staking.getAddress(), 1n); + await Staking.stake(identityId, 1n); + + // Index should now equal perStake and score still zero + expect( + await RandomSamplingStorage.getDelegatorLastSettledNodeEpochScorePerStake( + epoch, + identityId, + dKey, + ), + ).to.equal( + perStake, + 'Delegator last settled node epoch score per stake should be equal to perStake', ); - const redelegateAmount = minStake - nodeBStakeBefore - 1n; - const safeRedelegate = - redelegateAmount > d1TotalA ? d1TotalA : redelegateAmount; - console.log( - `d1 redelegates ${toEth(safeRedelegate)} ETH from NodeA to NodeB`, - ); - await Staking.connect(d1).redelegate( - NodeA.identityId, - NodeB.identityId, - safeRedelegate, - ); - await logNodeData(NodeB.identityId); - await logDelegatorData(NodeB.identityId, d1); - - await Token.mint(d2.address, minStake); - d2Balance += minStake; - console.log(`d2 minted balance: ${toEth(d2Balance)} ETH`); - await Token.connect(d2).approve(Staking.getAddress(), minStake); - console.log(`d2 stakes ${toEth(minStake)} ETH on NodeB`); - await Staking.connect(d2).stake(NodeB.identityId, minStake); - d2Balance -= minStake; - - await logNodeData(NodeB.identityId); - await logDelegatorData(NodeB.identityId, d2); - - const hugeRewardB = hre.ethers.parseEther('5000000'); - console.log(`Distributing huge reward: ${toEth(hugeRewardB)} ETH to NodeB`); - await Token.mint(StakingStorage.getAddress(), hugeRewardB); - await Staking.distributeRewards(NodeB.identityId, hugeRewardB); - opFeeBalanceB = await StakingStorage.getOperatorFeeBalance( - NodeB.identityId, - ); - console.log(`Operator fee on NodeB: ${toEth(opFeeBalanceB)} ETH`); - await expect( - Staking.connect(admin2).restakeOperatorFee( - NodeB.identityId, - opFeeBalanceB, + expect( + await RandomSamplingStorage.getEpochNodeDelegatorScore( + epoch, + identityId, + dKey, ), - ).to.be.reverted; - console.log('Exceed max restake reverted as expected'); - - const nodeBStake = await StakingStorage.getNodeStake(NodeB.identityId); - const partialRestake = - maxStake > nodeBStake ? (maxStake - nodeBStake) / 2n : 0n; - const safePartialRestake = - partialRestake > opFeeBalanceB ? opFeeBalanceB : partialRestake; - if (safePartialRestake > 0n) { - console.log(`Restaking partial fee: ${toEth(safePartialRestake)} ETH`); - await Staking.connect(admin2).restakeOperatorFee( - NodeB.identityId, - safePartialRestake, - ); - opFeeBalanceB -= safePartialRestake; - } + ).to.equal(0n, 'Delegator score for epoch should be 0'); + }); - console.log(`d1 stakes again minStake+10 ETH on NodeA`); - if (minStake + 10n > d1Balance) - throw new Error('Not enough balance for d1'); - await Staking.connect(d1).stake(NodeA.identityId, minStake + 10n); - d1Balance -= minStake + 10n; - [d1BaseA, d1IndexedA] = await StakingStorage.getDelegatorStakeInfo( - NodeA.identityId, - d1Key, + it('💸 finalizeOperatorFeeWithdrawal happy-path updates cumulatives and transfers tokens', async () => { + const { identityId } = await createProfile(); + const initialFeeBalance = hre.ethers.parseEther('150'); + await StakingStorage.setOperatorFeeBalance(identityId, initialFeeBalance); + + // Request withdrawal of 60 + const withdrawAmt = hre.ethers.parseEther('60'); + await Staking.requestOperatorFeeWithdrawal(identityId, withdrawAmt); + // capture request release timestamp from storage + const [, , releaseTs] = + await StakingStorage.getOperatorFeeWithdrawalRequest(identityId); + + // Mint tokens to the StakingStorage contract so withdrawal can succeed + await Token.mint(await StakingStorage.getAddress(), withdrawAmt); + + // Snapshot cumulative paid-out before + const paidOutBefore = + await StakingStorage.getOperatorFeeCumulativePaidOutRewards(identityId); + const balBefore = await Token.balanceOf(accounts[0].address); + + // Advance time to release + await time.increaseTo(BigInt(releaseTs)); + await Staking.finalizeOperatorFeeWithdrawal(identityId); + + const paidOutAfter = + await StakingStorage.getOperatorFeeCumulativePaidOutRewards(identityId); + const balAfter = await Token.balanceOf(accounts[0].address); + + expect(paidOutAfter).to.equal( + paidOutBefore + withdrawAmt, + 'Cumulative paid-out should increase', + ); + expect(balAfter - balBefore).to.equal( + withdrawAmt, + 'Admin balance should increase by withdrawn amount', + ); + // Request should be cleared after finalization + const [reqAmtAfter] = + await StakingStorage.getOperatorFeeWithdrawalRequest(identityId); + expect(reqAmtAfter).to.equal( + 0, + 'Withdrawal request amount should be zero after finalization', ); - d1TotalA = d1BaseA + d1IndexedA; - console.log( - `d1 total stake now: ${toEth(d1TotalA)} ETH, balance: ${toEth(d1Balance)} ETH`, + }); + + it('🚫 batchClaimDelegatorRewards reverts when older epochs unclaimed', async () => { + const { identityId } = await createProfile(); + const stakeAmt = hre.ethers.parseEther('30'); + await Token.mint(accounts[0].address, stakeAmt); + await Token.connect(accounts[0]).approve( + await Staking.getAddress(), + stakeAmt, ); + await Staking.stake(identityId, stakeAmt); - const firstReq = d1TotalA / 2n; - console.log(`d1 requests withdrawal: ${toEth(firstReq)} ETH from NodeA`); - await Staking.connect(d1).requestWithdrawal(NodeA.identityId, firstReq); + // Move to next epoch E2 + let inc = await Chronos.timeUntilNextEpoch(); + await time.increase(inc + 1n); + const epoch2 = await Chronos.getCurrentEpoch(); + // Advance to E3 so both previous epochs are claimable + inc = await Chronos.timeUntilNextEpoch(); + await time.increase(inc + 1n); - const secondReq = d1TotalA / 4n; - console.log( - `d1 requests another withdrawal: ${toEth(secondReq)} ETH from NodeA`, - ); + // Attempt batch claim skipping epoch1 – expect revert await expect( - Staking.connect(d1).requestWithdrawal(NodeA.identityId, secondReq), - ).to.not.be.reverted; - console.log('Multiple overlapping requests done'); + Staking.batchClaimDelegatorRewards( + identityId, + [epoch2], + [accounts[0].address], + ), + ).to.be.revertedWith('Must claim older epochs first'); + }); + + /********************************************************************** + * Token/Allowance & sharding-table guards + **********************************************************************/ - console.log('No operator fee request on NodeA, try finalize anyway'); + it('⛔️ redelegate with 0 amount reverts ZeroTokenAmount', async () => { + const { identityId: fromId } = await createProfile(undefined, accounts[3]); + const { identityId: toId } = await createProfile(undefined, accounts[4]); await expect( - Staking.connect(admin1).finalizeOperatorFeeWithdrawal(NodeA.identityId), - ).to.be.reverted; - console.log('Reverted as expected'); + Staking.redelegate(fromId, toId, 0n), + ).to.be.revertedWithCustomError(Staking, 'ZeroTokenAmount'); + }); + + it('📈 ShardingTableIsFull guard triggers when limit reached', async () => { + // Reduce table size for test speed + await ParametersStorage.setShardingTableSizeLimit(2); + const minStake = await ParametersStorage.minimumStake(); + + let opIndex = 3; + const stakeNode = async () => { + const { identityId } = await createProfile( + undefined, + accounts[opIndex++], + ); + await Token.mint(accounts[0].address, minStake); + await Token.connect(accounts[0]).approve( + await Staking.getAddress(), + minStake, + ); + await Staking.stake(identityId, minStake); + }; - const d2Key = hre.ethers.keccak256( - hre.ethers.solidityPacked(['address'], [d2.address]), + await stakeNode(); // node 1 + await stakeNode(); // node 2 – at limit + + const { identityId: overflowId } = await createProfile( + undefined, + accounts[opIndex++], ); - const [d2BaseB, d2IndexedB] = await StakingStorage.getDelegatorStakeInfo( - NodeB.identityId, - d2Key, + await Token.mint(accounts[0].address, minStake); + await Token.connect(accounts[0]).approve( + await Staking.getAddress(), + minStake, ); - const d2TotalStakeOnB = d2BaseB + d2IndexedB; - const d2WithdrawReq = d2TotalStakeOnB / 4n; - console.log( - `d2 requests ${toEth(d2WithdrawReq)} ETH withdrawal from NodeB`, + await expect( + Staking.stake(overflowId, minStake), + ).to.be.revertedWithCustomError(Staking, 'ShardingTableIsFull'); + }); + + it('📣 emits OperatorFeeBalanceUpdated and DelegatorBaseStakeUpdated on restakeOperatorFee', async () => { + const { identityId } = await createProfile(); + // Seed operator fee balance + const initialFee = 50n; + await StakingStorage.setOperatorFeeBalance(identityId, initialFee); + + // ensure node has stake + const stakeAmt = hre.ethers.parseEther('100'); + await Token.mint(accounts[0].address, stakeAmt); + await Token.connect(accounts[0]).approve( + await Staking.getAddress(), + stakeAmt, + ); + await Staking.stake(identityId, stakeAmt); + + const restakeAmt = 20n; + const newFeeBal = initialFee - restakeAmt; + const delegatorKey = hre.ethers.keccak256( + hre.ethers.solidityPacked(['address'], [accounts[0].address]), + ); + const baseBefore = await StakingStorage.getDelegatorStakeBase( + identityId, + delegatorKey, ); - await Staking.connect(d2).requestWithdrawal( - NodeB.identityId, - d2WithdrawReq, + + const tx = await Staking.restakeOperatorFee(identityId, restakeAmt); + + await expect(tx) + .to.emit(StakingStorage, 'OperatorFeeBalanceUpdated') + .withArgs(identityId, newFeeBal); + + await expect(tx) + .to.emit(StakingStorage, 'DelegatorBaseStakeUpdated') + .withArgs(identityId, delegatorKey, baseBefore + restakeAmt); + }); + + /********************************************************************** + * Events & sharding‑table transition on redelegate + **********************************************************************/ + it('emits StakeRedelegated and moves both nodes in sharding table', async () => { + const nodeA = await createProfile(); + const nodeB = await createProfile(accounts[0], accounts[2]); + + // make nodeA eligible for the table + const minStake = await ParametersStorage.minimumStake(); + await Token.mint(accounts[0].address, minStake); + await Token.connect(accounts[0]).approve( + await Staking.getAddress(), + minStake, ); + await Staking.stake(nodeA.identityId, minStake); + + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + expect(await ShardingTableStorage.nodeExists(nodeA.identityId)).to.be.true; + await expect( - Staking.connect(d2).finalizeWithdrawal(NodeB.identityId), - ).to.be.revertedWithCustomError(Staking, 'WithdrawalPeriodPending'); - console.log('Too early finalize reverted'); - console.log('d2 cancels withdrawal'); - await Staking.connect(d2).cancelWithdrawal(NodeB.identityId); + Staking.redelegate(nodeA.identityId, nodeB.identityId, minStake), + ) + .to.emit(Staking, 'StakeRedelegated') + .withArgs( + nodeA.identityId, + nodeB.identityId, + accounts[0].address, + minStake, + ); + + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + expect(await ShardingTableStorage.nodeExists(nodeA.identityId)).to.be.false; + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + expect(await ShardingTableStorage.nodeExists(nodeB.identityId)).to.be.true; + }); + + /********************************************************************** + * Withdrawal “fast‑path” when node is above new maximumStake + **********************************************************************/ + it('requestWithdrawal transfers immediately when newStake ≥ lowered maximumStake', async () => { + const { identityId } = await createProfile(); + const stakeAmt = hre.ethers.parseEther('100'); + await Token.mint(accounts[0].address, stakeAmt); + await Token.connect(accounts[0]).approve( + await Staking.getAddress(), + stakeAmt, + ); + await Staking.stake(identityId, stakeAmt); + + // Governance lowers the cap below current stake – makes the branch reachable + const newMax = stakeAmt - hre.ethers.parseEther('10'); + await ParametersStorage.setMaximumStake(newMax); + + const balBefore = await Token.balanceOf(accounts[0].address); + const withdraw = hre.ethers.parseEther('5'); + + await Staking.requestWithdrawal(identityId, withdraw); + const balAfter = await Token.balanceOf(accounts[0].address); + + expect(balAfter - balBefore).to.equal( + withdraw, + 'payout should be immediate', + ); + + const [pending] = await StakingStorage.getDelegatorWithdrawalRequest( + identityId, + hre.ethers.keccak256( + hre.ethers.solidityPacked(['address'], [accounts[0].address]), + ), + ); + expect(pending).to.equal(0n, 'no pending request stored'); + }); + + /********************************************************************** + * Operator‑fee withdrawal: merge‑then‑exceed should revert + **********************************************************************/ + it('requestOperatorFeeWithdrawal amount exceeds operator fee balance reverts', async () => { + const { identityId } = await createProfile(); + const feeBal = hre.ethers.parseEther('100'); + await StakingStorage.setOperatorFeeBalance(identityId, feeBal); + + await Staking.requestOperatorFeeWithdrawal( + identityId, + hre.ethers.parseEther('80'), + ); // existing request + await expect( - Staking.connect(d2).cancelWithdrawal(NodeB.identityId), - ).to.be.revertedWithCustomError(Staking, 'WithdrawalWasntInitiated'); - console.log('Second cancel reverted as expected'); + Staking.requestOperatorFeeWithdrawal( + identityId, + hre.ethers.parseEther('30'), + ), // 80+30 > 100 + ).to.be.revertedWithCustomError(Staking, 'AmountExceedsOperatorFeeBalance'); + }); - console.log('d3 never staked on NodeA, tries withdrawing 100 ETH'); - await expect(Staking.connect(d3).requestWithdrawal(NodeA.identityId, 100n)) - .to.be.reverted; - console.log('No stake withdrawal reverted as expected'); + /********************************************************************** + * restakeOperatorFee updates cumulativePaidOut bookkeeping + **********************************************************************/ + it('restakeOperatorFee bumps cumulativePaidOut', async () => { + const { identityId } = await createProfile(); + const feeBal = hre.ethers.parseEther('50'); + await StakingStorage.setOperatorFeeBalance(identityId, feeBal); - const halfD2StakeB = - (await StakingStorage.getNodeStake(NodeB.identityId)) / 5n; - console.log( - `d2 requests 20% stake withdrawal on NodeB: ${toEth(halfD2StakeB)} ETH`, + const before = + await StakingStorage.getOperatorFeeCumulativePaidOutRewards(identityId); + const restake = hre.ethers.parseEther('20'); + await Staking.restakeOperatorFee(identityId, restake); + const after = + await StakingStorage.getOperatorFeeCumulativePaidOutRewards(identityId); + + expect(after - before).to.equal(restake); + }); + + /********************************************************************** + * _validateDelegatorEpochClaims: must‑claim‑before‑re‑stake guard + **********************************************************************/ + it('Re-stake after full exit with unclaimed score reverts', async () => { + const { identityId } = await createProfile(); + const stakeAmt = hre.ethers.parseEther('100'); + await Token.mint(accounts[0].address, stakeAmt); + await Token.connect(accounts[0]).approve( + await Staking.getAddress(), + stakeAmt, ); - await Staking.connect(d2).requestWithdrawal(NodeB.identityId, halfD2StakeB); - await time.increase(Number(delay)); - const d2BeforeFinal = await Token.balanceOf(d2.address); - console.log( - `Finalizing large d2 withdrawal. Before: ${toEth(d2BeforeFinal)} ETH`, + await Staking.stake(identityId, stakeAmt); + + // give delegator some score in the current epoch + const curEp = await Chronos.getCurrentEpoch(); + const dKey = hre.ethers.keccak256( + hre.ethers.solidityPacked(['address'], [accounts[0].address]), ); - await Staking.connect(d2).finalizeWithdrawal(NodeB.identityId); - const d2AfterFinal = await Token.balanceOf(d2.address); - d2Balance += d2AfterFinal - d2BeforeFinal; - console.log( - `d2 after final: ${toEth(d2AfterFinal)} ETH, gained: ${toEth(d2AfterFinal - d2BeforeFinal)} ETH, d2Balance: ${toEth(d2Balance)} ETH`, + const SCALE18 = hre.ethers.parseUnits('1', 18); + await RandomSamplingStorage.addToEpochNodeDelegatorScore( + curEp, + identityId, + dKey, + SCALE18, ); - if ((await ShardingTableStorage.nodeExists(NodeB.identityId)) === false) { - const [d2BaseB2, d2IndexedB2] = - await StakingStorage.getDelegatorStakeInfo(NodeB.identityId, d2Key); - const d2TotalB = d2BaseB2 + d2IndexedB2; - console.log(`NodeB out of table, d2 totalB: ${toEth(d2TotalB)} ETH`); - if (d2TotalB > 0) { - console.log( - `d2 redelegates ${toEth(d2TotalB)} ETH from NodeB to NodeA`, - ); - await expect( - Staking.connect(d2).redelegate( - NodeB.identityId, - NodeA.identityId, - d2TotalB, - ), - ).to.not.be.reverted; - } - } + // withdraw everything and finalise + await Staking.requestWithdrawal(identityId, stakeAmt); + const [, , ts] = await StakingStorage.getDelegatorWithdrawalRequest( + identityId, + dKey, + ); + expect(curEp).to.equal( + await DelegatorsInfo.getLastStakeHeldEpoch( + identityId, + accounts[0].address, + ), + ); + await time.increaseTo(BigInt(ts)); + await Staking.finalizeWithdrawal(identityId); + + // hop to next epoch – the rewards are now claimable + await time.increase((await Chronos.timeUntilNextEpoch()) + 1n); + + await Token.mint(accounts[0].address, 1n); + await Token.connect(accounts[0]).approve(await Staking.getAddress(), 1n); + await expect(Staking.stake(identityId, 1n)).to.be.revertedWith( + 'Must claim rewards up to the lastStakeHeldEpoch before changing stake', + ); + }); + + /********************************************************************** + * claimDelegatorRewards basic guards + **********************************************************************/ + it('claimDelegatorRewards reverts for non-finalised epoch & unknown delegator', async () => { + const { identityId } = await createProfile(); + // epoch not finalised + await expect( + Staking.claimDelegatorRewards( + identityId, + await Chronos.getCurrentEpoch(), + accounts[0].address, + ), + ).to.be.revertedWith('Epoch not finalised'); + + // move one epoch forward; now previous epoch is finalised + await time.increase((await Chronos.timeUntilNextEpoch()) + 1n); + await expect( + Staking.claimDelegatorRewards( + identityId, + (await Chronos.getCurrentEpoch()) - 1n, + accounts[5].address, + ), + ).to.be.revertedWith('Delegator not found'); + }); + + it('reverts when claiming rewards for currentEpoch + 1', async () => { + const { identityId } = await createProfile(); + const epochPlus = (await Chronos.getCurrentEpoch()) + 1n; + await expect( + Staking.claimDelegatorRewards(identityId, epochPlus, accounts[0].address), + ).to.be.revertedWith('Epoch not finalised'); + }); - // Validate no negative values: - const finalNodeAStake = await StakingStorage.getNodeStake(NodeA.identityId); - const finalNodeBStake = await StakingStorage.getNodeStake(NodeB.identityId); - expect(finalNodeAStake).to.be.gte(0n); - expect(finalNodeBStake).to.be.gte(0n); + it('handles claim when node score is zero (no rewards)', async () => { + const { identityId } = await createProfile(); + await Token.mint(accounts[0].address, 1000); + await Token.connect(accounts[0]).approve(await Staking.getAddress(), 1000); + await Staking.stake(identityId, 1000); + + const epoch = await Chronos.getCurrentEpoch(); + // finalise epoch without adding scores + await time.increase((await Chronos.timeUntilNextEpoch()) + 1n); - console.log('--- END STRESS TEST SCENARIO ---'); + const dKey = hre.ethers.keccak256( + hre.ethers.solidityPacked(['address'], [accounts[0].address]), + ); + const balBefore = await StakingStorage.getDelegatorStakeBase( + identityId, + dKey, + ); + await Staking.claimDelegatorRewards(identityId, epoch, accounts[0].address); + const balAfter = await StakingStorage.getDelegatorStakeBase( + identityId, + dKey, + ); + expect(balAfter).to.equal(balBefore); // stake unchanged + // pointer advanced + expect( + await DelegatorsInfo.getLastClaimedEpoch(identityId, accounts[0].address), + ).to.equal(epoch); }); });