diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 70ab1f77..9efa124c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,7 +7,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - node-version: [16.x] + node-version: [18.x] # See supported Node.js release schedule at https://nodejs.org/en/about/releases/ steps: - uses: actions/checkout@v2 diff --git a/.openzeppelin/unknown-31337.json b/.openzeppelin/unknown-31337.json deleted file mode 100644 index ada174f6..00000000 --- a/.openzeppelin/unknown-31337.json +++ /dev/null @@ -1,12372 +0,0 @@ -{ - "manifestVersion": "3.2", - "admin": { - "address": "0x4321f0C1D60FAcA09C44B0b060cB6FAA7fB6c478", - "txHash": "0x3ddd706a80ec2f04a5786e1495952924d959fdb1667bb6cad38ba42f499f74b2" - }, - "proxies": [ - { - "address": "0xe2B69b930B3bD324Ad6ce799dFdC3d4452ae7520", - "txHash": "0x2f20c0de59781a186b85ba4df94207b8605d2cf3f479380b9ecea5da8caebb61", - "kind": "transparent" - }, - { - "address": "0xDb6F3aA47a3e48c482657a7257DDcC87aF9025CC", - "txHash": "0x45d1bc5ebb7e4cac8dda8f4c6d5c8eff8d11b579abf642cb6e2a6669a426117a", - "kind": "transparent" - }, - { - "address": "0x856C8B35b5Be590C54Cf16E2d6a416402F872cFA", - "txHash": "0xf659a792ad2e25e024405c11aa479a28cc25a91aea43789ed8de5969c78ecab0", - "kind": "transparent" - }, - { - "address": "0x82bc7A25cA5f010aE76585a8EFD3F02601C0CFE0", - "txHash": "0x2af8d6ce308b594aa2f2525a4d74e86292cc5785e12d9dd7e2797c3d85f52fd7", - "kind": "transparent" - }, - { - "address": "0x159A3AB7a1e5e723d2B2B7d45Ae28bD4406bFcC6", - "txHash": "0x3b6e90e76752b3d5f198cf29a3c2d36ce389612a85ef88977821d6db5c1202df", - "kind": "transparent" - }, - { - "address": "0x67437c4D2E0B4c102D830A11E5E59F960b502C42", - "txHash": "0x3c7be3022382e32b97f8fcc1c886efb73d6f8d5424e9886b00d3ec31f24e8c52", - "kind": "transparent" - }, - { - "address": "0x8FdE6Fb6bB1c517752a6bdB9E468F72fB576b4e5", - "txHash": "0xdf2de96da26c14d36f9a5f92c9e4227a6d585ab0db5fd04353a44051c38140ec", - "kind": "transparent" - }, - { - "address": "0x29D1F142bAfe260f22Ce5e623E0d5E97e99610f9", - "txHash": "0x423ad1b62955959f727cdccfa036c32966f969b8d61f5cafa07f17682ade1887", - "kind": "transparent" - }, - { - "address": "0x97A8EDf9328A98b5144Fd18716f57Ff208caa68d", - "txHash": "0x510ce6332108ca7fd251ad247b30ad3e066ebbbf7a5f511ca0d5690377a11254", - "kind": "transparent" - }, - { - "address": "0x4a3AB549Df05590914BDD3cFCAdB0ad3d3973308", - "txHash": "0x03e541ff24d89e0a641e9ef5669d3059035b7c24550e68d175eac49bca774251", - "kind": "transparent" - }, - { - "address": "0x370750695535FC32DaAb0E9868E45C94a38De77A", - "txHash": "0x4dccfa39d17a5d5d9ca8ae0a641c16be0f44aba2b461e5096bf5552a2908644f", - "kind": "transparent" - }, - { - "address": "0xD1545498c38EBA00F34794B464a2cf4d0C2E1Dfa", - "txHash": "0x9b7d2a13ce898d3906b54f207915786e130d0c49bcfe9c9a9a353e08ebed927e", - "kind": "transparent" - }, - { - "address": "0x35bf0c2FC60dcEE1D6911594574c780852D41BB9", - "txHash": "0x1430fd77a3634f6f6f3e35de4fe14b773ebc85d9c3f30b0d303f06af1c6538d4", - "kind": "transparent" - }, - { - "address": "0x23920797290f2fA94294C29F9F66Fa1B1d18a990", - "txHash": "0x354a2d0f25b0753cd20247f8ca263d5fd298da6f71e7dae15605eeb6f8912089", - "kind": "transparent" - }, - { - "address": "0x50511De6A170e0374Bf779b0791e169757d74413", - "txHash": "0x494c6da9a8ea9963a28e5ee048d4244428203c575c949d007778703411aa7626", - "kind": "transparent" - }, - { - "address": "0xD0BEb1F5A0d16D156526A6e5d78EEAAb058Bd173", - "txHash": "0x8cd4ae63f4e086615d564765bb7f5f613e845974753b1bac52fd663ebd90761d", - "kind": "transparent" - }, - { - "address": "0x31C12F5f349053FDAa84D990CfE5CBd82FB02Fef", - "txHash": "0x563d41590ccdfa5571ad242e00322f065160dd0431fd08b20102b10461199e2d", - "kind": "transparent" - }, - { - "address": "0x48c5cEa46173eB0CaaC397992096B563f63c5D2B", - "txHash": "0x01eda32796400aed78a35312ea9fc8abcce72eecb9047a334b1a6cb0ffbaf2e2", - "kind": "transparent" - }, - { - "address": "0x70a201a7AEB3eC29386efa9cfcC08452C2B6057F", - "txHash": "0x59c5fd3b5556ff285a9dabae2f54f9ba6bd568501969311f161eb85042b2ebeb", - "kind": "transparent" - }, - { - "address": "0x9C1201c625daCc7B5B46d720Ca56161C06B561cC", - "txHash": "0x4b10fdb38e173903531ccafd49eda351fe38b1ef41611f5dd940cab123ccdbff", - "kind": "transparent" - }, - { - "address": "0x36Ea1EAeF7785Ea0e1f6e6A172AdAD745cBb6190", - "txHash": "0x3a2510ad1b44c1c1fff1de9154f00a2172002016f05d883b7a50b161c6adb021", - "kind": "transparent" - }, - { - "address": "0x6574Ec39DB9c926738A3D25814f85895EC66355f", - "txHash": "0xe2bb379a67785fedb36f7619230b0499479c9c333c0d7f1d137ddcde54f2fc53", - "kind": "transparent" - }, - { - "address": "0x1953A831AbF3A95C94Acf24f70773282B3d93D95", - "txHash": "0x18b672f01c76d32f1c582ae42ed36fe64d899db0f81991682d114f81db5302fd", - "kind": "transparent" - }, - { - "address": "0x4b49185c8E327207945cF69B60BB60644a7b4C52", - "txHash": "0x58eadea53d9b5849a410998e06693576d792b6bc462a8d7c6daae44f0cee2a09", - "kind": "transparent" - }, - { - "address": "0x9328D8Cc9Eeb260980545197084e237179ee1E35", - "txHash": "0x3f83891045bd9942e5a792aa4c50c641ddb1faed14fa8c0cef53d5adf071385d", - "kind": "transparent" - }, - { - "address": "0x5AdD9F0012a8c5D3bF4Dec69336e634aB91Cc7A0", - "txHash": "0x255b93d4e1d033ad14e3c27a2af39066aade1f8c24beb5d1152c441b7f72ff55", - "kind": "transparent" - }, - { - "address": "0x32ea245FF07e72b9a154132B46C0C0563faaA2fe", - "txHash": "0x00d503cba0ee020e1ff2390f2641f5202db8e73ed52c1a605b3c7bf37ab8668c", - "kind": "transparent" - }, - { - "address": "0x46BA221C414cb4C01e21c55f0D77Cb9aaE7D9E69", - "txHash": "0x9f1ad4219549844d0e99d0dc7735eb15c4b9ac4ad029ff0c2260ad8e8d22fc67", - "kind": "transparent" - }, - { - "address": "0xaC8Fd961e3281ab5Ed0c7a807218a4E30C2b2F35", - "txHash": "0x3d90d22fe1c082e7ea8082e3c2fb817aac5cddf4b0c35c64c38a2f291cc30b62", - "kind": "transparent" - }, - { - "address": "0x3d598261aC29CCe165244626FADc6CE92168495C", - "txHash": "0x0c0e6bef215192a426e1a1a4e7eeed9838896800dddc73b6f141441a3600ea1e", - "kind": "transparent" - }, - { - "address": "0xB2cBf6027Ac3E380Bf0927B556d53504E982a201", - "txHash": "0xb4a247fe04a1ce6ef0d55767ce6ca84f175d5c84b4c3dfbf48e37cfc84cd9059", - "kind": "transparent" - }, - { - "address": "0x5354F3C5fc438BBc77Ddd29B8bdaFDc32C8D9d56", - "txHash": "0x1f4d0069229711a44112fbb53a2f3b11b8608351d005bccbfbc9cd93479ccb80", - "kind": "transparent" - }, - { - "address": "0x3CaF0287166CD9354DAC212683F864F4A7327653", - "txHash": "0x1b64effd5517adb231226ecb2ec2868e1ac646af6ce3bad48d4466e35bbd3c07", - "kind": "transparent" - }, - { - "address": "0xf17126AD75F746BC66d7c8932d6a7486E9b83DDB", - "txHash": "0x7f4ddcb257c40403e49e8ce23d9bc373cccc889e439889179d57fb12750badbe", - "kind": "transparent" - }, - { - "address": "0x514c1114e2354bC946D02429BBc98fA767B12cB2", - "txHash": "0xe90797e5a87d15f253abe33e75067bb16a7ad000eaf3b82c81d2bf3f177e4b80", - "kind": "transparent" - }, - { - "address": "0x3d49e29F3835AA6d6c41F18ad6cc7943aAFd2035", - "txHash": "0x114f71f56147561f242e93854c1d5482a8c2e702e62abc2f1cd1025284c3373b", - "kind": "transparent" - }, - { - "address": "0x5c353460e6d85214271DB1f7Dae0cEc1c5e0067f", - "txHash": "0xe002b9331a4d9fd93ef3579dc91deab044b50d714c12157927a199310552d392", - "kind": "transparent" - }, - { - "address": "0x599d188d5B78Abf04aFd9A7F96C7eb2FaD7Dc036", - "txHash": "0x547738aeae8b49468dd239f85df9cf6e40bc89b34dd1136678f203c0aae07365", - "kind": "transparent" - }, - { - "address": "0x8C87E752e7572BdF7C9B7AA99C0359763edfb569", - "txHash": "0x53258a2ead6a190b83c964a1f72eb257add88be1974f0d94e554d7dd17796cfc", - "kind": "transparent" - }, - { - "address": "0x3bC1adCe925327D6305eD7301DFcAD9fc2ef24E5", - "txHash": "0xbe94471464bf8dc898d31392cca4b853e6a8d7582b3761e88c82797133ead104", - "kind": "transparent" - }, - { - "address": "0x933F075000B3Edf32730cA7adCD4b914092a13bb", - "txHash": "0x0cd9e489f9c062fe4c0dd4a8570ff8528d6b6efacff3468c05e288d7866b7521", - "kind": "transparent" - }, - { - "address": "0x11FECc00145769DD8A1262277E8B611a6fcD07a4", - "txHash": "0x9f1c3d2fc8a0f3d3fa152d78eed60ebf9aded34628eccad8b2de4764a265ab5f", - "kind": "transparent" - }, - { - "address": "0x448de26110D0a86BcB85C5D342505C916a2f6bdC", - "txHash": "0x8e0c112ee430e84bc03996e45cdf1d994d1e8d6c7430c99fe20d67b39aea30bd", - "kind": "transparent" - }, - { - "address": "0xD8510F7C7E1f866f74d3aADb0F7B4d8c43604bC7", - "txHash": "0xf2c2b6817a7d8a152dfcbc68214ed1f781ad09fa34777c353959a9586247495f", - "kind": "transparent" - }, - { - "address": "0xFAd49F264cd78E82559ed873Ac4aE417829D6df1", - "txHash": "0xd9cec08fe20f9071d494c4a4b413958bc6f5b8bdb139125147a1db7a604b3085", - "kind": "transparent" - }, - { - "address": "0x99361D1725982fed7d9b13AdF87c2ED4208bf131", - "txHash": "0xecd79ef0c088622cfa866b14035bcc1ccc1b08c5332f7b62ca557e2957f71da3", - "kind": "transparent" - }, - { - "address": "0x639b01C801b4d32A8E9a2e55F875A1CB05976CF3", - "txHash": "0x17224d44f120b3899ce9035d8f47a92a242eaa50de43df3860be51bb1a7dc4bb", - "kind": "transparent" - }, - { - "address": "0x7B4C21519051c3146cf285248cA255429354B3e9", - "txHash": "0x2ed698cd260d8bda4e1605f11feaec4a045b104ddcb7fdd978218ee12ee2ee5a", - "kind": "transparent" - }, - { - "address": "0x8427dFE982506e38e46B021cd8454199a68FD85E", - "txHash": "0x9d83653260df67277555900f997058d51d1f22ac78a82a35b66b921815143085", - "kind": "transparent" - }, - { - "address": "0x550a037c58E345F7478bB61635777fF0d61822a9", - "txHash": "0x9090deb10abea0979fd6a7eaa47b35e454d77398ac17904aa931f847ab8b6f43", - "kind": "transparent" - }, - { - "address": "0xDFc40Bff7864773Ef1c0c3C9C357Fb334B867367", - "txHash": "0x6c25d910274ad01bfb7627519d358e351c56a61bccb7fac9f6db2fa04cd9396c", - "kind": "transparent" - }, - { - "address": "0x6a5397633E1B7f551c1Cac3D58F888ce4AE15F24", - "txHash": "0x84a3fc7925a8c0294c129e05f14e14e795694f7f9f1a6ec8d1c13d8642a6de95", - "kind": "transparent" - }, - { - "address": "0x24d12Ea87B3756a044eB9A396Eb471e47FD2C62d", - "txHash": "0xd5a4e360e21782c64c0250b1f09f9fd1c4c715b8622a295c7991b4c1be308033", - "kind": "transparent" - }, - { - "address": "0x0E97416c5b9Bb978E1B064DC722db685e5CF3a4f", - "txHash": "0xd0e9942302479f3c830609d54e47c3e4ca0aafb9f7208a0a45b8f1be80506b0b", - "kind": "transparent" - }, - { - "address": "0x43c5e07418d516401d715A3267812F108CE837C8", - "txHash": "0x411751cea78e9222fe293944adb56adf3ff5a6e59bf6c8aaacf8c305d69e5926", - "kind": "transparent" - }, - { - "address": "0xA31df9fcDaB22c5d5adcB411A9F9822574c6C2c5", - "txHash": "0x0e9660f263b24865f7a5f4a6e4c7dffa66513f0d2945ffa1db7000860e5a7681", - "kind": "transparent" - }, - { - "address": "0xD8E63f8F8fE59E1D45E1ab2F87dF62f9EE08Ad07", - "txHash": "0x1563f1700aec1f663e0e6960ede0b17d997efee9ad879e590502b16fd3b93269", - "kind": "transparent" - }, - { - "address": "0xBA4399f4D7984a327631c9aBE8718E92a88620e1", - "txHash": "0x7072e8e603be9a861976a08f67a3c998161c2a4e95c196a76717cfe0b3d6c376", - "kind": "transparent" - }, - { - "address": "0xF2f89e0953862f46Ed788cf3707ccB82d6284AB7", - "txHash": "0x2cebd2072dfd6bf7ffb4cb91ac848b3754b56cc51dde00701204c5f1b27d7e84", - "kind": "transparent" - }, - { - "address": "0xeE39Cb6ef7e156261D8A14FEd729E93665245C6a", - "txHash": "0x34174cce8c3a7e1fcf376d84844e62adc1beae89ccdc317cfb7047f4c64ecf2e", - "kind": "transparent" - }, - { - "address": "0x6526efca4D752A1Be411FCd7b474E4Bf17Fe9e34", - "txHash": "0xeaf09b12c079fd78e4aea0fafcdca7d7c8d5f8a5fcffdc4460e03a9588424f6e", - "kind": "transparent" - }, - { - "address": "0x4045411E807aC695B89758AE9CcB3BC5D1459642", - "txHash": "0x38d8b37ea1051ef82aaaf5b96e748c2c4a5126847e4b3af0577cdad3a0a79dfa", - "kind": "transparent" - }, - { - "address": "0xb10c250E79effa63eE7f8EAaA3cDe5097e331D35", - "txHash": "0x1fa641417e91bfd9448fd54538cd2968e5748ea14e8429275c30f4372bacb658", - "kind": "transparent" - }, - { - "address": "0xD1F4a6EF47F8AdEf09Edfc4A0Facf3efc2702243", - "txHash": "0xbcb92a7bb0dbd2e4dfa32e650764997607807afac314475a67a05c722de3db4a", - "kind": "transparent" - }, - { - "address": "0xC0bAc4c637BEb053300803aE0fDBe470E6F21D4c", - "txHash": "0xcdd500e901c111e8b098d676da697195d9e7a67eeb1fde7a736206866507c576", - "kind": "transparent" - }, - { - "address": "0x6eC4E86A33671349221E56FbB185451504FE431A", - "txHash": "0x9a608f3d83a89e24c16ce37e99fd7b627f5fd82b521566ec2f1e89c8a45d2ae8", - "kind": "transparent" - }, - { - "address": "0x27c6168E416451Cf47F8a4399D76Cf4400359A65", - "txHash": "0xcc1a03866938625482f7ca851b3722b3134cd0572c6eb4ac2d34163fd7fb0470", - "kind": "transparent" - }, - { - "address": "0xCf11ecB95BB86aD0803403e09a473D06af2DD053", - "txHash": "0xe784403c9615c7e358fda90ba2c505c1b35f01e4791163a9779f871017114210", - "kind": "transparent" - }, - { - "address": "0xA8621Ec58E5690e8AC1C5FE65EB3C4E08f54af43", - "txHash": "0x7997e82a4c573373b9585e1c9bd3d6c62ee35cce761b47ef6c95c769ac873ed3", - "kind": "transparent" - }, - { - "address": "0x554725C54A923a539568FBDd530F334ec0dBA88E", - "txHash": "0x9dd68d634604f9f811ffb5d1ec4961a1cb457b47ab516b509dbf11d3e08175ef", - "kind": "transparent" - }, - { - "address": "0x7B14439Ae65930B443c7aD9d500aF2F3b942886A", - "txHash": "0x724f8c48f280d7eb906435667f611517629c55695ed5e369bbc0af66d39b7133", - "kind": "transparent" - }, - { - "address": "0x3dF2B63850516AeBaABf8F3BA921234e99EC564D", - "txHash": "0x78f29cf99c33ce5f7379fd6f481a1e5aaf391e4147238810139da19b4b09b79c", - "kind": "transparent" - }, - { - "address": "0xDd00E15b8745C909051DC6ddF00aeB4a474B05c7", - "txHash": "0xd8179ac59d61b5937970c8fdd44aed41e1d8b75b1704b0a19c3e3d07fafb2e72", - "kind": "transparent" - }, - { - "address": "0xFB286c49Fb1df1EC4A0Dc777AA7fF568056A5478", - "txHash": "0xdb9d6da0fc0af57ddeec4a5b91f9106e6eefbc6389750ef99c4194325dccc4ef", - "kind": "transparent" - }, - { - "address": "0x8fb2f9012103534ed5C2104A30c36F05EC10c2d1", - "txHash": "0x64dad95a14c2de52651282c3f1c882f8bb73f93021dcd8007cc3b8c8e2c89ff4", - "kind": "transparent" - }, - { - "address": "0xc39BdeC836fB4D3C2Fa1472B7797539F9Db4ca3b", - "txHash": "0x41e30359b093ef6fccb495629c39469c59ff8681d9bd27adabdc75a1cc019a24", - "kind": "transparent" - }, - { - "address": "0x8449D24e0A63ab45D41792A17743aD09194aAA14", - "txHash": "0x538456dca4e92a2f16867f1dbb61d362ea2a244cd4e0d0c7adba7b0ebf05f420", - "kind": "transparent" - }, - { - "address": "0xc829da2bB1529b2160209a10ae9Db1711Af65788", - "txHash": "0xd11762d6099ccaba044168440741f43a8d9bac5bd0e58fedb6589817938d0cef", - "kind": "transparent" - }, - { - "address": "0x0921dB32601d8BE6024f2f7D988cDd4158518545", - "txHash": "0x2070bdfcce8090fa4a4b61ff7ad982f30c90543322a78dd4568616a782dfd41c", - "kind": "transparent" - }, - { - "address": "0x740Cd8A92539Ede3D0a9e4d392Bb8c739bB8bbc8", - "txHash": "0xe0cb3f01b469c6dc9aa49afc13421fb9f433b808b0601af44afe3c23f15a62a6", - "kind": "transparent" - }, - { - "address": "0xed20303aCce2e4eb424EE0013dde571c169056b3", - "txHash": "0x75dbefad35a64e9fdad48c2ca377363c56b63c3b7411cac9b18996875f0e1c85", - "kind": "transparent" - }, - { - "address": "0x00A77455Bff29043C7324F48f4c6b32C082F8276", - "txHash": "0x67356c561ba13b6f17888607f2ee56324af1f45d774931f31191945eec3a7702", - "kind": "transparent" - }, - { - "address": "0x4F0D070CBC36226407f18588CcA7c1d2E292Bca0", - "txHash": "0x405e98ccc997b294324c147f9cf9c8c2011206e1467924e2b57c0ca8c7ddd105", - "kind": "transparent" - }, - { - "address": "0xfA5a5B69065bb8F3eE0a9d30889eDf92aDDdE7F1", - "txHash": "0x18f37ffe1a9c14f9107b3e44812c94b74506eae185d83d99cf24d9ea3822fb57", - "kind": "transparent" - }, - { - "address": "0x984F3b4B34A2D0417B4B1b30aDA14A2233103c7a", - "txHash": "0xca2b2fb3cb1dab3546ec28b9558c491cc563474482a13c1c3a4bc0ddc3d3f79a", - "kind": "transparent" - }, - { - "address": "0x51823fc931154cf8ac21480b211C906dD54d9529", - "txHash": "0x0bb10de4e405319d7d3839a2eb3e3caf645ac49b76a463252d2e8e0098637b20", - "kind": "transparent" - }, - { - "address": "0xD58C75276701717cd363E779B2f778360fb85F0a", - "txHash": "0xad478d836b50e1076ab01437dbb4d7ba7e499584556d196cbd49d67f02a1e4f0", - "kind": "transparent" - }, - { - "address": "0x0240f039254b2FB0ffCa56887b4DB8fe4b315C5F", - "txHash": "0x9c659db935a183e0d780a10bab7f42fd76defebf57c1c2e20aae7246422f6818", - "kind": "transparent" - }, - { - "address": "0x50260Ba376ec0f75319e275fb0B103c3f13A3D56", - "txHash": "0x4685f4f49e5c638068838e67e3aa9bcce667d7744edc47f18fb752aac937fa03", - "kind": "transparent" - }, - { - "address": "0x6fC71Bb34E2A464Fa1a0a7b31d4F6035e186618e", - "txHash": "0x7d74ae25d00ecee0bfac2254ab447022ee7bda0b3bd1dda1e31443c51228d7f0", - "kind": "transparent" - }, - { - "address": "0x99B4704257c3AEBE81607167422925727A617E6C", - "txHash": "0xb5d1e17a3bd892b8d64318538b2d388a7f76248d93b8b74087dcc075e9c3c990", - "kind": "transparent" - }, - { - "address": "0xFfDC509aC7Dda2dd75C423eaD4a8EdDFbD1977f6", - "txHash": "0xa6e6315ba69ad75fed5c58ab7378521691e3aaeb2689c712f85cc28ece1b7e1d", - "kind": "transparent" - }, - { - "address": "0xcbB188C0a6E55BE174F29e0c08285f1C2546299F", - "txHash": "0x7056ff04fd9424377f78d6579c03f999e41493be724665ca9b7f9c0f6f891aa0", - "kind": "transparent" - }, - { - "address": "0x50eA2e3C634344F69fF00f853c70B85752ceBE96", - "txHash": "0xd6cd52c86ad4df4d326bb386878e324b7373277f215242fa2ca2cba271b27785", - "kind": "transparent" - }, - { - "address": "0xc4456E436b4B2a8fA6c51D7d478Bc2443B04869C", - "txHash": "0x44d3924504f2a0bc42211c97354cb9aaa325b3da2414cf1a3f7386090329957e", - "kind": "transparent" - }, - { - "address": "0x1c7d53A186Ec93B595Bd632E29F3DD2400b5aa43", - "txHash": "0x09ba74966f63a3b10f7eedfbe4f39937f16cbefd6d4b2e23e838a2e2c0ff30df", - "kind": "transparent" - }, - { - "address": "0xBb35a7FBdC014D4eE29bd082bC3620aCBD8b7278", - "txHash": "0x84447e8363fd4a5a9dea7835755483d7795beb3db63eefe03075472169385c2a", - "kind": "transparent" - }, - { - "address": "0xFcF38C5Ad82D073C3D1bdC4835f427eD4Ccf1756", - "txHash": "0x3b16713bfb0985bc1973b156ed789e4719a18f60b650e2fae21a4a497c6cb7bb", - "kind": "transparent" - }, - { - "address": "0x7efa219Ae022Ae523069e3c6D20172975906DB33", - "txHash": "0xac45290dfcec15506f3d78f283084d86ddff65fc90ff73a28cf3a97b83927cb2", - "kind": "transparent" - }, - { - "address": "0x29C2C48030fea5e56C4729a898E320761C9fBf9a", - "txHash": "0x7cb62fab12f3d18b8555f7a97ff452bfdcaaf1a653be700ae9da44e314cf8689", - "kind": "transparent" - }, - { - "address": "0x6e955f7B5CA023EE3F7a114a8a79Fae1AFA167b1", - "txHash": "0xfab34de301a694274d9ec5e8dd2fbcbe6e785d790bea6b9c608057f2363225fb", - "kind": "transparent" - }, - { - "address": "0x7EC326B71627565a1A4521Cab216efD8FB1F3a85", - "txHash": "0x58d4ab55deb40bbfa46bcd94df05b3cc03c05c29000476b7debf234332c7ea22", - "kind": "transparent" - }, - { - "address": "0xDF45bFB404eb6cCcd4D99bF080a70f2Eab79cd65", - "txHash": "0x17de9ef873478b12905dbce33939f3c954f57d990817cfd69f44fa4fb54ab1cf", - "kind": "transparent" - }, - { - "address": "0xF6c745A8669e528d11cFBf61F3D56E8840E43D87", - "txHash": "0x74acc93e93ae3b2dc3dd6b2b9bbc31522414045d0a9884147a93650f026c6b9f", - "kind": "transparent" - }, - { - "address": "0x469A9f19d70260A6Ac469C7789790aCa5c6CbEF7", - "txHash": "0x00efb6b80e64d93dbf4572a0c2eecad36f092c77c1ad7d3f4be45dccc6de0796", - "kind": "transparent" - }, - { - "address": "0x2ADd4C32Aa2c1066C019e329188695521b2278E3", - "txHash": "0x29e3bc8f605bf2734bff922604fc09550053bd703b1892eb15696f505484de96", - "kind": "transparent" - }, - { - "address": "0x1D9d143dFBb5ED9BA1D110b3abeA42A3D7DE039b", - "txHash": "0x31f2f5d19586c90a6be37b2d55d516b3e923670ea8d39c889f1a8b624ccb3765", - "kind": "transparent" - }, - { - "address": "0xF9c7D812154A9306f71518EFb89e1995b3EF337c", - "txHash": "0x44196a1f0e22ff30d3fee73e330c00711bd6dc77f53ef3577f5ce50b93e4243d", - "kind": "transparent" - }, - { - "address": "0x6296a3C0C6c33Ff50C1F29a9d0663F04E88C3a80", - "txHash": "0xd256c524bd04e8e4ffd7fc54ebfa07dbf6c148eace4606d983a4ad84c0db6d8c", - "kind": "transparent" - }, - { - "address": "0x7671bdf6eEf3E2ABaa5e5076F0Ba2495c28F227c", - "txHash": "0xaac3a98dc107bebe4f7ed3642a49a0e8758df0315a0ca42c5c1210a34bdff82a", - "kind": "transparent" - }, - { - "address": "0x226B01dc077222e4755D00bA1063C21944d787Dd", - "txHash": "0x24c2fc9826234e8b76c3b221628aeeda95c14dc857d782cc7c4d4bffcdb8acb6", - "kind": "transparent" - }, - { - "address": "0x5087c199905B0a6B9535676A1EF5CA10E177D1b3", - "txHash": "0x68c223830bc5efda42adf2ba1d382e9c663969d6794655047a8c0adf70907603", - "kind": "transparent" - }, - { - "address": "0x935B9a22a8E0E4C4711E25713b2d60E223B20008", - "txHash": "0xe5ad0565d48766a37e1d24e0a6647b99ef4e380a6150755d3f240c8b37656ea2", - "kind": "transparent" - }, - { - "address": "0xd7c3FD2c96C80313cEa008bB0BC4Ec6194467B9c", - "txHash": "0x328e2901e59c32dc8034d861cec0d5d7e5caaa04d18373bdec87a2d17f21d641", - "kind": "transparent" - }, - { - "address": "0x35D6f4a2fCD955501c6D0051f62e22080c548fc3", - "txHash": "0xe85b1087050929befed63590e43c87b2e34be3c4620524c48f416b0ac3b3dcb2", - "kind": "transparent" - }, - { - "address": "0xf53996bA2360895e5f8319A72D7A3A55Cc8d99B1", - "txHash": "0xe19a7e873485d889ce0e0629a7dcf65615ed7f2b56f79f67959cca2908be3ac8", - "kind": "transparent" - }, - { - "address": "0x903E996F848502adB563538c5d568452B38821AD", - "txHash": "0x4b15aa2eaa95e38da615a512d4cfd997d1d79e729e36670c5eb7e28596d76545", - "kind": "transparent" - }, - { - "address": "0xF4aBe373CeEB3c7C8e619A48EcB9342103b995D5", - "txHash": "0x3b42758230dfc8abf516e0d0d635914a7d5a24b5d42f855046ccbf7de19b2c52", - "kind": "transparent" - }, - { - "address": "0xf3D194DCB594b98B8faFADAAAD24e81DE4783638", - "txHash": "0x26ff20ffae94f45a9dfac84c4c469ee5a17f41b580819681e3e7e170b09fc15d", - "kind": "transparent" - }, - { - "address": "0xA0d0F9DA105aE16df266DFc106fEBa28Af4a9f00", - "txHash": "0x642628bf6445dc8f01206aa01fa8df136218370d53ecb3fa679b9e04ba9b43e8", - "kind": "transparent" - }, - { - "address": "0xB201ACFaBF17E16e7EE1a39a9894d295c8dc3675", - "txHash": "0x0e4c313e082c4852bcaa80f1082706dc857684697397fafe9e0c09edfc9ec2df", - "kind": "transparent" - }, - { - "address": "0x998b41a3a879591398b6B74B08A59Bc740bE63FE", - "txHash": "0x3cc52babd508be338da2786f698b787067422784eaba3373613cc8c8c43f0ac6", - "kind": "transparent" - }, - { - "address": "0x555c9600968665710C76834D08d003f096cAD67B", - "txHash": "0x54f9f85de9cb735c8d0e00d2a7553dd82d6b6798ca6ad8edbcae6def6624caef", - "kind": "transparent" - }, - { - "address": "0x7cE665847aA8334DA7B22f76915b9630D572eA1A", - "txHash": "0x00ceb8e82dc832c8116dee8f458de1b0e362760c780dcac764ad3b5660dadf30", - "kind": "transparent" - }, - { - "address": "0xAd2013Bc783F1500a632395bDEce04479d5dC55F", - "txHash": "0x231d5ab86379454f7745602366237fa6806cbd5d7565f54af36374916f9b9d70", - "kind": "transparent" - }, - { - "address": "0x562e0B111060A34b884e8A6C00ce7B54B72b4B5F", - "txHash": "0x28bbf4ceae4588c3aa91b84a1a73708ccc4c82ab2cc8b1fa18df92435e2d5593", - "kind": "transparent" - }, - { - "address": "0xFeFCa4609CCc05CFd61e1Ee221b62c5b0097A5F0", - "txHash": "0x01765c563fa1feb9bbb9c8fd9d4cc0942c739172e73dbe6172303b982510d9e6", - "kind": "transparent" - }, - { - "address": "0x65093057883F56D79eABe3E6CE93CCD504cD192D", - "txHash": "0x4820965ef93fd56711d9a2f094f5e0a3965df4dac4a84bb47386e06abf7fc735", - "kind": "transparent" - }, - { - "address": "0x02CC4fD14F3854cFb01B59EF2fe8D4228eC81bC8", - "txHash": "0x9f0729c88ce52957affa3272cc1144454a8a4300f46e3f8816289ece4cf68f32", - "kind": "transparent" - }, - { - "address": "0x74Ba9A1376d3f87B1dc6BCC3aC17B60c222a2B87", - "txHash": "0xcd93e15c9c5e2d10c289c1e65eaf9a18e05896338813885cb16d63a222126275", - "kind": "transparent" - }, - { - "address": "0x4bF16532B67bcBBe054f0eB0c47626687DF487d5", - "txHash": "0x34dbd57f370d051f4869ba153968573d4524185eda95e834e8151802893919c6", - "kind": "transparent" - }, - { - "address": "0x530C6819b40B5FFEa86c6Be5BcACA4b991bF800A", - "txHash": "0x7be4c7b7216f27bd8d34e97f417bf178a711eea66ba516bc6e434c9b2f0dd3e7", - "kind": "transparent" - }, - { - "address": "0x368b768A0C69Ef6E705872A64eDfA041335d6Ab1", - "txHash": "0x71521ae89ec87a466819964f834f5e283ffaea45973c9deb392877b3f72212a7", - "kind": "transparent" - }, - { - "address": "0x987D05c08B18Cb9c1F792AF857F898761Af6f3C7", - "txHash": "0xf51d14e225f51c34e72abb6a15082c955e782387e10835a8f21ddf2e1d54e355", - "kind": "transparent" - }, - { - "address": "0xBf31aF6243709c1Bd5Ba6D26FFc0C2aEF773Dc0F", - "txHash": "0x0bc5d97b3950f9f3a2958c86049220b6b7a50000854b25407c8204b7c7956238", - "kind": "transparent" - }, - { - "address": "0xCA7304ec58AEd3b4103683280F0E3Df50B9f7e47", - "txHash": "0x9b33b0948f8707e6571d37a9506dacb8ee61d121832664716683d99067783cf2", - "kind": "transparent" - }, - { - "address": "0x05a4d5e26f667aAB4FcD40BF90D92631d1788331", - "txHash": "0xc07967121f183b3f289d9f2bf40655f41d5386bcf7bbb6e289e5e508daf47859", - "kind": "transparent" - }, - { - "address": "0x82A37683D9E03E06269099fa2A78ae0244deAABf", - "txHash": "0x38cb540619926886498f9412800446e6798714a15caaf10cb61bf2363ae072eb", - "kind": "transparent" - }, - { - "address": "0x86C6217b6F52470598D4BBD2fd43f5fd7cA9C3C3", - "txHash": "0x0e34153b9d7ba763ff36491156cf52752d14bfb0635e3bd6b2d418cd5b5aa927", - "kind": "transparent" - }, - { - "address": "0x01C568f28B6FE1ee1b93C63D6Bac430780497b18", - "txHash": "0x1214c7cb10f93613c3e510fbc95ec940044b10c8441a7f75b0a41c7eefe08873", - "kind": "transparent" - }, - { - "address": "0x24d7391525C63Dbd9986DA271Fc8383108ed08EE", - "txHash": "0x21c9613934a2bef76aa89955e04937463f2054b82334906e4802e9c0935862ea", - "kind": "transparent" - }, - { - "address": "0x6544Ae208aEA20ce5c490f3A5e210B961bB1177f", - "txHash": "0x9d9523e5ed70bd1ec49eb00618be2293136a03dcd9923f3e68cb9a7a5506f1c3", - "kind": "transparent" - }, - { - "address": "0x307b196d6f448dEB208006a6E846B6af660306da", - "txHash": "0x509779b84879c3d81372e8b07bf5df133b155551ca29f09091f5db079178c055", - "kind": "transparent" - }, - { - "address": "0x75Cb820702F6e53B988D521475401bB198D73D7d", - "txHash": "0x14f6e252c40376595ac44888a77496265d073e11ba4294d6e064c44024b0db14", - "kind": "transparent" - }, - { - "address": "0x08C3000A916246501fBa62998c8e33b1259629a3", - "txHash": "0x43d64799e498d47b84ece4ca815a811f1013eee57bcaee35c384459d20597921", - "kind": "transparent" - }, - { - "address": "0xa3ff03BEe24C88Ee8B9Bc84ab74C1CF553CeCE6C", - "txHash": "0xfb1282fbab306484375092611dd50d96ea14259dd69aac109a3923bf4ab3fc60", - "kind": "transparent" - }, - { - "address": "0x87490276F25589eAEDfb810f6588Da6a4E8a1428", - "txHash": "0xdf71251f4630cc0e82418e8f1ec31632e0c25e08d03032da7ec6236743c395a9", - "kind": "transparent" - }, - { - "address": "0x7CdbDA365810fB8Ac8AddA014CBa335CB7425cA3", - "txHash": "0x57647b9b6e5d3cabfadf314e173f2cde4a7d1f2599be310760613c5e0056c834", - "kind": "transparent" - }, - { - "address": "0xc7958dAc9ffa40D3B82D3f975F0bea0EEbafDaf6", - "txHash": "0x0c085d7211d2df49cd2fe8c86c3854381e9327251941978f9cb4fdddfb509399", - "kind": "transparent" - }, - { - "address": "0xd9b234e59B7410646c80abb870838e665e69F0c4", - "txHash": "0x630f3fcfef9e89f15f3447075adf6505d54b8a0bcad08bb8f05ab5e0d0257328", - "kind": "transparent" - }, - { - "address": "0x55186C26326b725D0C69e599D083fa25DC1A4de1", - "txHash": "0x01ea74b65fbadad3c6cdb46a5d0633509fa6bddfedac3bc6100c2447a44bc872", - "kind": "transparent" - }, - { - "address": "0xA314CA3Da28D0ccf7CF2D125Fd1D953d53390c42", - "txHash": "0x894a15108d84d90598b8c49a8f424b4209580c718efb86a68aa9b52c3fae9bdf", - "kind": "transparent" - }, - { - "address": "0x9FcB34740eC51dAD38483AA8544410b76165cad4", - "txHash": "0x7002b32fdc8cf806276fabeedd413bee8402e21de1d6bcabf1c94c37e30f51d2", - "kind": "transparent" - }, - { - "address": "0x672D3FB5B0D05560f998Dc3B786721f066Be316B", - "txHash": "0x265fc0686842ad4db7bffd4998a577842d242f7978f9e0a43c0a0c7e1f775737", - "kind": "transparent" - }, - { - "address": "0xbe45e5F5d2b176d62E3bBbb008A433ECcCBe1cC9", - "txHash": "0xce662ae46c37feef010ac8f895505bdaa691b70678bb9583c4f8cd9147ef4797", - "kind": "transparent" - }, - { - "address": "0x866f949b9e8F610E9734dF8ED63Bf61DA32C527B", - "txHash": "0xfe8352c3b793a2a2063df6c877cd6b54f25224861966227cbff2d6bb6e6146b6", - "kind": "transparent" - }, - { - "address": "0x2a52eaeFeA9421C0BeDCDe47eFb82b8546aaA03a", - "txHash": "0x448f9ee1ce9fa9ed0ed1863b4f6706e470c896327e1c6e76aeb6c02be5c5e953", - "kind": "transparent" - }, - { - "address": "0x51dF71312b975CE0c3aFD1AC99e8185CD82bEA8f", - "txHash": "0x149c3795a733e6bbb30e57906c1df6421440040222481170d94046f672c8d52b", - "kind": "transparent" - }, - { - "address": "0x970ecBA270Fe144CB77771471513d49059c3DCA3", - "txHash": "0x8729e1c2151dc9f60c2fb1d9bd5123bb55690fae721c0024ba7d810cba92dd97", - "kind": "transparent" - }, - { - "address": "0x97f025688a3AaC54C08C2afeF0e9a42D517Eb7fB", - "txHash": "0x27e9662377deab764336e4dc2997ae61bd68137c38a6414728eb408b4bca119a", - "kind": "transparent" - }, - { - "address": "0xA906D9214214551e8DFa967359F379ad853D67A6", - "txHash": "0x76a7c1e5457763ae6d01efcc11331299de266f851e9f563ba6b8fdf169995ce5", - "kind": "transparent" - }, - { - "address": "0x575b92C68a23E6D386eD5Ec61cff4342De79b305", - "txHash": "0x5356aed85c1ea3985520ca6fa732e9cf25070bea8eb207402b97c8097ee6436a", - "kind": "transparent" - }, - { - "address": "0x641756C6B34ee7Daf900da401Fd9CD5da881F368", - "txHash": "0x7345d3587671f4a71887d6c44a4a49bd36d67661909c9b1445749f5a5a2be2f7", - "kind": "transparent" - }, - { - "address": "0xD9fB35BBeb8de8bA3786FfcdA3CbAE39fF55104C", - "txHash": "0x3c5a52085859bf24b93ea6be4478c6899ad28592a1e985705a0e442d701efb0e", - "kind": "transparent" - }, - { - "address": "0x6D3762E4FB416d81bd520285B2F96f7880767DB0", - "txHash": "0x9fbc1f7e9d9052e97d5b8fa20ed26c1e3ead3a09c07035ea6b109037fb97d96e", - "kind": "transparent" - }, - { - "address": "0x7186a7C120576D41fa68090E45F9A97e2A336819", - "txHash": "0xf803afa4c60d962ff647fbb642532c0a7b62ff155c42905eeef8f60ceecbb7fa", - "kind": "transparent" - }, - { - "address": "0xd7eA292f6C60a860Cb89D0f8a46b97007BcF29BA", - "txHash": "0xbba7d39cfdfc528ae0c38516198e13adcc6d696946eafdfd0eac2a0f1fa88933", - "kind": "transparent" - }, - { - "address": "0x492536ee9B879267146187C57d21aC76eb6fc050", - "txHash": "0x807d0126b5541bb096dd5ccf1088ab50cf739e2bf63a9e83f6098e118eeae4aa", - "kind": "transparent" - }, - { - "address": "0xd33c7abF7A40A587A9DB0A1BcFdE6e36b980054e", - "txHash": "0xf5d0de7f2e50de0b26cd58dfb19d7879e8fef99f7c1825dc63c7526bd0bea242", - "kind": "transparent" - }, - { - "address": "0xb92244591d38F273EdE408c47FfC37F397D9Aa55", - "txHash": "0x63cba63201fdcb7466474a3d3564d776326279e6185d09d5c7decaeeafc508ca", - "kind": "transparent" - }, - { - "address": "0xa48163A36485Fd25BcDB57Ba7A19fB82af74e7d6", - "txHash": "0x298ed624f827b2013b79a54ecdde0e853d5e9105d1ebbda00e509a4269951ad0", - "kind": "transparent" - }, - { - "address": "0x0b1c79bc465e1124B6ff21ab56149E347Bf8366d", - "txHash": "0x5c77fdb19627baf9937f5578c8f1b5b124e72ec4abb1438d1475040555f81676", - "kind": "transparent" - }, - { - "address": "0xd54A236b53483b97f4759E8090d520b80cD5521b", - "txHash": "0x647fc14f9872d7fd1e61111733a2cb97c55eaa589e53459e712ff941ab305d7d", - "kind": "transparent" - }, - { - "address": "0x4EeE2A922Cc80278e627AB204db3096F305e8338", - "txHash": "0x633956cfec84602a157dd46815afd3517a3afdb67aa370494cc4c97b4a3412fb", - "kind": "transparent" - }, - { - "address": "0x57101Cae1c05bfA69941661028DFF622Cf644F43", - "txHash": "0x7c4bd3ef65fc196160aa20d229cc3d0a8abfd2c8462d072e05c9d51daf4b330c", - "kind": "transparent" - }, - { - "address": "0x51796E7Ccd3bBe739424c78FC0D0935712A94Ad0", - "txHash": "0x0379bbf7d616b52500f41d1652b98296f62c6ecb867a4511c134963cd8658770", - "kind": "transparent" - }, - { - "address": "0x02cd3dEE4691066e48956555bE3B6df3c9C9d15B", - "txHash": "0xe259566c23c6e7c5db98db2303a6a6043daec57f8c322e86fd846275751ac381", - "kind": "transparent" - }, - { - "address": "0x157472D689C6F775A8b3972D5A4471f9b9BC3c88", - "txHash": "0xbb30fb70b931bc278fdfdd2fe05610e969e6f0b2cd27c0084cc3b2815abd5eda", - "kind": "transparent" - }, - { - "address": "0xB504d737939B038A92da89397053D782787D4c05", - "txHash": "0xc34c56821d2be14f304da9be38b8b8fa58b8aa1084ad345b956dd1a6d82a8151", - "kind": "transparent" - }, - { - "address": "0xC70A926b2a5753188C6Abe04a266CE1FfB11c7aA", - "txHash": "0xf523eabeed30613e79a45d2593d1e776df1ce71c1738b1ea0bbf9c4531b4e0bc", - "kind": "transparent" - }, - { - "address": "0xB12c6e534Caf64Fadd6B807D7cdCad87385C674B", - "txHash": "0x134c28fc8ed9f948f2a687efb9e41ef6a95b37de76d9346ca1848bec16e01f9c", - "kind": "transparent" - }, - { - "address": "0x079adF54d7105476B9dd6e93EF347114c1f6848b", - "txHash": "0xea71d77a33c13c8b45311a166ad24251e3a116c7d5ffbb3270148f1e98d6fb95", - "kind": "transparent" - }, - { - "address": "0xd01EcbC16657B5A5E99AB1361edE8F3A453C09a2", - "txHash": "0xf85111a1e0efc69f63d6ede4450e1ffd1aca5c002259d14fda7118890295e4a2", - "kind": "transparent" - }, - { - "address": "0xa1B0a267F535F9CE3265e5356D3414c12416221D", - "txHash": "0xe1c0089395b8e9042b122cd90a975a5faff7c21850f5eec4ce0a503ff54a0367", - "kind": "transparent" - }, - { - "address": "0x8032BcE8ea4Fe98F00a6e4962F635EBcdC0C5c84", - "txHash": "0x2c9015e29899a59d9dcce81daea7706aac86db502af00056961ca59f64822e00", - "kind": "transparent" - }, - { - "address": "0x39675061Ae47fc270624C33220a0EA1d9DFFd545", - "txHash": "0x8c4b6b72fcff2f3f20875cdfe4a57b814d3724af8a3a0c554203d6fef34bc24f", - "kind": "transparent" - }, - { - "address": "0x8535D530D50c65036e57C1e92B03D0dc66232193", - "txHash": "0x88d51a48985313e907a03a0fe474e1f05c1d08fa9079b56bab0970832d987a29", - "kind": "transparent" - }, - { - "address": "0xeC0FbC14948c67Aa14839411A21211CfD020a26e", - "txHash": "0xc06b5a554aacd459b8227c6a77718693eb9598f8bb416eb77e82545556585706", - "kind": "transparent" - }, - { - "address": "0xC1ff5069D59934B1F08B5574c15CFec023AD0CE6", - "txHash": "0x5c48b84be24c1388e51053206253794565ecf02cd51ff2abaa51dc563292416f", - "kind": "transparent" - }, - { - "address": "0xcA2D87cD82C5c8CA418798867494F69E9Fae6228", - "txHash": "0x704cfbcc94947063d208d382bb7840ee43492be0b1b52ca199e2e120bdd3f3c3", - "kind": "transparent" - }, - { - "address": "0xe7D5CDA9Aa1b657EE14F077d11620efE555C042F", - "txHash": "0x8f691268f9276388e18e6f1cfad9ff9d9d4167ba0692001bf8ef011bd38390d7", - "kind": "transparent" - }, - { - "address": "0x97749e50aB0849d3f0dAF1d1B264E9b008D8A95B", - "txHash": "0x5cdd5335d3a4878faa7d39d9252611d7d0554962eb1bb0f457e9d107abb0f894", - "kind": "transparent" - }, - { - "address": "0xB51a9F6A51eC4638BC5FEfd61E66A553165F993E", - "txHash": "0xb7ce97e42cc5fc7e82d47164e72fbe9bea4d18bd62cb85bcd163691f9bfe6942", - "kind": "transparent" - }, - { - "address": "0x17d03C12Da29C27D8106DfD777c4515eFf8B0EAd", - "txHash": "0xf68e42ad458f038948367793e3ee94e0e8ba8e915feda0c1a72467a5923bb6ac", - "kind": "transparent" - }, - { - "address": "0x29c4D8c820a88C9Ea7638e95292F311A8390a110", - "txHash": "0x87ef3028443ef90ad6a7d7ad4cf56c51e4268af639aadca7aec9c4fe33a8e46c", - "kind": "transparent" - }, - { - "address": "0xCDd1E66f0181990c4B22E674c29595C430F57b27", - "txHash": "0xc6c3fac641d825aa937334c300a0adc07b97d53c0abf64b33bc864537bda46dc", - "kind": "transparent" - }, - { - "address": "0x00770560AdAEaB6F8f7049fD2A3b8445Ff8B88a8", - "txHash": "0x58240b1de802602dc22847cec31dd97cf27f05c4ed3377b46717ad5f6d093be3", - "kind": "transparent" - }, - { - "address": "0x84d99F1edBdcB3D2bAF7F34fFc9B6f284c0D9830", - "txHash": "0xcddcfa24c3ced9aad1e6c6445b662207e669edfa3c8059aa7a2b04172771af5f", - "kind": "transparent" - }, - { - "address": "0x5ff9c8f7c5110a5300f647c1Cb97e6F2d72929E5", - "txHash": "0x3eb2e6ce492f23a6997c5ec51fb41e5a6db6bbbcc6a15307eaa1117dcd718986", - "kind": "transparent" - }, - { - "address": "0x9e31d9a4974Cc4675029bE37fFc9Df6a4274a2e6", - "txHash": "0x31460224990112fb83f61bf236bfd2d318cb0b0191b7d370f3e490a85d2d7c05", - "kind": "transparent" - }, - { - "address": "0x0D4bDD620bc6a16614956DddA3DAcF61049107bd", - "txHash": "0x51c2f936b38f92efea5d18d63eda466d40886cb57244b9a59323e3e1c936fcaf", - "kind": "transparent" - }, - { - "address": "0xF5F427940B9F1abbE127BF6a18dDFf02dEdE3E5D", - "txHash": "0x05ee0a57fcdd0f51944892a0f6fdb283f92318387b6dae02c7fb91ca9ecd52ee", - "kind": "transparent" - }, - { - "address": "0x66490ba23cF35367FBf51BA518BBb2475A06736f", - "txHash": "0xdfc91a07b928e01a2e90e577508c23b0954dc6448f1f70413a0576736db7cc07", - "kind": "transparent" - }, - { - "address": "0x1372fFbd9Bf03d5690d14FE508761e7D97eE97a1", - "txHash": "0x469424a0dcde4a2ec00d0b19fbf51130b5817fe34cb564942b5ae408be69cc51", - "kind": "transparent" - }, - { - "address": "0x5794f304E6aE48532f705a44A8D9C30D76569d7B", - "txHash": "0xa12bb142b0e169355997efabd0de9adb69433c120cfcea956f0d6eff2a74a12e", - "kind": "transparent" - }, - { - "address": "0xe2aA6d2C66616B2861fc708BCbbEb6bdE4D39F3b", - "txHash": "0x79172248d033cabb9e2519de54eefd1fcff7a4e1a220210e76634daf18e50fbe", - "kind": "transparent" - }, - { - "address": "0x2Cf7bC9f68E156F8d860aEaAC0758b34168b1Bf0", - "txHash": "0xe84bc5776e2e461f81d3e5a570f983823e368008b8633c5da724749747bc5f1c", - "kind": "transparent" - }, - { - "address": "0x20781d9b92c49d073d7d791908E98C652237274D", - "txHash": "0x97263f8493e13ccdc304972036fc1644c9d45934713ea56e09d137f15340540c", - "kind": "transparent" - }, - { - "address": "0xa1b8af4b086A40d48614c549D06C5484acFeDe0b", - "txHash": "0xb23c8a8f6a97ef72e9d15aa940297df2a53546ea4a0e8c3bb18d7bfc8b05cba2", - "kind": "transparent" - }, - { - "address": "0xb8295381a6b2eDd67628B707100A81428e67a214", - "txHash": "0x2dd6a4d3f4231a7e8c18566be262cc1623f9aae89852505132f5d52f38cd28d6", - "kind": "transparent" - }, - { - "address": "0x73d4aB45e6351dfd723608F5581023c83aDEA2c7", - "txHash": "0xad1356f301a0efadeb0201e443c80a0221476384deebb89067c7d4b8f5384d93", - "kind": "transparent" - }, - { - "address": "0x4d54c80049f92FB1Ca3c037b3B236d8f558206d8", - "txHash": "0x62a562765a87a4c164ed23efae32c7ca6aa9961d419e8548c8c8fb1054b66f64", - "kind": "transparent" - }, - { - "address": "0xc911228c0548033EbB4DD104324DDf864f4Cc689", - "txHash": "0x66e03d1f14654b36b14da8cc4a97c235ad8e05988b01012798dcfb172f5314d5", - "kind": "transparent" - }, - { - "address": "0xcc1Ebed13ea1dF5B179812e290146a18461e84d6", - "txHash": "0xc12724f08344adf9e92f63380392f8edf79d056ea797f61f83d26647ceca30a0", - "kind": "transparent" - }, - { - "address": "0x4908aca80f2b43d72C4380844Ac9EA395F23d21d", - "txHash": "0xac87a554f9b267d64e4aea5e939d503da42b0c41ceed4118eb22b99b00c7e000", - "kind": "transparent" - }, - { - "address": "0xf7193395435435FC0f312aFA9e7A6DAc6B827a29", - "txHash": "0x9cc1a0f3e16835724bf11de8b58b0c227f3c7e5b077bb2ad2cb7f52ff5f0cc80", - "kind": "transparent" - }, - { - "address": "0xC722EBf76B7fa7649b389BaedbB1448731b043fC", - "txHash": "0x528cef9909a9af405086b4fac663c0114ad93020da54acdd9049d70f1c81e3fc", - "kind": "transparent" - }, - { - "address": "0xe1F65C1F2a9Ef8B2b8f1b4164197f4e585CaED46", - "txHash": "0x599bee68a51b045fa48da0b9ed6cfc2a6103338079d14f13f7c8e7bdeb1919a9", - "kind": "transparent" - }, - { - "address": "0xFbf1F2A47961C62EA0F95d2F2028F734f5Bdc44C", - "txHash": "0x84c0d3a0e4d93cdffabf957935049af1918103ea45366d256ea47def11234476", - "kind": "transparent" - }, - { - "address": "0xdf3B9740F93894601BA9Dc7db507e9B3772c05F9", - "txHash": "0xca64158e83d9021999a9114ff367706816a04e5099b314db5e0eca7b11e54d76", - "kind": "transparent" - }, - { - "address": "0x8c0D430F5451bAdE3f9c60d00811b05Df797DcBA", - "txHash": "0x2f31c890d6a4baca1875118005966ae1f083c90c7c76143de431ec95cade994d", - "kind": "transparent" - }, - { - "address": "0x1719828b3381c569454F2DDD803bC59568101153", - "txHash": "0x58a60c5c202cdcae94398aff6662502e67a1e0cbe90479372ff1fe8ca4120dd1", - "kind": "transparent" - }, - { - "address": "0x55912914022D677820d0ef42178eE845538A27cD", - "txHash": "0xcaa95a8c3ae3c2135279448e9038ef0778ff765a5364c15851ad0ea7d4fcebca", - "kind": "transparent" - }, - { - "address": "0x79196482d24DadF9205f2637856917bECDC99e20", - "txHash": "0x2396f3055c726906f49b29023081ff334e22cef2a82f172be5e12fb22d816b44", - "kind": "transparent" - }, - { - "address": "0x97DeBDEff15fd4691ca215f520d487a36e1406A9", - "txHash": "0x6487d38174e2d377db9178a824cc4b324cdb284ce023f62aa9383b0e7d2f8764", - "kind": "transparent" - }, - { - "address": "0xaeF2E704fc1918c1d443865B686CD93328c72811", - "txHash": "0x8f882ee8f09ad85ba209ba5e6c96d914078408f44b0420148a60b8d500e17041", - "kind": "transparent" - }, - { - "address": "0x7E28AAdf2FBE99578d12E347738e71dBCee5a48E", - "txHash": "0x78bebf63a3760479dc1f282d76507649cc5efdd00f60bd6f548c356ebbf37048", - "kind": "transparent" - }, - { - "address": "0x0DD2E4C2F53569F7b989618dFB65F2b2fAfBE75c", - "txHash": "0x1682701809ef30c667a5e849aabe78d9d99aeaba141e493d2acf9a2a25572e8a", - "kind": "transparent" - }, - { - "address": "0xE4519463B21fE0df16De317D3e74AEebBD40D46B", - "txHash": "0x29efaff6ae9507861b7781092b00a1afe296c1ff03f5a6d69cfd5b5091de75ba", - "kind": "transparent" - }, - { - "address": "0xFE73b16c282Ad21b64877c54443Ff0A3e5c3d71F", - "txHash": "0x0051e3a3cc0336bd367b0a3afb069460a9518d3a9d7f65c78a48e537d5d9e5c9", - "kind": "transparent" - }, - { - "address": "0xe72F09B421Df28B99B6CCEe6fB5c1A68D9E292e9", - "txHash": "0x37fc8408be589e4dcf9ff6d1baf11aed922a50313b8c793c26341d11d8a1f54d", - "kind": "transparent" - }, - { - "address": "0x74A819c920251Ee4b63Ab3E4E793866194fCe6Ef", - "txHash": "0x86a6701dd3d231cc8bb41d63ffb28abdafdd6e7cf791c022c6767e1a882de478", - "kind": "transparent" - }, - { - "address": "0xD7BfFC984EE9ed032B740448a5041d5165823B8A", - "txHash": "0x1845f40290dc3d48c808a8a165f1e56d66179d3013403922e2a018965faf9381", - "kind": "transparent" - }, - { - "address": "0x7ae5f8A3bA594348129b062f498AF12DC7fCC108", - "txHash": "0xabc855227bb4f122498b2f2191a5c46b7cc40c6dd1cecd36bc941d4cf1f091aa", - "kind": "transparent" - }, - { - "address": "0x7C72b37Da53DFED9166d3b11A41DF825D16C19D8", - "txHash": "0x9e4f98cd77efa1cc2926f040482fd542f455ba7e0ae8a8bdf6b449ab34ffa445", - "kind": "transparent" - }, - { - "address": "0x1304fD6Dcf0B27A05399B9BBf335f4f5BB60a894", - "txHash": "0xbddbf422e232a6346ab188e3e0fc984e1566ee69b607b8b3be6e991a1f1952e7", - "kind": "transparent" - }, - { - "address": "0xEe0a4c3856F82C9a12151A4729F89Dd85AbC3d20", - "txHash": "0xc192b9ed18e9176947c77a63dfe8e804eaeb70f87becec7e3790febb88673eb8", - "kind": "transparent" - }, - { - "address": "0x42441eEA513cb742b6e55687e321CEC43db47A38", - "txHash": "0x07d9141ee16674e5b7ad0aeaceb59471672ffd288d64be400d3ca04a43ffa05a", - "kind": "transparent" - }, - { - "address": "0x0F65e267Cd067FAD469c8e066844Cf131722788e", - "txHash": "0x86e9d99ee16cfa7004338950c387c7d4c3886c8c879a39af9b69e8112ef9103f", - "kind": "transparent" - }, - { - "address": "0xD0F3F2526D2511778306f31766fd32e3aD6997c4", - "txHash": "0x086e722fa746368369cd43ac18be45685c46cbbac2d9cb11272a1ba0f7da22b8", - "kind": "transparent" - }, - { - "address": "0x080F43c97f01CAC59e87b43E1620a7C61CaF157C", - "txHash": "0xc267cc96148e0691c2db3a1253600a118f1a75d61c06321ffa4b22476ae96046", - "kind": "transparent" - }, - { - "address": "0xC390F90A93caC1691993f77E07e8B126DbAC60E3", - "txHash": "0x4486a4726ba5574a85ae3a62510a7c6e67bdd0486a38d1f7181201cadc842095", - "kind": "transparent" - }, - { - "address": "0xdE392Ce20B7581828b8408d9F3e84ad9c892956d", - "txHash": "0x1aa4daa1555ae6ada7dd191614748b4d19c021893e565bdc75c14dd4261a7dcd", - "kind": "transparent" - }, - { - "address": "0xfFF9b5B2193C91fb6ae65CCE5ff0648434c2ff58", - "txHash": "0xce04544308c7a02a0a568eda607e9f1ec69da828a15464a4f9e2493fb46893d2", - "kind": "transparent" - }, - { - "address": "0x1D499F91c260DBaba4af7C3931147D0675B2C924", - "txHash": "0x636df4f967415255bfda96c70ed0db8a285a58564f1465c735b79c6396f57f0d", - "kind": "transparent" - }, - { - "address": "0xB3d4EA3393387A2D169DB126fad6DC28019e945a", - "txHash": "0x5954b25dd41b0790a796dfc11195cf280ec2187373a504b054b4e6992fef08f1", - "kind": "transparent" - }, - { - "address": "0xF2ADfC464d3c970ccF8770F16Eeb7313c7e775C5", - "txHash": "0x24cad563545385ced878cbc76b1ec330f8a8a2b0fa2841c04ac11575dcdf94ad", - "kind": "transparent" - }, - { - "address": "0x9850D8739be63292E4efDCcb4faaEab1675c5BC5", - "txHash": "0x181fc56fa83fc609f3bcbdc553325cb56eda21255d5af38970fac81bcc9fb6f0", - "kind": "transparent" - }, - { - "address": "0x509B9E90f188a0c1b1860766dabaa2c18E5be72d", - "txHash": "0x2569256350ac5e8e9bb2f9816952692f062c490f0dea69a17290d274c7115404", - "kind": "transparent" - }, - { - "address": "0x77e38ee114250b1c969cF6C881AFdA7e754B88f2", - "txHash": "0x18e3725f16fd22397acdffaf455bb080cac2ccf4bf330f7ae62f37e438a95f95", - "kind": "transparent" - }, - { - "address": "0xef12EEe0BE8ed1eE4242B89Cd10D58473C58E23A", - "txHash": "0x10c9bf1e3b3dd5cdfedea683ffdace274df7d7f4e4f4452752472ebea4c8b083", - "kind": "transparent" - }, - { - "address": "0xC147cDC91a19D4e2B588783AD36330f4CD510eBf", - "txHash": "0x34293c4a4b9a5467f99a3fe8f79c5c02523ac5dfe3ed42387192966a6790cf42", - "kind": "transparent" - }, - { - "address": "0x4038fc590D584379db8Ee004351CaF927Ee16ae8", - "txHash": "0x82e38d982f87a9f154ce96b362cb1c098ecbe143d5b4e1172868a65236912f20", - "kind": "transparent" - }, - { - "address": "0x7c6E1D677a3cE037b4e818e280A5c03f8f6926F5", - "txHash": "0x7fe5db28d07ce1a9c127b47e4617e63773b869e10e764c720493b066b1374ecc", - "kind": "transparent" - }, - { - "address": "0xE1D443B9D4E937bBC4D690e8eC9eA766527a1a1c", - "txHash": "0x29f5c7ebc55c81ce96f40a4f976a7c9639768acb2b169a9f4de5494cb682a910", - "kind": "transparent" - }, - { - "address": "0xeE2c5709520719B067ef10Cf1614F772960c146d", - "txHash": "0xc61998c3dedd74c13c446c41e8acc489a95f1ab387e51209bed953f6d0cd347e", - "kind": "transparent" - }, - { - "address": "0xc6b64a27BF8874ea659349E18c487bA0922C55E3", - "txHash": "0x0959496bd3e2ec10f814f08a44d1af13b4228e0716376b0491f636f9f354518e", - "kind": "transparent" - }, - { - "address": "0x835eCF7B72f228F4Fbf1156daabE14fb008332fd", - "txHash": "0xc6a47c8957ec817317668e0718cc7085ca3a676d62da37ee7d24824a3ceeeace", - "kind": "transparent" - }, - { - "address": "0x86F3A4F64B293f67C1F654ea6c1aaBf645957493", - "txHash": "0x12a94bafd39ef77e24b73ebf97d75a7b22d30de60719dc126e4f16c2385a7b37", - "kind": "transparent" - }, - { - "address": "0xdcceD94587776500597874fDC9267fa88688Ce9a", - "txHash": "0x08b18d0487e1414e3875f94a4672ec7aea361107b0ac210980e6fb2bdb20b705", - "kind": "transparent" - }, - { - "address": "0x50aB3361692CE26E20fd619d8FeB8a37f9cd8adf", - "txHash": "0x5039cd928829657841e6ec878b66da59c3ba19708c22fd7198e962e3e82cf0b2", - "kind": "transparent" - }, - { - "address": "0xB2707514aC3b57C0208a1ef0d4d10F3ac7A19670", - "txHash": "0xc15138024e861f233c4ab390162c7e704b9f3273884c5f2c71fd013ad2ac22be", - "kind": "transparent" - }, - { - "address": "0x2897290Fe45F401Abef2C51943F8832CFC4AC233", - "txHash": "0x14578326e71192855fd2e53ffdc4a8c035f3b67692f53edc6ef9022ad6e1483b", - "kind": "transparent" - }, - { - "address": "0xF4cBAb64ead10B22b64bd26742C1c0b8C5dee855", - "txHash": "0xd4928112c19d5e0da9ae631ff6af17b006d1b3cc719f6045662af31b6d806c77", - "kind": "transparent" - }, - { - "address": "0xFD9De8b0D1F6b8b97947d6C73367653fff3BD804", - "txHash": "0xfa4acac1bae14582559b33caed08694eaab4523b5f344155d51c779e3a76d5d1", - "kind": "transparent" - }, - { - "address": "0x2332101CBd8f925A0697f7390594Cbd704A360e7", - "txHash": "0xdc336563b2735f273bb33e1077e192f7c318190b0b11ec42dbb97f24b815046b", - "kind": "transparent" - }, - { - "address": "0x0fC865b80eAb3b9Af1e6343321C7a10382a60d8D", - "txHash": "0x4815eb7ebebb546798da97ce53dc492bebed17197cb0a5f2dc09c198778cd19d", - "kind": "transparent" - }, - { - "address": "0x0130764cd1fb3078b6b19783Cc60D101dEC87730", - "txHash": "0x7035fdddde7d9559e75f49b72ee2f9652caa9db02139c5d9c2d105483549e488", - "kind": "transparent" - }, - { - "address": "0x48C8FaF6c65FAa36320d2F5008f1F0AE55199ca3", - "txHash": "0xdda426c2883d9d7e695265e3f280c641b4cf56f2a6525a8ede9014c34e9c711d", - "kind": "transparent" - }, - { - "address": "0xfA4c928F79D8Ec4c7dc2B9c01c743AB6680a5f74", - "txHash": "0x944a8afc4eb8cb043fd23040b6892e6c84d98b947ece8e09a536864e4f7fd089", - "kind": "transparent" - }, - { - "address": "0x7F1A3ECE4b3Df64BB888936c431B89f12A49EBcB", - "txHash": "0xf41b015445cf3340beb7acb021ca4feea5431c4bcb10d893446ad0d3b0666693", - "kind": "transparent" - }, - { - "address": "0x635A715BdcB3196d7943755d54B66e95305955a5", - "txHash": "0x93cd24c0c1d3819f0fb0849a49323e4debcba757a963e3c5daa2387f6723fde4", - "kind": "transparent" - }, - { - "address": "0xac511d24fCa81E1ec2F3a0c0326Ce0a7fB464dA4", - "txHash": "0xd41c93bf054fc07b64f9d3d57e2ba2cd1fe1ba4feb228bf6f3976dbb2b8a0866", - "kind": "transparent" - }, - { - "address": "0x52610d14f77d67e038D0f167daF14eb024e25d7a", - "txHash": "0x04337cabe7b3fd891cf084d36e9493f0a1fdcfc38e28f00c551f1ff2117b6bf0", - "kind": "transparent" - }, - { - "address": "0xb40e4d0dccA99DD9bB9068d14D0C5Ec873a8f621", - "txHash": "0x466949e1c44abbbec50fee11ef7cc959746fe4bcb96705a2fb2adcc7a8cd17b2", - "kind": "transparent" - }, - { - "address": "0x0e95294fc74DF2E35e3284c92c17d0E9E7778b93", - "txHash": "0xa1df2562ab76ed8f8a9856145e9f5a9638854f29ebe0bdcd6066a62d84b86cbd", - "kind": "transparent" - }, - { - "address": "0x76E770c43568c046C743f5aaFE90979674c42099", - "txHash": "0x376a6f3a07cbd82e0b7c71d5ad610bed42f7d52ec8a6c91c060ab3251d914209", - "kind": "transparent" - }, - { - "address": "0x779334C210460674da43b07e0a8201d2185F9fC7", - "txHash": "0x56792081095453de46d0613f06a9378ba088872ba948e4225d91861b26829f5d", - "kind": "transparent" - }, - { - "address": "0xF422D0314211EDaC942EF3a387C3538C3990f7e2", - "txHash": "0xdfd96e524eed1c24b0f1e082e11ed299273a375d36eebb02475739257342abc4", - "kind": "transparent" - }, - { - "address": "0x67Aa0aA2617aa8e50a1dfb79bE027E7aE2523DCA", - "txHash": "0x26a7b27a17e681ef712a28109353254ffa647d7e4bdd3fac0c37666b8eb2aee9", - "kind": "transparent" - }, - { - "address": "0x7C10AeB54b0AD04f2ED03ACAFd4c762e8512eF48", - "txHash": "0x03c1adb5d9d9e9e4acf9a61d8df5341a606072bcf1e7fe772ae7b15931888066", - "kind": "transparent" - }, - { - "address": "0x169933fc12683cf2A510122fA60BDFb252417723", - "txHash": "0xe6c2015dc56320f4212e62918269def482a03c798c5b472b6b8e5e748ecdb052", - "kind": "transparent" - }, - { - "address": "0x1145f74E990d3da931804967ffAcE08acb70Ee14", - "txHash": "0x16f5d8c9fac60fc57ec63e118d1af49167650adb065e0053486e770f8c271620", - "kind": "transparent" - }, - { - "address": "0xa54879E418327bB1e64a8A4f485F3a496178F57D", - "txHash": "0xedaaf1f14566149fb4516c319bcfa56012973476beefba6a7bdd247adfdbf38f", - "kind": "transparent" - }, - { - "address": "0xf7B384C81Eaa225B105ac57a41f63fcD3F2D9591", - "txHash": "0x46fc7547f6156a218576b2f40bcc0bcdedade03824933e482b0ad4ea147c022e", - "kind": "transparent" - }, - { - "address": "0x57b096BFD7dF3B8D3219F8a17510254D8c2bF2Ec", - "txHash": "0xbfaa715dcecdd2df1aab23bdd228cece7b07f553d10c5b0c55adf0b75da6186c", - "kind": "transparent" - }, - { - "address": "0x936aD5d80F9D786788A8e3C198372BC7291aef86", - "txHash": "0xc981c8bf61297615222fd460030743f2507b51f139583869964527e2f43b5396", - "kind": "transparent" - }, - { - "address": "0xc154623A446dB4198f54918346f7c1a057D5E143", - "txHash": "0x2234474587a0903f91261b0469b62cdd5c61c1fbc4393c5797b3eb8eea35440b", - "kind": "transparent" - }, - { - "address": "0x3Ba48599A4DE0ddd29AFE6e2dc15CEd26538a1ba", - "txHash": "0x683809d459fa7395ca039f5d52633963f58e2c9b512bba017b372629d1d97242", - "kind": "transparent" - }, - { - "address": "0x28eB3E053a5a87522c5E20aFc1f501C96e388a05", - "txHash": "0x618d0e7177fe6b83618ff885df2c21c9b14c6096605e3840703a117ff84c2a40", - "kind": "transparent" - }, - { - "address": "0x082dB62c88B2caa163518D6d18CBB9f8894a61ec", - "txHash": "0x1ebf749581190dbf3630d676eb8919e1e9afaa98acc4ad02602c369459ee37e5", - "kind": "transparent" - }, - { - "address": "0xa8926d70174B5EB771Cb504f8b03eC3A72E3c800", - "txHash": "0x6bbf5a4da133adff9cc0f1bd7728256489a3f2a522540a4c82fd149399ccb6e4", - "kind": "transparent" - }, - { - "address": "0x948e5f595f0C1507Ba57B7062E24e57d5Cbe9997", - "txHash": "0x4d8049a8412b832d281139771f2a4450eb6b00a26d2ca9a80824800d40c52483", - "kind": "transparent" - }, - { - "address": "0xb16cE7519765E75aabf4fF7687dC10b49168fB3f", - "txHash": "0xf1d20de4a3f2edd07ab3ad04f1bf9ab30b5e8bdb318221ad95e6fbda2fc28d26", - "kind": "transparent" - }, - { - "address": "0x8730EDB62e0441fB79B6B5d4F4ACF6E16589a895", - "txHash": "0x32d7ac1b26e8ae6b08ba5e4b04f84a8fb5b811deb87bd7c88685f0e4126e2fa9", - "kind": "transparent" - }, - { - "address": "0x91F650eEC26D1e19546b733C3A058B5129d445FE", - "txHash": "0xa78769c7dfc25d7acc5a46ce012dabcf0f9af90842336d55288cebf18fe82be1", - "kind": "transparent" - }, - { - "address": "0x64c6bF2c256995218cE2DB4b64B7eB247975F3f3", - "txHash": "0x151f6f5356ddc79e037e040c380f191089b4f617099efd228dfa4be7f7f60832", - "kind": "transparent" - }, - { - "address": "0x866E4a9DF5aAB3353b85132F4a942a2138249c9A", - "txHash": "0xfd6d5139238c60cd3634ef29579b73ad476536ad3f6a1f49c2fd5ab2a5d78b5d", - "kind": "transparent" - }, - { - "address": "0x4E4bFd452009374Cfd1F51f926d54adD1a5D6F8B", - "txHash": "0xe1b4f42d37bc383ef6bd99a9572849044e4e3462e416b34735af72b601cd30e0", - "kind": "transparent" - }, - { - "address": "0x0e30591830bDD7d9AcDfc4DFD089260Ff5Aa4aC1", - "txHash": "0x673ff6a10ac33dad46ab1bfb442a3b172e30404c281061e5850c5580a6dd9941", - "kind": "transparent" - }, - { - "address": "0xBAa7eE8C7349dD30D5154518D6B83aE237aB1A82", - "txHash": "0x15f40b059b2504efdcf8e1893bee4df227209b91f1c30799c152a106f496add0", - "kind": "transparent" - }, - { - "address": "0x2E15701dBD264b93514Ca4A66D259Ca771e0dA0d", - "txHash": "0xe13c32f290b7226de9ca6b3a2178fd72b15702a46b4b29a9466e6a389df0a6b2", - "kind": "transparent" - }, - { - "address": "0x234DFCF9C53777D0d978Ac10c8B8C8364cC35922", - "txHash": "0xd1a730d7a3be7d97a13cd135ec5796e66f4cb987c9d3c7a24c8f79384c78c3fb", - "kind": "transparent" - }, - { - "address": "0x484126710951873d76b959536F59004D1E39763f", - "txHash": "0x00efd4b4a7d6173eb0db3ee50ba6b6161c5148a3ed0926ab61d327799bb89447", - "kind": "transparent" - }, - { - "address": "0x9450F16F5803EB8dD9902df700A2ff2E82493C82", - "txHash": "0xf81ebe697fce7527e3e55725bed972c96f777cf74171402a778592738a8e32da", - "kind": "transparent" - }, - { - "address": "0x8d33e8Bf0b4F522d43229298Ae57DAcdD12F7F84", - "txHash": "0x393e5eebbf3dc8fed18e55d60d2c0b6bc8d6125b264724146952b480638025ed", - "kind": "transparent" - }, - { - "address": "0x5A9dfd7cA425d09eca86724A2d5e029F004C0214", - "txHash": "0x5fda4f62b12bea400ebcef0763cf96e0939fb6eb76871f774f731af43d98fb08", - "kind": "transparent" - }, - { - "address": "0xF461DB98971b058Ffa1EeDe60025C602c51B7C95", - "txHash": "0x5c61a07ac507d3097ae82d8f27468758ff7674667c5e1c39a84d8ac5a67306b7", - "kind": "transparent" - }, - { - "address": "0x0bEde36bf90C5Fbe042890F361ddBC5efB1FEaF9", - "txHash": "0x24c8231033d406b88149d189cba8caa372bdc320230eb359ac67af9b5cec9866", - "kind": "transparent" - }, - { - "address": "0x5DC5F89D9bc448066C9Cd1AaA55438d08BeD7650", - "txHash": "0x0a749b1260c083dfb6f77befcc1046a7f482e46c8adf9511a42990efa4c858b1", - "kind": "transparent" - }, - { - "address": "0xE906a0766779809B0946DCB6d144D65E43DB1840", - "txHash": "0xcfc49b9687f07e252e0d8a432511084d57bcbc77b87e0919d6f9bfde0f55929c", - "kind": "transparent" - }, - { - "address": "0x163831836c01DB0ad03904a57186B00b221aa4C2", - "txHash": "0xf9da1f3c534777a7d0c9f28288af88b12b037148dcb23c3e71188a4850dfc059", - "kind": "transparent" - }, - { - "address": "0x60FA17EcB5260AA13EB0e0CFcfb3CDd587F5124B", - "txHash": "0x5963503b5186cb2b03b287dd7e0661c6222d15ff1bf3f27500a6576774276966", - "kind": "transparent" - }, - { - "address": "0xfD1417FB36b46EBCEcD700CB12A17E5EE1854ebd", - "txHash": "0x5a7c1ef0b3579548b066601e3a3d62e5c354ff6fca3be1fb82a1b15812cbc368", - "kind": "transparent" - }, - { - "address": "0xf260935d3Ec44Ae446ca9270aEDdf75c4e626334", - "txHash": "0xfd8cf102d1d7313d42907e99d6ed6042ab9e408d27597564242f6e3e079ec2f5", - "kind": "transparent" - }, - { - "address": "0xD748c50B8869Bc89Bd323585dfdCA50b380B3FC4", - "txHash": "0xe98c6afa2ca79a0f6538e45a607f8f30555b9800d35e993c4f0ad5f4957446c7", - "kind": "transparent" - }, - { - "address": "0xbF8b82C0ed1F490d6DbAaC7202372bFd86613Ec5", - "txHash": "0xd80b5021e0408ceb0894e0a29d732c5c5f73322c368a75c16f61bf7719d79d1b", - "kind": "transparent" - }, - { - "address": "0xd474B23229935d107691f97905E1B616241eb764", - "txHash": "0x8d82c3390a9730c68936431bc1fb73709091ac7c8342c14242716262e95e5c44", - "kind": "transparent" - }, - { - "address": "0xdcc49DF47dB3ED770d76783496bFa494E0dE3c82", - "txHash": "0xd2644076cf492017a8807afb64a87fa064e9bb4c61d35658ed16b92585b85c16", - "kind": "transparent" - }, - { - "address": "0x948A2306635C3A230500EB234387380C2a7A0B58", - "txHash": "0x807715060cb7254281e8637b78000fe316bfe79ad7f3ef6bb4ba0bcb9adae877", - "kind": "transparent" - }, - { - "address": "0xEBE8CF8860284B7e95FC37D9f18867ae987a0e2A", - "txHash": "0x16c7b2e29f0109c8e3698e0437b40abb57f98ac131978b5171791e4b31338e60", - "kind": "transparent" - }, - { - "address": "0x8cC7f1ca37333322ff92b48C4E93F96501591aA8", - "txHash": "0xcaed731cd04bb553f433c8e9e7a5bfb01bc492ce4c28483bb437c6eef3edf146", - "kind": "transparent" - }, - { - "address": "0x9EAcACb3025059E27fdbd76bfAB56d274017e35F", - "txHash": "0xabc4c5f959c9ccdfa20ce28494cfbff6c44894739fbdd0cbb3c70c4fe33a8b4e", - "kind": "transparent" - }, - { - "address": "0x5fD63322F4C660E6f3468b7a623Ded75d49f0090", - "txHash": "0x9f9e584abdb3f28ac99f1d8416805e0b3650e64206390889472334ba5531f9c6", - "kind": "transparent" - }, - { - "address": "0x7bC74FBb3cA6d94C02611b30071CD870A2A2Ffe3", - "txHash": "0x77d94b10facaeaccbcd3e7d435e32ebe8760dffd0e14b38342e009c94adc742c", - "kind": "transparent" - }, - { - "address": "0xc625dd32191E14c729a1468de37D7d4a16d679Ed", - "txHash": "0xe33b9cf8c6808f1124ebb0f0d598400ac4ee349f18554cb312843a8d0e7920c3", - "kind": "transparent" - }, - { - "address": "0x2705317d7F8F633960426F95FC93000C03D2b2De", - "txHash": "0x7ad93de7d1615c6fb98a2a58995c5a13282d4b064049138ef0850fc847adffec", - "kind": "transparent" - }, - { - "address": "0x51c9aEB88A4e4dEDfAee892a3d1C5535d39d87Bc", - "txHash": "0x491dc80ded29aec941cfb4c555f43d38a03c4f376dbef1cfdc9795227fad3b5b", - "kind": "transparent" - }, - { - "address": "0xD585d2e9ED5e7e36fb3917CD0870dBCe327540C6", - "txHash": "0x75d29ab778f1c46ad2a3ee41880af59502506b79b03bce2e755310121535ccfa", - "kind": "transparent" - }, - { - "address": "0x8e8Bf9A1cAE9CB7225b9e1E890De19f9534d8205", - "txHash": "0x69e4291d4b86cee94d0f8706ae4e52603e8e5ddcb76141ac4b536931d23fe681", - "kind": "transparent" - }, - { - "address": "0x4150dB8D65A8636Cf496086D2b786A4aac7D8c70", - "txHash": "0x5afbec50e129a77057c83b6723f5ef8e0b8275e5cc73d51ce2486b28289ba82b", - "kind": "transparent" - }, - { - "address": "0x8bE9BAE99282c43fc5B938a16f2690B27fbe1B79", - "txHash": "0x5891a83707624b87447932557956c34bd83595dc7c980232ba9399b536b055a7", - "kind": "transparent" - }, - { - "address": "0xDcFdb93FFE11CDBDE72dA4A01dA060B87fe50b9C", - "txHash": "0x7b335008e0e239c5657e3d9d3c8ac69f94eb461508995f28ef05258564190ad8", - "kind": "transparent" - }, - { - "address": "0x507bAdE44Bf1317C5e549d1C656dEBB75573A81c", - "txHash": "0xa185f832eadd0e4b26dd788c8524b224daf09f1400e7f3e6d4517c7580c0871f", - "kind": "transparent" - }, - { - "address": "0x9De9D6B726F002902687d9281452C8E1e9fE6670", - "txHash": "0x2edb287458db61aa2842249244dc2eee8d01e289dbfb4ba13636fcfa26adc34d", - "kind": "transparent" - }, - { - "address": "0x0bBD7B3117be63149851167a05D81631f8326Df9", - "txHash": "0xf63cae71c6885734e951de3f6a2476c24e5381cdd3528866f204fda85bf9491b", - "kind": "transparent" - }, - { - "address": "0xB17A136368c27BDAc96F8bdDa8e5C794522f01d7", - "txHash": "0x3466b78b967a39daf67c59136e22966246546ab1a88f2c2f45fec00b0b444b98", - "kind": "transparent" - }, - { - "address": "0x96d2ad5867cd0bbCd68D171D007C84B6C7d58bE4", - "txHash": "0x202ffbe846699cdae0047ada6fde38db7a102c8085a459fe9580b15c1ca0986f", - "kind": "transparent" - }, - { - "address": "0x94acBa2806D7536428ef9F424da8840F02C959de", - "txHash": "0x822aa487f6849c17bbd95318a4c0159af86f29b5db143defc6ab8edc6ba6324c", - "kind": "transparent" - }, - { - "address": "0x38783b83732f872a21EB0D40800DdBFa1F8BBbda", - "txHash": "0x876a73ad69877539a1ece292ded639ca857c4f10c4734d5a5dd1f9da2e3ae1e4", - "kind": "transparent" - }, - { - "address": "0xF64e506b9B55B31357F7aFD9c8c9e1f4152598E9", - "txHash": "0x46c54fd7fa6c5e75003868c436e3290cf0b2cea57279d52e650368f9e3791e94", - "kind": "transparent" - }, - { - "address": "0xa0458024c21a5e6c9E09c98CD1c8D61Fb3D771C3", - "txHash": "0x91e3c2f781b9aa31d9dac7bf8f88675f042f883803031477eec4d0f3f8b3b235", - "kind": "transparent" - }, - { - "address": "0x5575dAAEB472821f79ff6806e2fe9e4BED095Aa9", - "txHash": "0xede7793accaf0a4cb47bbf1c91d569cd741d6d359cda29d49dabab7f01d618a5", - "kind": "transparent" - }, - { - "address": "0x04e4a857BaC7392aB654849379541A008a0446E6", - "txHash": "0x6fe9151f8ddd1428a711b87f297f8a238e3d5b3dfdecba6828fda2ea4c695bba", - "kind": "transparent" - }, - { - "address": "0x7D471e225e0BBe23532cE5A6b2E2c96b6F0D8fB4", - "txHash": "0xb37b96c7b6d39f6a6adacb5822f0f1cd65f4bf09368fe40a9a04c073a336622c", - "kind": "transparent" - }, - { - "address": "0x43B9eabcFc543630ee770fe0EC669933844527d5", - "txHash": "0x37b6dca9c7abc506948a0eed20c43167772192da929dd8bacad9f7f16e07bbc8", - "kind": "transparent" - }, - { - "address": "0x3E6634A39337f588B9964870dB8195Db45255025", - "txHash": "0x68d80b27b062c1adfec2a4ac4521f7668d6c5a66c046f67f55bd8b73568cd5a1", - "kind": "transparent" - }, - { - "address": "0x2f52D6032bc291142D195C6F577e5Ea1D49451ea", - "txHash": "0xb551a72d23ddd7ba2445392823d814e155788af28d35c0edb7f01c1125b3a6bb", - "kind": "transparent" - }, - { - "address": "0xFC3C3a587FDc589025557F29d4A276CE059D3328", - "txHash": "0xadae8235cf9433f34f199b2cfcbb4493017c4878f88535a5df2cf5231e871ce8", - "kind": "transparent" - }, - { - "address": "0x39be1288CE7DE5ec9dF77c450d0CE7f281A3bD00", - "txHash": "0x3f26f10fd20afd50fb1ac959a11ac9882111c6819672bd8401756b000dd19789", - "kind": "transparent" - }, - { - "address": "0x8a2afa7920B7c4901EBeB06b91c409bb37970aeF", - "txHash": "0x2d56141b9eea2bea2aae8ef257636c7b7a7af46814cc48b3ce0d45323c65c95d", - "kind": "transparent" - }, - { - "address": "0x6cC6e493b8ed09Bb1FAd88723Be67288761E972c", - "txHash": "0x818abebe399094c485f04ddf6a2483b176326bf4f379bf0e6127f4670920698b", - "kind": "transparent" - }, - { - "address": "0xdE90403d90d5f164fe3770dccA4B0633cDF9DF3B", - "txHash": "0x663b09c2f2c3342a50040b79c1b03ee601d1626745ca77c52fc3e56cd00e7384", - "kind": "transparent" - }, - { - "address": "0x419FDeAF8abBa959496F77bE8B208904904F95fA", - "txHash": "0xcb0db0c2796de7dbe3dceaf7c54d098378e8234caf5ab8cdb904506e9f7e4b00", - "kind": "transparent" - }, - { - "address": "0x79602495dab7d9222E701cc12fbc7208a47f5994", - "txHash": "0x259aaf66253caf3cb1f21d7e7c5ad3a05b50c9924bfffee479ccd64e59a21631", - "kind": "transparent" - }, - { - "address": "0x317E736BBd5f0130E17c10BE34CcC97e8EA6243a", - "txHash": "0xe7c707989764a54baf5b7096b214cbec070b82659b04c122d487cd4bd42aad68", - "kind": "transparent" - }, - { - "address": "0xb9b2fe7551ed9Fd727Fa139a2f6751fB116E3050", - "txHash": "0xe4705877046cd79f43c3a036a2f719a953c90cab5d74e1874643864082116127", - "kind": "transparent" - }, - { - "address": "0x6e950cef7C295DAC677A4F79Aaf290e047cc7038", - "txHash": "0x02ec472454f083d669be6c90f5b13e06b7826c46a791611b03bea52feff4ee92", - "kind": "transparent" - }, - { - "address": "0x52Eef0F0977f9dc773A532459254283e86A2961a", - "txHash": "0x7b1511851de03eec34360d9722d86859334d5d064a4ccc99cc4c3a36f504cf84", - "kind": "transparent" - }, - { - "address": "0x0aD8b20f1E0BbfEdf9233F4cA5e8E4Bc60394A26", - "txHash": "0x4aac50c80f05a138f48bef4ad19320098f5294c717dd35407b94334a8f49650d", - "kind": "transparent" - }, - { - "address": "0x52d8eD24829A68d3d03d7Dbf5699DADE30961bDc", - "txHash": "0x3a2887c2430a01ed289c31a71010050c9ced29656a20fba45c4e38e60b465e22", - "kind": "transparent" - }, - { - "address": "0x9432a86898a2090cB24CF8dd4fe4f87e510dcBDD", - "txHash": "0x338051ecc65918e31a6d4c25087898d3d0235698caa554846782e0d5e0252855", - "kind": "transparent" - }, - { - "address": "0x1d06AF0Cc951c8b65146571812E2e6e778ccbed0", - "txHash": "0xc1560b000bdd1aed7f79a5e3becd2713240b822902b9ef0e492e1aeb39efd407", - "kind": "transparent" - }, - { - "address": "0x6fac25b9d82DB0B0A6F943247ff5b49d2C7e5423", - "txHash": "0x1658bf41ea3c42e2562dbea9b64f3b87d4b0558aecb766e4b8aec1619b52bf79", - "kind": "transparent" - }, - { - "address": "0x118E0f497DA0f2316be73bb7F9ebfB563ddC8Ff8", - "txHash": "0xa4bd6a0fcab808bddbfb0fae83d60f815334576dbd4742c61a21f9de785a2093", - "kind": "transparent" - }, - { - "address": "0x9EC92C44861f6cB233D600A0a70B1E8Cb9d239D0", - "txHash": "0x17fc1a346191a59aba5b23fd87230227d8d7c516e3fe81acbb6ad7571fb1aa12", - "kind": "transparent" - }, - { - "address": "0xF68Ca5faa907dDEB380a5B3962AA17F6B8350571", - "txHash": "0x1dd7037ea592673ee987d2b465e3b09e3468b195cf88627ce3bbc3b734525d95", - "kind": "transparent" - }, - { - "address": "0x8Fe915939B4dB9D275b8d94537E9529cA8ad71d2", - "txHash": "0x7e6582e7c5aca2148106753e60ec1db65741217816b860c00fe6b0b5366c45a2", - "kind": "transparent" - }, - { - "address": "0x32C441f4f235A007987420BE580BF76839aC752a", - "txHash": "0x6d0a6c6697a37bfb980961592555d89d574c1ce2d523c49af79ad076af2254e6", - "kind": "transparent" - }, - { - "address": "0x9B0D2BA6030a4C6059d6Cc220D6B766A02956589", - "txHash": "0x0897a2695b77121a5b28083d44811cf76e25e5e5e191d3ac154b8e07efb09190", - "kind": "transparent" - }, - { - "address": "0xDb5eEC6925AcE46463A39652A59Ff0a9fa837D1E", - "txHash": "0x05b9985a800318b2926d5ed16019afa4e0b0db8af2aada58315c5124485a5c6f", - "kind": "transparent" - }, - { - "address": "0xFe4BE6d2F3D81E9e1E4ff23607980A690f6cF5D4", - "txHash": "0x23165296327c412a4205be58db576fe813f1d3547672f370e66fae73f29b8f0c", - "kind": "transparent" - }, - { - "address": "0xbA13e3E82f349ed390BA83c9eA631aAbA3C53D07", - "txHash": "0xcd8a848704bb9f501d29b4ba70712d7ad56ba94c5f0d7a8d424ca3b2b3232c85", - "kind": "transparent" - }, - { - "address": "0x2b28ACA2147D19cbfc8c6541Bf159dFB94bE4323", - "txHash": "0xaf4a775e5f791dc71fef22ab66ce5d77400590c12c8c5b2430e10b772afd0992", - "kind": "transparent" - }, - { - "address": "0x4076Aaf7BB98Ec650F087451453cE103890c4451", - "txHash": "0x72b805fd5098e6812b45edf089031e78b4245413e745b7138d4b0a49e58485d8", - "kind": "transparent" - }, - { - "address": "0xB10908034f33F558C57b7aCE1538c0BaAEE92A97", - "txHash": "0x33e02a6e76b3572141e78eb4665f6bbcfa76c44de612f0199078ef7d738d40a1", - "kind": "transparent" - }, - { - "address": "0xdD8eD6618ee433e75cEb1F74B4230cb954708367", - "txHash": "0x5abbe05ef01cd2dd4cfa77c6406ba97a9070d14c67a674701bd00ea7a6deb076", - "kind": "transparent" - }, - { - "address": "0x72f30fF7906EfF9f6460A4a28a635B2EaA11Ab25", - "txHash": "0xc65a77e6d41ea50461e2b901a67c40d133749b817bc56ece585c1caafd0cb290", - "kind": "transparent" - }, - { - "address": "0x88C8c7C396F91e73746dDCbF3Da50a09936AD599", - "txHash": "0x42aa583f83f177597517eb464db3760041a2eac2b0e6707001a3435bde5e3d4c", - "kind": "transparent" - }, - { - "address": "0x15DdA27599792df887c3aff9bb54EF472A003adD", - "txHash": "0x2cd2a3e92c765d99e19061d532af78bba5bda9f10cfba6131808c01d7e22bbd7", - "kind": "transparent" - }, - { - "address": "0x20964C311a9722eDA4CAaa6AfeC8103D8E39B15d", - "txHash": "0xe62ac5641447d56f10555534feecb277d3d600ceaa2e0e0aa20916de69a0cc6d", - "kind": "transparent" - }, - { - "address": "0x733965a3A6483328acd9cfEdA83fd9957F97d33B", - "txHash": "0xecbb87c2c397c1998d4ae15cb1f8f6f0c80046a8de0a10e68052ae830f612ee8", - "kind": "transparent" - }, - { - "address": "0xaCa00a503dB3aC59638018D7CB7beeeB707f473e", - "txHash": "0x162070987f6111935413277bd176e2330882ff6db66edf9cf50557e858d45d40", - "kind": "transparent" - }, - { - "address": "0x876a5f6F451134FEb2290797cfd049D8CA1b134a", - "txHash": "0x275c0a9a6ee2e2a2b7f5d0c375578eba89e24b68b055468c9f4cecdb18533e01", - "kind": "transparent" - }, - { - "address": "0x9Ad161910414246364A49e0F02CEE7479354fD18", - "txHash": "0x4b0924e418bbd2011dca66aa8657ee874f290b771acf4c34ed74e14f5ea3cec9", - "kind": "transparent" - }, - { - "address": "0x67eC875F884a0A115199393d8C438353aF2D153f", - "txHash": "0xdf7bd65d660239872ab2d4bce208f918ceb6f4b34f0558d66613c1c04fd0da36", - "kind": "transparent" - }, - { - "address": "0x87cff4d135e803E91a2B172CDeC434409A33B251", - "txHash": "0xd90190546731f1cadad5677d90ea5acbf6525c21082c5ec10f38d02c9430306c", - "kind": "transparent" - }, - { - "address": "0x1615Da06553c2292Da29076E8Caa0f5e6602b9EF", - "txHash": "0xb83675498248300243f71c81978a0f02e070d9dc991d39603b0ed3ec5de5be9c", - "kind": "transparent" - }, - { - "address": "0x0778AdD21c731187282Ad102110a3774F1c5182d", - "txHash": "0xad981cc19a946404988fcd094d976fae5fca42bbbc206b3c4fa449b59dbe760a", - "kind": "transparent" - }, - { - "address": "0x64d582Bd408b44513E2F1383Cc82A648A3cBA175", - "txHash": "0x4eb190632e5df2cc881f8618b93ccb5a132f0d11897bc1a857d571e1f32096b1", - "kind": "transparent" - }, - { - "address": "0x65b3A4c0993613b25744Cb7a7c28b03EDFf31910", - "txHash": "0x3990f28f0d7dd7a6d04d3eff92ba0e27986a431d4c7b742c193a44f739f1fa7f", - "kind": "transparent" - }, - { - "address": "0xe90c39F0c59c42fDbd12933FE05d3d050dc32aAf", - "txHash": "0x9a36183b1680cf9b78f2378730088e15c37d4047622c4f787045cdab9db54ad8", - "kind": "transparent" - }, - { - "address": "0x8929c5707F5C584689A4483115BeBB0974987670", - "txHash": "0xb5804c89b931efffbb88ab27e53ef2916a94740a5a941c32456f7c2b65be4e00", - "kind": "transparent" - }, - { - "address": "0xb1e1EbF0C836C62D71A59E8c2819BABbEd5B565F", - "txHash": "0xa4266a63950bc5dda902f8532f9ddad86ac8ad1163f6e392712fc1a849acc464", - "kind": "transparent" - }, - { - "address": "0x486fE0A735e5CC9827CEa41d437ba956b74dfd9E", - "txHash": "0xbfd514497e5e3ed8ec4352512e8ba6abdb4805b8bb49129049deb05f9b4cdf57", - "kind": "transparent" - }, - { - "address": "0x0D3A14A1AbccF90291617DA196801D94e696ea7a", - "txHash": "0xe44435131c4ad15defa8d2b9bdad77e540d1da44498e582bfdc8cd2d7b54a2ac", - "kind": "transparent" - }, - { - "address": "0x6F5dEF332c5e37Ce949b15BD8947D673d815E93F", - "txHash": "0xc997767df3193f6e33d567714754997308a65505e9936cbaaed39e53b17ba251", - "kind": "transparent" - }, - { - "address": "0x5620fd6650d908B75756590Ce72ADA08616da47e", - "txHash": "0x1dbdef17dc8f460a2292ae74523c99ac02fdf31c761ec22cd660cb392eaadc7a", - "kind": "transparent" - }, - { - "address": "0x9C2E2B8493B018130d94AC532F3E6dC481044B31", - "txHash": "0xe1b8ba9fdbf7ac4e16bd04b9785f2bd092c28bc00bd49ef4781db806f6053740", - "kind": "transparent" - }, - { - "address": "0x5d95179a0252C40dF9d71cF2ac9C1D06F5201Db2", - "txHash": "0xe2f1f24d3a4733b9f0eb28b018347ccb4e18a9141c9323797bab5a6ba650b3a2", - "kind": "transparent" - }, - { - "address": "0x9aD08b1c0d66476754dfFA3Efd83fd8F6eA09900", - "txHash": "0x934a80bf9e69171bced4d5f5521c85092cb4424f2af91cbc16ce5ad31745e380", - "kind": "transparent" - }, - { - "address": "0x197cdEB0651717c3d61605db98bB994F71f7c632", - "txHash": "0x72de3b1f6bf51a2482587251317a8d1599d8ee2905bd069ee3b102fac1ca2158", - "kind": "transparent" - }, - { - "address": "0x32c94Fbd9B1D395B148d86a228014251707E27c2", - "txHash": "0x40d2f2b749506c546a2e3ee8dddd1b0ab74079168880f25d6738c817e4e05bde", - "kind": "transparent" - }, - { - "address": "0xbfc15fB8D8D38B3f6c813215625F21501c358BCa", - "txHash": "0xb513179a40807ebea2002e04653df56cb4e23c1e30dbd7b99a2473af4e7336da", - "kind": "transparent" - }, - { - "address": "0xA55377c3a422E8837bb24b50934bA7C987c3448a", - "txHash": "0x4e33e4b708d521b5730c0b554a89eff020c3d14492817fd7ca4e3aef682235fb", - "kind": "transparent" - }, - { - "address": "0x4322b147Ed94Fd079Bd6767e5f8596CD49cC4f7e", - "txHash": "0x95cb593902926bb616e4f1ee898340784199b3ba72801e9aa9fff77cabdb7b97", - "kind": "transparent" - }, - { - "address": "0x0260Bc0411a6f0A9f915D1f2C6B713A7E9D7f441", - "txHash": "0xc8c0853a59ee43c248b764b2567d58ff71a498b8a68a3fd086a7bd552fb15d29", - "kind": "transparent" - }, - { - "address": "0x10570D9f08Fe397E8a8E3ECF6216a52fc1cB0b8e", - "txHash": "0x95cc4b7f3909ab4a1bb5c4056d0617589456c4c4deeafa985c2ea332139cdc6f", - "kind": "transparent" - }, - { - "address": "0xF4Ae4c9103265bcb4549483973F7f625E873E52c", - "txHash": "0xe59be643228972a69729f763e448f74fe2aac670bf66ab0032373794343430ec", - "kind": "transparent" - }, - { - "address": "0xF6E056CDc7397848d7bB01592E2AB121D002906d", - "txHash": "0x6bf6c2b5810581ff3da8c531bebf7a940e0da76ec242c4ca9b85fb740737b2b5", - "kind": "transparent" - }, - { - "address": "0x9DcE45570fF7C1291336257e3Bca4563ea7775D0", - "txHash": "0xfcb1a3d4cbeabeb82f86dcb2fa6250b4cc1c0a0bf179bb31fd0f720f225932e6", - "kind": "transparent" - }, - { - "address": "0x0a4C51E451CA745030e676b3691e6400aA3808f0", - "txHash": "0x2e57123b53374526aa68326132e9040f28f3025e9dc132c452c5bbbbd02132ba", - "kind": "transparent" - }, - { - "address": "0xCfD898BefF8f4b035911bE527dCa3a15ac561177", - "txHash": "0xc8175613f64a882f194441dd7bf01897d7be6ec1a7f9e5193a3c916587b8cde9", - "kind": "transparent" - }, - { - "address": "0x706Cb63FdbD3850ED9b8fE9de19608B05F0f74C0", - "txHash": "0x0f3c8adab656271e0da7438bb353306a91faf9e2d596ee33aba3094efbeca07f", - "kind": "transparent" - }, - { - "address": "0x36493a8Be960743aE2cb9386b237eC53D95Fe084", - "txHash": "0xf95f3414e4e0175b31ef6a7979a5b0aea23a0faa905c9d4963409a027c4ec983", - "kind": "transparent" - }, - { - "address": "0x15adA646E0F0BD1233bcE51024F2580c67EEf57f", - "txHash": "0x135623e7f37162771007ea5f2b1f29da74bc0d53c75e09b034711e06029ad692", - "kind": "transparent" - }, - { - "address": "0x2EBb070E6A32FDE09A8557C18Fc41D5F7466f944", - "txHash": "0x24325c9b08048561cb63decbdf2677b072dc8200ff7670fc4171b9b14f608c2a", - "kind": "transparent" - }, - { - "address": "0x2e2a0CcE0724737f0709b600B571054061aA3c86", - "txHash": "0x6a5e8c98d78e47376cb39409dfe4f28e0116ef986eb33799c4900fee6d107a95", - "kind": "transparent" - }, - { - "address": "0xa83D7a33F309EBB058cB4DA917A57B3581527353", - "txHash": "0x19a9a4fcb0743b654368e0947d3fb054cf38bc28ef13776743d97b8a10325176", - "kind": "transparent" - }, - { - "address": "0x5A83E3b68362D1e4FfD56D2CA80A72266E6a3947", - "txHash": "0xa2e0657fee0d2fd8051d317f46f032717f5b33a60c280498f3c1169c166e1c89", - "kind": "transparent" - }, - { - "address": "0x101900F3504Af2491e0197933639c406dAB6E024", - "txHash": "0x8b7b3db32b0e8ac7c2027b159c441f9a9f3103ef97425704d8458a0783fabadd", - "kind": "transparent" - }, - { - "address": "0xC4EFf53cfDB597716A008572fFDb64a169a37aB1", - "txHash": "0x3d87691e27dc07a615825fa192742d443188fa65ccf42c107fd4c75f177d7d38", - "kind": "transparent" - }, - { - "address": "0x0e0877c93586D8912203c444614aA533c4B1A5Ae", - "txHash": "0xa5719725796314650b44c319596a8de4c097a02f40e53162b8c5c4e0809bba66", - "kind": "transparent" - }, - { - "address": "0x94FE4590d817C383C6730bb42a0591055a34f11b", - "txHash": "0x79e11e7ae3967d3cf4e5f0b20784b14a4da82bef89191f2cc731646f766d0aa5", - "kind": "transparent" - }, - { - "address": "0xa5f018754dD2ad7aC68a45a2DD3144C0B585A800", - "txHash": "0x21a0e09a9b767c5814c6487995446c8bf1c89bb0103cf958d8f70443b30f39cd", - "kind": "transparent" - }, - { - "address": "0x01FC36d29Fe3A863B375C368622d46b701CC413b", - "txHash": "0xdfa441e6ad5e1fdb00334738d759adaae5e41f775b074f9413e8f4423b86aa97", - "kind": "transparent" - }, - { - "address": "0xc8d6269821093A21fa85375A997909cA9575Ed10", - "txHash": "0x8dbe8a3f357beacb25ef9481ebf043ad4bed895e16089ae6a7e163260deab9bd", - "kind": "transparent" - }, - { - "address": "0xb3E4d8A9541121fcbd80408C2b35EF8740634Cb1", - "txHash": "0xe8ad836b230850c58f6e04d347aea786461ffb97c86387ea93dd720f6e2fa3a0", - "kind": "transparent" - }, - { - "address": "0x6dcfb5eA96258261205d56F6d939B7334898614c", - "txHash": "0xe1480982ec5ac5bb66fd4e23bc3c2c808440f4e7861f0f8444e1b7476a080d80", - "kind": "transparent" - }, - { - "address": "0x40b3aB664CE556c2d8fBbec246C3b6759903acD2", - "txHash": "0x13b133a8bbc83de89db37d81ebb10e3f79d704635dadfe184a2e5bed7e34b7e7", - "kind": "transparent" - }, - { - "address": "0x934354E822d5540C78794d71b7B66fEbd6A1E351", - "txHash": "0x3a1e6314e75defda6ade48fcd3b8661d9738f309396a857e0aab1c8f175c480d", - "kind": "transparent" - }, - { - "address": "0xe63C1EfcfD0FE311E6Fe427D97111E39125b1D1a", - "txHash": "0x87e52eb8b72620c330faa94ca3d278e1e0448787349fa783f09273a08691e1b3", - "kind": "transparent" - }, - { - "address": "0x2d5804C5865C435A4001eD6043cF712728c584b1", - "txHash": "0xc7cd75418a750823fc2bdae3d272262e508c5dd3c2659e5e5272b4a663dabc0e", - "kind": "transparent" - }, - { - "address": "0x233e1A9844F0e85d497f65F299c45D5C658659bE", - "txHash": "0x767c3ca4962a98188bba4d856f9ddc53cebe29e47ee8bd8850744bf3844001fc", - "kind": "transparent" - }, - { - "address": "0xC53208728AB12B8aF80ED2Bd1eECA5D979478022", - "txHash": "0x80329e8ce736cd6d48ac5b26e2e5870bdd25cf9538e7e9f9eb07443edac8270a", - "kind": "transparent" - }, - { - "address": "0x9C56032808333e4CCC0c9587fDAb29Cb8A9Aa400", - "txHash": "0x15a3337871ec49f02757531b300b36b55932b58d56c27b7f7c7ba952952d9cdf", - "kind": "transparent" - }, - { - "address": "0x1f678eB25b3f576b9e1448E4dd6695E01a8b0927", - "txHash": "0x9704ddaec1258b83ab095be2a0cdb394e2e99a74d6001b00ad73383a21ce931a", - "kind": "transparent" - }, - { - "address": "0xd03498627A76e97878ad3E20748cF97A968657bf", - "txHash": "0x7f1ea9f32f189194ee94a4e9b1dd56d79858dc6b52ea72239d172c03b9e65adb", - "kind": "transparent" - }, - { - "address": "0x4F5C4f5ddAfd0e9f11eCee915590Db2Bfe88F111", - "txHash": "0xe81a599a9fd9e3a552aed9c2f505b7657c2d7a51871198ae2ed642275c22ca4d", - "kind": "transparent" - }, - { - "address": "0xdBffFDf5098595a3E9BF3FEEa3fCfa3b5cCc464d", - "txHash": "0x3aecf6913d0729649905efc75ca606cc5163fab70a056aa50709bcf29eb90332", - "kind": "transparent" - }, - { - "address": "0x730DEE75Ff753435b6b0AfCf5591aa423436F291", - "txHash": "0x94cfc09aafe1daa7009ef0eac6c7b7550901bdac3cd0a1ace94c7ee3f5717348", - "kind": "transparent" - }, - { - "address": "0xB3D02a924E5F639B40AFdD2acaD650E9bCEd7c81", - "txHash": "0x1c9cd21ce3472fc8488509fbc6d9f613c2834c6cba883045822effdf735e6abf", - "kind": "transparent" - }, - { - "address": "0xfd045BE06B2f842050D92C87C7A74e2E9d18C2C5", - "txHash": "0x55059f5393cc0f34abbbd07e70f7908b521e26b8c12d768f641d354f09008ea0", - "kind": "transparent" - }, - { - "address": "0x6e24cFD8F69a11ABd44b48132f32b549ABd6fcB4", - "txHash": "0x13d596ca3848807afc3a2eb0e13c0b6f962b2f5fc7f798a3dc26db99d015c289", - "kind": "transparent" - }, - { - "address": "0xB96cfbfAf35Ba7Ab60fe614dde84d1F4Efc06cd9", - "txHash": "0xa8a27d537de3d0ad0731a8043394951e84c7cd02d34439aeb7a15abb277e68fc", - "kind": "transparent" - }, - { - "address": "0x2f6fCe92773DA3cfC880FB13D730901A10E61709", - "txHash": "0x33f36b64052ce77130e11d0aca24e5d3afafd2a894b2df61228ec22337f656f2", - "kind": "transparent" - }, - { - "address": "0xEbAe6EaA2C2f2804667e0d65BB0916C44B132626", - "txHash": "0xe956c923c4cd9c6ab5d7269ffc260c960109699242b59dddaec5f7314eaae566", - "kind": "transparent" - }, - { - "address": "0x5FAbc850053016a7edC193C4635b7118054fB764", - "txHash": "0x13c7acc6ce45e157f20b63d84808150b25ba3d18b227b82f8c8425b8e8d37a8a", - "kind": "transparent" - }, - { - "address": "0x415cF58382646994f0e54EB5d558e432c9B7eb3d", - "txHash": "0x42f08bf4cea5200ce1bf580cc4f654938ae3db8995638cf0aa4c6ffd3145ad36", - "kind": "transparent" - }, - { - "address": "0x73BaE4EC7a9f3DeE65392374944eEDAd00b1Af0f", - "txHash": "0x96df1c006498f08bc9747de9709d1bfcbc0225fa3ed00a46b0022f34209bf842", - "kind": "transparent" - }, - { - "address": "0x65C2008C3270Ec7D0c59a1cE80ab8e35a7eECcBd", - "txHash": "0xabb46d927c18aa96ad603b71c89a5ce5bb9d53fc7c87b2150afc2ee8ca10bbdb", - "kind": "transparent" - }, - { - "address": "0x98B658Eaf5Ddc31c2f252BEbaFA1632CE93608a4", - "txHash": "0x26fb10436f6189093d1a60eaa8c5968254c87520af97b608e50e507df203d502", - "kind": "transparent" - }, - { - "address": "0x1f3ba4EF841b23C7E2F449c5806656e6732196c9", - "txHash": "0x982540087bb6df7cf45704226d80979ccedd3f9d9c088d537c23defb5000fb41", - "kind": "transparent" - }, - { - "address": "0x1b78D9DB995Fd4BdA932524fa4AD9Ea3DdbA25B2", - "txHash": "0xbafe5f0ca056ef1276d0720eeefc3c25bbb1888548e2f76432cfb0cad49535ad", - "kind": "transparent" - }, - { - "address": "0x06aE30E68Aa6FF6B2ea69FD7ADbd00e99B4CbC45", - "txHash": "0xb12c08278880e0b03d513cc08d8b809083d3b490106413f68a5208ec3866b529", - "kind": "transparent" - }, - { - "address": "0x66301042f49E29755B8C036bCd24548c3B276297", - "txHash": "0xfc2a54561aae13e0c39c985bc8d58ef8ff5f9622b0fb87c82dd6fedf04e22125", - "kind": "transparent" - }, - { - "address": "0x0121562D6d7804342c0e25fEA4c6E7C6C4b97EbB", - "txHash": "0x644bafd97219fb7e9bc6a58b77278a70788e2ec1b88bb50af8fbe0edbc56f8ab", - "kind": "transparent" - }, - { - "address": "0x19C40c63F0d93c1be85C183bb58E9063BD4c6F0E", - "txHash": "0x2e21197ccc02e96a379459784df3b503990444ce790c2348d1ae5735633c8c5a", - "kind": "transparent" - }, - { - "address": "0x68D812dbd64101B3A2D7eA8Bf0EA4dB168ae5373", - "txHash": "0xd8c046c67897d236ce6ef383e5b1303b31d9cf7e4ea9590765d07b1b40aef2f4", - "kind": "transparent" - }, - { - "address": "0x6443880c8d3CFbd97b205b323220a76935d789Ea", - "txHash": "0x9c650cec224014cfc45697e9babf93c67009b10abfc0899a5c0a868c9fb98022", - "kind": "transparent" - }, - { - "address": "0x048Dc51581Ad0CC1E81F77D21819a772304ece3f", - "txHash": "0xf467c9f02d9b0180fb12cd271f5a1d878b68c9f312aa115fbe601c7428dda4af", - "kind": "transparent" - }, - { - "address": "0xFeBd3220A04596Edc6defc8532d6e081013896F7", - "txHash": "0x1a9b411990ae613692b0811e40f2cd6feaa8f946fdd870a5368f0426d2415dd9", - "kind": "transparent" - }, - { - "address": "0xA3c42768a8D64ad0C11ae3Fb07A885B32308922F", - "txHash": "0x416877dbe2b35f9bc9ddbe4795f4f38dfd2d4701323b8568e41c99bfab4c62eb", - "kind": "transparent" - }, - { - "address": "0xFCf480E4364f935BcA013de7fB151fB3F9E04a86", - "txHash": "0xd4327af6a5559a96ee3f8200613f801e547f6f7f1ec57c1541cd263591583085", - "kind": "transparent" - }, - { - "address": "0x2bF5fD604cb5EF37809774Cdf2Ed4C9f07cc5F9E", - "txHash": "0x9b914877c9072c3116cc6ab55b81730cba67738a3121fedc9fb25566e4290882", - "kind": "transparent" - }, - { - "address": "0xB3D437D41C72F5D95E435bA3a4595A7e15f0Bad5", - "txHash": "0x5ccefd8462865e17d9d5a04a5a93ba9a24081f30b5acc829e66086a9dc7b7f15", - "kind": "transparent" - }, - { - "address": "0xB2efd0Ce6Ce4DEAaD49b50568985052a4c60D636", - "txHash": "0x4a17076de69edc4d2dbd6f497e787897b984cfc7de114ed24c34d4d524745410", - "kind": "transparent" - }, - { - "address": "0xdfbac509297Ddba140138980B6144021a07bef91", - "txHash": "0x1efbb5cc9745a8cd6efc9b81897924e80a36516a781dadb2ee22216f4c30be8c", - "kind": "transparent" - }, - { - "address": "0xc7a502d97A3b8A93fE44386D3392B3784dCd7935", - "txHash": "0x4067b44fcf5fe6aeeeafe40f0f6e538deca8878f7848fc583e65fd931c7a687e", - "kind": "transparent" - }, - { - "address": "0x8F7A1De20DF4F162b78395E7ca6A20E8D34776d0", - "txHash": "0x5b7643a9a30e9feffe98c0b40913d16bade3a3614726774f701ee0f73135bb58", - "kind": "transparent" - }, - { - "address": "0x2f4F6613795Cd633c05617d23C83A50C2F74c803", - "txHash": "0x14f1673eae7f684e36eef3a5b45e374137737544f2c08ff233f29fbd00b8d787", - "kind": "transparent" - }, - { - "address": "0x60019b3c743E7a1d50097facaBAB8D072Dfe8Dc2", - "txHash": "0x8a9e58804f94f958e0178371d7dda328de806241c29dff57ae44bc6a87670ae8", - "kind": "transparent" - }, - { - "address": "0x8c799b6A998152acD6Db13218A26FB31858fcBD0", - "txHash": "0x7f4132348a2031ae3d9a13aec4e5a2711f547e3f8a32070deba17cc86a430688", - "kind": "transparent" - }, - { - "address": "0xb9376c2b861bdd0b5a93Ab5AC90ea361E7298Eb1", - "txHash": "0xb9f2baf374d1dee94349381c8acf6ceab7ae02d631e904f5aba51b456b5b49a5", - "kind": "transparent" - }, - { - "address": "0xcb1029F87fDd273e142e9962E2e63eee6743C4D8", - "txHash": "0xc13f88afd9876ee09db3a26a39b3eae51d942a7bb829a237fe297b9802f99720", - "kind": "transparent" - }, - { - "address": "0x9e43aBACbCCdE4cB5347d3e4E0f3Dd60e9c3b593", - "txHash": "0x29e76a1cc1015d06717d973690b8d8d6b4f5b7861d19fa3e880146e233d1ac8a", - "kind": "transparent" - }, - { - "address": "0x3684a78fB2CdB52f84397349C3A3E02a96486746", - "txHash": "0x56f37ecb99914cb406c8f7dd7cf4912f809b04427a7f417f3623dde2c1009cf4", - "kind": "transparent" - }, - { - "address": "0x1bDdD9A9A9ea76d542ed513F667f075B7480A029", - "txHash": "0xd83870fc1ef2e75690d97c193265c1c22cc823b7c3899523df47b8771b6548a9", - "kind": "transparent" - }, - { - "address": "0xc866188E0Dac37D421A2808bF40D1738566625a0", - "txHash": "0xd422cce8bd9705d35f7164867c4aec20cab7fbba88324b3073a46ab6cb10e23d", - "kind": "transparent" - }, - { - "address": "0x3Aa2EBB2c805A2C678ebd272e52031Da49522EbE", - "txHash": "0x68500ce63320f32e23c0abc7dc90555f7c80322e9f900c6283bcf16c0bb96965", - "kind": "transparent" - }, - { - "address": "0xaBfD26db177dB205556A13f1Cf1c753eb588891d", - "txHash": "0x8733019cabcfa83a36eeff8c0ed591145d07eda0b668ea53740c34e2b01930e0", - "kind": "transparent" - }, - { - "address": "0x2D0ae11d982063c313a760d20c5B38aD828726F6", - "txHash": "0x2dca48272f4c766856be0bbb535045ed979da8f47c778488705abac421ab154d", - "kind": "transparent" - }, - { - "address": "0x15C62A087B706E4Cf9eaCa8AF5cbBFeED30373F4", - "txHash": "0xb5fb899167c83bc6da03e3895617a132da759c38e996c458d751338ee5ac545f", - "kind": "transparent" - }, - { - "address": "0xC508e9F20f15874df5B56352E88D094c15d46C14", - "txHash": "0x1832176b916d44e7b9fdaa6dd0ea37ff52f42c5945e6f8231efd276274ae1601", - "kind": "transparent" - }, - { - "address": "0xe7D99053bc5e1724cFbF7bCae937D0F9667D18Bf", - "txHash": "0x7582e7fccf3bc486274940d54e9aeefc3d8a182ac6f5ad67d0c543fcd3581aa1", - "kind": "transparent" - }, - { - "address": "0x128f1E04b6c02e489bB1c6f39bA244d17AdEe551", - "txHash": "0xfd2148814dd96bd7a694b06be399132bb711240482f2bbc38a21230526a5e14b", - "kind": "transparent" - }, - { - "address": "0x686A964bCbB08F19E1ED9912E60E2f976b383cc5", - "txHash": "0xbbcbde4e8b667608f144b3dca1bdb59455970f93e0d8b81c3b5affb03bb78f66", - "kind": "transparent" - }, - { - "address": "0xa8b21ae36000bcB9e16Dc35c67957d121550423b", - "txHash": "0x36e8e2d1b660236a53a28c4673983ca47c2a06036f4a09992c92e150f52b23d8", - "kind": "transparent" - }, - { - "address": "0xE11D4fFc3BF128556ab95da50e4849BE523c56E7", - "txHash": "0x93793747db8ed173e8de83f8bb93bf4f13f29476caf193465d7ffe1960a5affc", - "kind": "transparent" - }, - { - "address": "0x1168AB8B7fC476D6bd8a9DfcaD69b18EB0AF83D6", - "txHash": "0xa8eaf6d3068ba0418b1c3d1fe539a2665ea627fbfb1422a6a1f16774248fc629", - "kind": "transparent" - }, - { - "address": "0x04600Bd0A57719dbAF78949121FBB108BD53D5b5", - "txHash": "0xc9bca562819ccbfbbac0cac9050dfe82034b584b0959fee4e7b653abd725176b", - "kind": "transparent" - }, - { - "address": "0xd78476274fdc3E91aBbd49a38F76d493d28DAd6b", - "txHash": "0xa17ee82e1c143a6e0be8d33a047a67cf4438e072061c375b97ad429bef75c4d7", - "kind": "transparent" - }, - { - "address": "0x1010dc23aA79B2e975D92D1973409093cd0578A1", - "txHash": "0x8ec929d9724cc1892b2ea8fed4b7c149979e487c54dfd0063d7ee86512244d2e", - "kind": "transparent" - }, - { - "address": "0x026c9AdD1CA3d94280F67ac6aEe3224813753FFC", - "txHash": "0x07ab1f71e5b3093c07a8cfb01b3aaa3140296ae8c4bb9adc99e7e077469f7d4d", - "kind": "transparent" - }, - { - "address": "0x7d9379fA404636F3bCDc26B7D7A9a6eF4532F9A3", - "txHash": "0xe1920dcb820678b8186aaffc3b3722c963cace074f6dee5b29df0d230d5cd5f7", - "kind": "transparent" - }, - { - "address": "0xA60E311B16C03943e967ff3d01e523B5A4786b6f", - "txHash": "0x1e257e023733797c816d278665ebbe08df088e8123d91966cb6cc5144bce6584", - "kind": "transparent" - }, - { - "address": "0x448e815b5cfa2f464E8AC4226922EFbf69c937Bb", - "txHash": "0x8a8d39659d596f33b21b9089994b8d81c2e7a01947690c9d6e9fb9fab4b03a99", - "kind": "transparent" - }, - { - "address": "0xe08f73567d5431459E3490381e8e9f4AF91fe65f", - "txHash": "0x88114f24a5e282f5cbe6ee725210464ba47d782fb2b7efc14fa3f0a8a162dc0a", - "kind": "transparent" - }, - { - "address": "0xb957b4a3Ed2eeBc71Bd25a45F4c671ADe4F88418", - "txHash": "0x4568bc32b8328eae0bcf83eb5f7bdb5aa12d9a7eea120768e1baa5856f3b9aa4", - "kind": "transparent" - }, - { - "address": "0xA5FBAb28398Fe23E713F6B30dC432D2174574901", - "txHash": "0xdd43c6eeafd2b2f720e6687d8d00ac75956fff9d937d14023cc6d61869347f81", - "kind": "transparent" - }, - { - "address": "0x0A52243255C8d3b4ACd2227dbAa7fABFFEF4E503", - "txHash": "0x17c3fc3a43be453981a290f7a43a4bf0885871ebc11d6179ecf732f17ac5a11c", - "kind": "transparent" - }, - { - "address": "0xc8cf0371eAB9341841038697A439E4BEf5E192F7", - "txHash": "0xd46419014fb8e48447f589f1191dfff250c6667c3960f839a976926ae402a7cf", - "kind": "transparent" - }, - { - "address": "0x60dC23898a309852B6B4BCFe89344a38FC7C4557", - "txHash": "0x576443e9e2da85ed881a2c4709eb7f7cb6a60655330e9571a2a96eaec8bd6172", - "kind": "transparent" - }, - { - "address": "0xF71Bb4717B6df35e7D11D04585C9F1638F357FB5", - "txHash": "0x4b9d5a1ca1bda10511bc835bcc36d56e2146055650fbc4dd9a9437692e4a4558", - "kind": "transparent" - }, - { - "address": "0xBE88c76ac251d2435D729CD0b6c883940399361E", - "txHash": "0xb5584fb4bffd40f027a633d6fdb3c2a74919b83d737ca6df4b5f478f36721b71", - "kind": "transparent" - }, - { - "address": "0xF66da372F507A2B85Bba2a239b386d06Db6e6526", - "txHash": "0x2fd5a9d3dbf408e257472f51600a1d630b454cc0330a0314ea73894562a96f40", - "kind": "transparent" - }, - { - "address": "0x3265458749421bc8d840C816E02AFc1F11c7564B", - "txHash": "0x53849f3feef473994571087d1acca024b6b01c48bc9160ca5776ac9669eb4ce4", - "kind": "transparent" - }, - { - "address": "0x46460Ee9710132e278eb2a4d294C6cd073BC5A49", - "txHash": "0x59b3503ea39711fa75a4a05132dba1e46bad7cfc4ba7fc7a1d405aa79cd1f2a3", - "kind": "transparent" - }, - { - "address": "0x008b66EdF09e6A74E74Bde1493da3Cdc1CC3a110", - "txHash": "0xa4a129207e7455bad4819b377ba83e3758d6e2693b7ef599e82b4a3a27d4eb36", - "kind": "transparent" - }, - { - "address": "0x222D7AB31a287d25D5dDecc83C94d7F52EE734bD", - "txHash": "0x93c04f6cf40600afda7fdd16a3b6d2bd18ebf274a7d7562ae0704ff1ca027b9e", - "kind": "transparent" - }, - { - "address": "0xC76B0d2777dF0F469C223b2cFb82c74C5CF69C40", - "txHash": "0xc39a3f8f93042adeb29e18e08b9afda24fbac90383552af280eb860eafb204fa", - "kind": "transparent" - }, - { - "address": "0xe0F7eB81c7368466A038B68a58a334B1B3573F65", - "txHash": "0xe8663f05ea05d7e4bcc8d4f8681041ec782db5606b3d8d0c179ff6653609630c", - "kind": "transparent" - }, - { - "address": "0xE2dEdC79686c24ef57c6fad594F9c27f00Fa1a13", - "txHash": "0x61caafc187d91b43bfaa012770e972ee93cdc7b75df5636228336fac64a9ece8", - "kind": "transparent" - }, - { - "address": "0xb2153a7032A2F97749e6DFFc2313F1bA2b45D7E0", - "txHash": "0xf31b6d9c9369f43e42a57ac51580dcb3b974257a1e6343317a52cf749e5f4b03", - "kind": "transparent" - }, - { - "address": "0x2B74859840c6fc92aa5802B11A8F2C87925E000b", - "txHash": "0xa53d3568a37f0a30a70fc3bb3e7f8168d3c8ed97dae0edceebd2f6d77b4f98f6", - "kind": "transparent" - }, - { - "address": "0x91B532477981CeA4F24a21f7E3CC1984044F3f1c", - "txHash": "0x1448a11263cfd433b6c9d547952656b3c7994044803507142de735ba0da4d8d2", - "kind": "transparent" - }, - { - "address": "0x1EFC7AdCFc7Ef0B0CeB2E8Df2cb8D5839d89f528", - "txHash": "0x36903c1a2505573a0984ef54ce3f56b600bbf5ad0773b4f00db04adf2d9d8b78", - "kind": "transparent" - }, - { - "address": "0xacD6Bf73756150bA9af19490Bf174C84e6C6E550", - "txHash": "0x3b1bb2f32e40b3aa11f9cb12c0079a8e32f4c9fa05620c29f3bd399b56a60531", - "kind": "transparent" - }, - { - "address": "0xD8a2cc10fdc7452060C339543eAaDfFB8A7Bca38", - "txHash": "0x4d8438ea86f276abdd90ae6dabe6f2ee70a1e76897d5fad8e08a4247ee8a53f3", - "kind": "transparent" - }, - { - "address": "0xC8c992639B1f01cD4C9932ed42Db37DEBb904848", - "txHash": "0xf1295bec0afd6216e8d76e5dfdb1f520dcc5dc3c74e5e5abc813797a3d3f2349", - "kind": "transparent" - }, - { - "address": "0x035D5210e615C8F452106b80C64F0aB3FA65F067", - "txHash": "0xe442dee4f363c2d8e536f8164d8653e353878934f3eba43c0b94e044a177e54f", - "kind": "transparent" - }, - { - "address": "0x2E454e544a5c29ba0339e98C2d459e9981910c7A", - "txHash": "0x5db74a337b8cc1b0f26ea99c1e641ecc1ca4e57e3c1fb0986100a4541f643884", - "kind": "transparent" - }, - { - "address": "0xb534A6b13b8569e98f8DE6bfCF2a7356fCDdD98e", - "txHash": "0x863dccf3394fe45f5d387c611818d48dfa008c779c90be2d335795a0880df3b3", - "kind": "transparent" - }, - { - "address": "0x4337896d128859c8EaF7a1DA3D2931908f3cF7dD", - "txHash": "0xa37f2adcabf4b5cac7d880d1236ecba79b20d4fd09eac8c7dad56f08af68a4c7", - "kind": "transparent" - }, - { - "address": "0x8eef5a6457a79b8E663D4A95ffC14308Be56d4de", - "txHash": "0x73c2d6cd034b65decc70c0049e35dee2fd45f59cb3b88a0cafc960cb34c36b50", - "kind": "transparent" - }, - { - "address": "0xa24525ad3a3c2683375669a9F4Aa4715c49C21fA", - "txHash": "0xc790eb4b73291df2e66fff71e6279205407fd234706b44c292df0bb51ef5a926", - "kind": "transparent" - }, - { - "address": "0x5C94c3C7205063d84600D92Ac1acBC6619EAb017", - "txHash": "0xb22644c6b1298597d0334bcb2104158325d830c7d3b7a70af55ae2359869f323", - "kind": "transparent" - }, - { - "address": "0x54a1CBFE7560Dc1Ff7f1CC2c75E06699cA4c8D18", - "txHash": "0xe1be9c3d2100a0c00ec8a2cd99f7d6c7da09e9177a94268d04749fa7f87dcf5a", - "kind": "transparent" - }, - { - "address": "0xd6f9738a343ACe4ccbc238304F758a11c24066A9", - "txHash": "0x791d506bc2e3ed2549ccc7708cc6ee9bd34e6af70b530a9199ff87d3e51c146a", - "kind": "transparent" - }, - { - "address": "0x4425BE1a2a4613Fe9847C31862722491169b9207", - "txHash": "0x8ef4c596db8ba8f3651d58a0106b6362aa9c41e66f2a36c483475058412ce1d3", - "kind": "transparent" - }, - { - "address": "0x5A1d860d42b5B60204d8C57d785E0C8b4d6065F9", - "txHash": "0x4e609e6b40729b31aee4ee69bd3c00a1ffea6e8379513be50d5e6cc670ddf7e4", - "kind": "transparent" - }, - { - "address": "0xaEAC8E6f7c9C9ba57574317fDADe5E511e8b79C8", - "txHash": "0x696fb5c43fb33acfacb05d3ca0cee531828304d4c82fb783b62dffb505eaaf25", - "kind": "transparent" - }, - { - "address": "0x85c5780eE2cf7c041531733dCF5437052fb689D9", - "txHash": "0xb8e64af2a5e117036f00d11ad529681c317dcaad672a4e3efbc8402cd90b7d99", - "kind": "transparent" - }, - { - "address": "0x506CC13aE6687AF4cE3B3D75C7fACf060B625947", - "txHash": "0x165f319e81422e2c494ad6fc7e0c96e56792ada571a0c564e6176c044153b528", - "kind": "transparent" - }, - { - "address": "0x42fBe0D6f7Cbd1495442AB47C7BAaB550CeBE795", - "txHash": "0x6d9f7e43b2c15ec5a506f0c8e96c45ff0e20d13d83dabdbe32b541091bb78e79", - "kind": "transparent" - }, - { - "address": "0x4ed052E572A500Ce8DC7C0177d50B4e8D685e8ed", - "txHash": "0x89ec7f0d2d089bee0960582c7bc42a0bd5073fa96459f229475303f72ffadcd2", - "kind": "transparent" - }, - { - "address": "0x66aEAD2864Da1706dEe68A72BBB4cF35eA8f966e", - "txHash": "0x73b0b620e307f3cf785d7a0d35a38b396625915591875bd7a125f9ec34539f97", - "kind": "transparent" - }, - { - "address": "0xA09449342C5f3848998f92C0aF9c4B7311fF3121", - "txHash": "0x2f49556ea4d97e7e6f52351dfd8ae9deaebb0b14a80af1e68a508b13243b533c", - "kind": "transparent" - }, - { - "address": "0xe33705ee59387E74f9054d66E64439C1eE9ef738", - "txHash": "0x80affb328f91654e3fabdecfedf5751bf83133e74d6a104a2d9a1c0841f09adc", - "kind": "transparent" - }, - { - "address": "0x973A3B986dede674Cc765707bD7ec2665430efFD", - "txHash": "0x639d8375199f0ba017e951497f21d139c79fec87a94f411f30662b158f5328dd", - "kind": "transparent" - }, - { - "address": "0x3586922f2220C6Be3B061fA24ce22D92cDEF6dA6", - "txHash": "0x520d067b2c4560ee5d73871562fd49caf35900abc4e5e3ae932755f5eb425b48", - "kind": "transparent" - }, - { - "address": "0xAEC0355000a2E5a3E61C0CCD2749d1AAE0578627", - "txHash": "0x206e0a017af306a3ab554e8d5f157900468dbdcf0abf01a7510e8e532a5de58c", - "kind": "transparent" - }, - { - "address": "0x2fad481Da5dEBB58803e03eb272D6925b7CD2e32", - "txHash": "0xe1d14a3a4e15a37c7c470df197c1124a404d0d67766b9acde91857797dd3ac87", - "kind": "transparent" - }, - { - "address": "0x07Eb1b9450467307CF440EA853dCb238568C5967", - "txHash": "0x5de279c9da93113d07c1ea466e19a1ed1c78c0954d20983b63b6e051bf81d3be", - "kind": "transparent" - }, - { - "address": "0x36C7b3A47F122a516a39A3E7EA98e2e586148809", - "txHash": "0xef947a232cea1868105032b0dafac03c0974889554a3cf77d2821e06df1d90c9", - "kind": "transparent" - }, - { - "address": "0x8ED0F981B7b2ac57963f9c6Ca386973c6d4297D5", - "txHash": "0xcadd0633720529fdaa361b6889f19c4e59a921705b30a05e9676fc2811936089", - "kind": "transparent" - }, - { - "address": "0x4753Fc91740F8bc9badA79bd3d0C1FC3948d7b51", - "txHash": "0xbf055e3c63d9f8bb6ec4f8dc2eacca09260ff5257bc3c3649b7b9fb03ea0233a", - "kind": "transparent" - }, - { - "address": "0x4C309BA9f90Bb40a4E19c2C9c5141717889596F0", - "txHash": "0xf2ca5106b20cd20703b68aebc272f0863178b77ba4e988ea506e215d749189a3", - "kind": "transparent" - }, - { - "address": "0xd831E2147e496372f63f3Dc02E726c1446c7FC51", - "txHash": "0x47704445335caee8149efceba8ed16cfcacefa8845e94d711038e2ae4f1c76ad", - "kind": "transparent" - }, - { - "address": "0xAdADD57Ec495F9844B5045188599FAB20B31430C", - "txHash": "0xaf2b1b60175555431ea158e91136d9020e3a534da6065a24cdd477a025bb6edc", - "kind": "transparent" - }, - { - "address": "0x318C481E85b464792A45958DC40446E5070bFB09", - "txHash": "0xd0cdc5fe2dd792013f11d8f3ddcb10516800f691fb4255dc2c335d7d2f1083d1", - "kind": "transparent" - }, - { - "address": "0xf1E8D7045B524307bFB0A87987f224d0D0867757", - "txHash": "0x40632c44115da253ffa037adb7522ec22d5c8626b099cf9a1bbea2e93c789f63", - "kind": "transparent" - }, - { - "address": "0xf968f95826a8478C0d65e6600E0EB803Ea5a0747", - "txHash": "0x925a028286683b065d4cb8eed72ef699788bc3ffe45af5049959c1306b27d040", - "kind": "transparent" - }, - { - "address": "0x6dD21218A391A41209B2Fef770903b1dbFEe0C1A", - "txHash": "0x155cf2dd9c5f989794f40aa965ddb2df79c1a57171ef21e235a0bb583b59d7fe", - "kind": "transparent" - }, - { - "address": "0x8E3CBa6c302af0a56061849ddfFf41D9b321F3C0", - "txHash": "0x505163a9a80a97520f201330cb3d085499f82405188dafc355a8de00658ef515", - "kind": "transparent" - }, - { - "address": "0xFB61ee7E3A313A0B3f8143fc53D65104Ca016594", - "txHash": "0xa6f7e8e593f99d571752071fc5ec91b090bf37eb4f3cbac56735fcf10f60e1d2", - "kind": "transparent" - }, - { - "address": "0xdDc8FdC93f336DE85dF43B48fC463007594A51AF", - "txHash": "0x45d77a2077fb1f89139956eb9a540a2a709b764453e3c986c53cbdfb09e1f5e3", - "kind": "transparent" - }, - { - "address": "0x33aBB3Dd816531F4C5D31F080a21bDf7aBD5986B", - "txHash": "0x1129e2b11dc882f07e798e654f65d21f2f9704509d707ff610a2da0e9f987e76", - "kind": "transparent" - }, - { - "address": "0x49e3C3Afa4f1b7366238b90c624445bb4064Fe4e", - "txHash": "0xd5c72c294cc1a9f0dcceb230b31bc9443e503f3d2d5c5e839011ec09bcd58485", - "kind": "transparent" - }, - { - "address": "0x31EF441b394395Ea474713e3B4b3EDa86dCE66a5", - "txHash": "0xcea276398a669987006f22dd1c84f4085c9e6ba61538548d6ebeaff2a4c83de0", - "kind": "transparent" - }, - { - "address": "0x77eCe84be78b7a12c002E48A9cBbeE3a921EF434", - "txHash": "0xd62433d06d4c5478bd9aa219bb510b60918924b9c3d7a853e205c6be8d270897", - "kind": "transparent" - }, - { - "address": "0x694Eef6eB20c0B5e2b5bAb8BF8348F87A43f0785", - "txHash": "0x6cbf7fa56a37770deab51d8b2ba9583edf465019227cbbeaa0d00b2782eb26da", - "kind": "transparent" - }, - { - "address": "0x3B52E9aab2Ccf2F7b47FD6d75A205477106DB570", - "txHash": "0xd98cabc9ad484f8b5520e35ce9ec9f3e33a35aaf9c2a82fc404ca5276a49a407", - "kind": "transparent" - }, - { - "address": "0xBae939E260Ed15dC8D2f3A7B3046439388B725b4", - "txHash": "0xe1720a566516a0af6dd75923c05d30bfc193f65a4c41c607770d6fc5bbbf4127", - "kind": "transparent" - }, - { - "address": "0x69F7805e411F2623eb0f2b7c6C685c8C6B2279eb", - "txHash": "0x25f2414c33f5d9d6aa9de55e201bcf3b25b8aa33a6a07b09c575656a9adc58d4", - "kind": "transparent" - }, - { - "address": "0x975De56017DEEDe9DDBE2fE135424f56C664462a", - "txHash": "0x0e2dc099703193c0e349d3ff681c01d2004e3fa5aba86aa4ba50086792c16c9a", - "kind": "transparent" - }, - { - "address": "0x8Db9157D364Ec7bdcE6e5fB133AF92df3C58C7f3", - "txHash": "0x8a7c877c7b61fdec6c7505d3eb40d90c326b6e35be2188de03c29e635259095b", - "kind": "transparent" - }, - { - "address": "0x569F0D34e8956531CC822424ddc69BDA392bAfa7", - "txHash": "0x7d4c4d5b1119b5cc080efeac6f66377becdfd568da3845fbd2674f1260dbd387", - "kind": "transparent" - }, - { - "address": "0xbE6D0a39D87058367b0805d89Dc2A61993F1EeA5", - "txHash": "0xc5dbca1659e670e560555d327f27d6d1780257b0582814834d9b40af2e4e7846", - "kind": "transparent" - }, - { - "address": "0xBf165773668BcC62F0dEF753cBb6E752832424cf", - "txHash": "0x4c31d1f4d0bc6afc9f3a2debc4db0f9cd9abeeddf1cffa8c8b49edd123ef16b0", - "kind": "transparent" - }, - { - "address": "0x793A26Ff63C107Fa6110FbDb0454026f37294745", - "txHash": "0x05383bc597df1c9b75be68f69e8671fb78aa6211be4a596b6c4e00d461acc180", - "kind": "transparent" - }, - { - "address": "0xd621C116fF3cCE294fB082DBbf260c5D74c47116", - "txHash": "0xc9bb83e75e4dc3353b863bcc1060438fdf09f6f4786bff913c95a2dd86e8bf4e", - "kind": "transparent" - }, - { - "address": "0x91F5439BdA5a944fBa8B5c0e99e9E8D49d244b58", - "txHash": "0x86520036fc92291b8a6017af45612672b60f089645dfabf41272a86361192920", - "kind": "transparent" - }, - { - "address": "0x72Bda1d69804c2453A1a6950a44c2f34461B96B9", - "txHash": "0x379d55c55c38f6c272b1133c295155fe4b8ccb6fcc933d07da2e9c84f03623be", - "kind": "transparent" - }, - { - "address": "0x6e995bF2E22A470f7Aff780E9cEBc2381522d7E6", - "txHash": "0x867d8c67053caa9dcadb09e109b3eb05474a3fbb860aeecf84fab26063c30ec5", - "kind": "transparent" - }, - { - "address": "0x73a949ce8040C0f11AAd724dAc084432F09C9D00", - "txHash": "0xfa478b5b84560273cff4d62072b9cd5ffe49addf42a5746d1288c94d781d235c", - "kind": "transparent" - }, - { - "address": "0x1839291a892b25DB1077374e30fC368eeaa1CbF1", - "txHash": "0x275876538657fd672a1dbfe30f272b319330a3f24a3ba3870aa172bf56167397", - "kind": "transparent" - }, - { - "address": "0xfCAce6b0dCCCA3a887016Ba5f9B8d66F2070b046", - "txHash": "0xa742d585da723d2918db7daec0def7c0ef1220315b318f4121d3c5c986bc6274", - "kind": "transparent" - }, - { - "address": "0x29361657d52c592F96185f6241E087BE1d2e3408", - "txHash": "0x4f07d17afec2efc98d5307007ace7c80b2ec65655abf2c96f612cd24a64d9591", - "kind": "transparent" - }, - { - "address": "0xe34Cb3a7a0Bc0934e417bD11975c834ad3Bf14d3", - "txHash": "0x52dd3cc358d35515f0d6af1b7bc4726cd19db341400f025a637e388dde900719", - "kind": "transparent" - }, - { - "address": "0x1b3593089B7679F5BbEe885cbEe0db5fF9a76aB7", - "txHash": "0xd7d73cb868357224986da5af40a96237ba6e542020ec12eb4b7b6e03b1b742d5", - "kind": "transparent" - }, - { - "address": "0x3777a2660642eEE1773267c860a755B838689f78", - "txHash": "0x2000fb286e216af789a1dd1b3e0f8ed022057bcdd2be5eec778c275732fe5917", - "kind": "transparent" - }, - { - "address": "0x09daE534Cb5FD85A7ffcC16a74c5321981477de9", - "txHash": "0x596bff96dbc275becae581e491c32615d3e4119a343465cfb33fadefaa6d43c3", - "kind": "transparent" - }, - { - "address": "0xd1b07f47556b96aCD65Aa40f088bD3ab81FE910f", - "txHash": "0x63aad6d52657ae48d6582a68c0e06b7b71b9ac1d02c27404851c2cf8ed969cc3", - "kind": "transparent" - }, - { - "address": "0xa41Af37F51d714920605e00C5158d0778d0d57Ca", - "txHash": "0x45a847b2896a2a605ae4c819c35e299dd91f1d1c34a3d1264daa1104376351a3", - "kind": "transparent" - }, - { - "address": "0xe9D79237563A1a1a5dd71e1CF04491503b2204C1", - "txHash": "0x0c841176a74d220b585c1d3ddc975872eace8477db878706fbd243e16772a0e6", - "kind": "transparent" - }, - { - "address": "0x4a9033c3BC8696BbE54EE9627BfBD938Ec763745", - "txHash": "0x93a37b3123082ff55710a75058c61a922396f9338f7eb3226e4a506c2274b69a", - "kind": "transparent" - }, - { - "address": "0x634ac2976B2c89625d00674E18B48c17B7344284", - "txHash": "0x424d4af61d356a856913d1c05c82bcd3daca3e964eabc33c461cccce4e5078f0", - "kind": "transparent" - }, - { - "address": "0x24156C80CaEfD5113bACEe4CB18435e4048E8957", - "txHash": "0x06112f6d230e47ad9a2e7a76dfc59e617a1ca60194dc559e02ac49aeb9eb80ff", - "kind": "transparent" - }, - { - "address": "0xd3da1393F8e1538D812C7cb8280868505933a086", - "txHash": "0xa6078d0a794f764e8dd0d0d9ad2b0331df3264c0b0d736aac8194609321e142c", - "kind": "transparent" - }, - { - "address": "0x7BE25836469799d9b8ecc446C1C882A7F3e5E1fD", - "txHash": "0xf9f00bbb790c41c684bced0c610643b4eaad32e22b6b7cef46b2a5393601271b", - "kind": "transparent" - }, - { - "address": "0xFB4c43F10e2d81Ee3f5fc61CaBc4B943ca5E1075", - "txHash": "0x8ae81479e3ba1a50e98cf0213cf31e8b4dc631ef92e630628c40e6a0319f17b9", - "kind": "transparent" - }, - { - "address": "0x8CAaafbF2288DCA716DFE6B881d299cb59C01958", - "txHash": "0xd6c7aa4701f6fdbcc7eaa687e5fdb0c277e4c407a6e553fda8cec0a1380c046f", - "kind": "transparent" - }, - { - "address": "0x18cC0dc00965994eF30C00a6a256fE84cF011DCF", - "txHash": "0x906cdf016053e53d5cd2d7a7875c8f15633748b69e20958bc0e5d87bf622fb82", - "kind": "transparent" - }, - { - "address": "0x66c46f5155AF397497E8D1B3188708b55310bb01", - "txHash": "0x91814532696063c6eeb40973e37303bf05e04ede9d05245f563ccfa606beb54a", - "kind": "transparent" - }, - { - "address": "0xD975f386c64523c9664572F8b3665ae19874f51E", - "txHash": "0x35ea2232c72e3fdfcc4c01a88d51374ccc106a29623158179999681033e0d1ac", - "kind": "transparent" - }, - { - "address": "0xc5f12b2261FD26DC7a11871A25Fb4Ee263CBC1e8", - "txHash": "0xb7cc7d056fd406ea46a06760ccc3266801ab8c485697d14d47af179c127dd2c8", - "kind": "transparent" - }, - { - "address": "0x3ee5D936484C8c07Cbd4e3F50d9c74Ff4f51773d", - "txHash": "0x0e43842b2f2a50175cf79c04da688eeebdfd3a8317a5a46b86cf7ecb3002c078", - "kind": "transparent" - }, - { - "address": "0xaD9441411b80382DC6cf6306D7Ee66F59B068244", - "txHash": "0xda7cfa35651637863bbfab0aada3afd76fbcf46b63322a09a07c98a19fb59636", - "kind": "transparent" - }, - { - "address": "0x9Ea558777509183C814ef4ce9F088C87f7ce7ea0", - "txHash": "0x62be699113d472076d0d3ba8a7da9d485edef7588ff5e08d2f20257b614e4c8f", - "kind": "transparent" - }, - { - "address": "0xf49B53A0875e23068965A17ab965fD41a49766a3", - "txHash": "0x1ea0be656639502ee8e41b8fb21c5d957462c7749a6919ea4184f3d250a3dfeb", - "kind": "transparent" - }, - { - "address": "0x5C59dc5298017682cC8662B6F5572e675a282642", - "txHash": "0x799011b44e3354ecd2400e0671881f45dac421765051565b2fddc3ff7c0d2728", - "kind": "transparent" - }, - { - "address": "0xDCebe564b077034f6C7214CeE37D68F2832eD078", - "txHash": "0x96b1048019b84ace2bfefd8e9545f2f7ce84bd2a473ca897b90ca701ebca33a7", - "kind": "transparent" - }, - { - "address": "0xEb9908d56B32E6a1f81772472d0Db34C037b2403", - "txHash": "0xce36ead83725f8f58854f22e54ee79d97d4c0ef4246b433534a0a498cd1981a1", - "kind": "transparent" - }, - { - "address": "0xAEB8ED10ee539220daCB75FdFa44A6dD96A999f7", - "txHash": "0x6861c70f16ff85050729ac1991ce1ed68942b8ebf487afbc249f13501659c03c", - "kind": "transparent" - }, - { - "address": "0x92c108ab092F2B17D612e794beDC87f043165c9C", - "txHash": "0x797c17eb8a1ffb286c55b06509c9956e497249813973b5b17652b3a057a77ab1", - "kind": "transparent" - }, - { - "address": "0x8c080e5Df71aA3E9F84B3511D4C8a32CA44B6B0b", - "txHash": "0xda83bd025464aead0efd8524511713ef74e4870424f25449ce6767a4fede943d", - "kind": "transparent" - }, - { - "address": "0xB170ab2aA8bAB763C3cB346a4c14BA2Fd3B954D3", - "txHash": "0xe1db5f1203e706df3553994b9b378bf63f9b3d1efcaaac57d63d8b2b5cc8be5a", - "kind": "transparent" - }, - { - "address": "0xCde0C18151A10F97D04a03DeeaC993324556FdcC", - "txHash": "0xce85dda1e8008107143962a5747310d60cbd6b5a7b12cd1fe41282864b0d59ad", - "kind": "transparent" - }, - { - "address": "0xC4DE1D896FAc96559c5677f17490dE9C57A7273f", - "txHash": "0x251f17dba8c05cc97d9fff584b5790bf7552eac9cf117c651fc3af5d2a541eff", - "kind": "transparent" - }, - { - "address": "0xeda1Bc253BAfB71C96901C2B50f664C928A8d5A9", - "txHash": "0x392c0a4b5987f3cab867fd105c3d4c8321a4b4923505de1d3565fc19f1e0fe0c", - "kind": "transparent" - }, - { - "address": "0x3F68d63a9aF0260620e72a5d26C799f6ea429b33", - "txHash": "0x99a15631a857b5a45a5f8f39e9160de30edca9775e9b77d04f18205173830f15", - "kind": "transparent" - }, - { - "address": "0x8A5d903d70D832dDd171FF2e61f2d3d6fA04Ab01", - "txHash": "0x52d6700a04cd7d4f2300aefa79cd30dab86b09b18c5fce4a52f88af87dd78d1e", - "kind": "transparent" - }, - { - "address": "0xCA9E8d56317CAD96b1C7FB30c788f210EAa91F63", - "txHash": "0xf4a51640c46c3fa25df10910bf4d8ef15fa943e4e6bd86b07632f077c66747ac", - "kind": "transparent" - }, - { - "address": "0xD3Fb046f2685a85ed347ad820D57c94eF8CF3dc1", - "txHash": "0x491409a149162150d0dc84ff66163e99f696552eeee420f35a2c4b365f38a673", - "kind": "transparent" - }, - { - "address": "0x4e83873Ed3734D205087a6EF41B12e8A8fCfD91e", - "txHash": "0x039f5610aedf691f4ab21a25cfe70747dd5c73080cc8a743bdad972d7a94a58f", - "kind": "transparent" - }, - { - "address": "0xD8cE01701EAE7482e93dF6004701A665d10763c8", - "txHash": "0x2c30e2478e916de56973189d8ea19467ad8efc2929a8314d736376c5d20ae2cb", - "kind": "transparent" - }, - { - "address": "0x33fE7C3D9029502454EbAfB430a470e1ce44C9f9", - "txHash": "0x2bba0de9c56ba560af42aa28f1279b128f37a37854ad9a9ce9995a86adedf74e", - "kind": "transparent" - }, - { - "address": "0xf535F7A36cC2725d6b9aB9d2469B0c48cE2892d2", - "txHash": "0x152dc0d160d6c0e5d925fef8c03fa240072867f98264323752e167dff63c0e36", - "kind": "transparent" - }, - { - "address": "0xDeEA72FD8Dfd2307453E6873A5b291DC5300dd56", - "txHash": "0xb17a031dfff52b638d32b8fa45a3d11eb7171f8164472241bc74657a8cb112be", - "kind": "transparent" - }, - { - "address": "0x3b2f1B497e23c1Cd462ebCa3fd4964Ab12BaFe99", - "txHash": "0xa3fd6510fc4f94f45a44edb67928a2f806980dcc451a5b6bab78cccb37c5d352", - "kind": "transparent" - }, - { - "address": "0x979D1Ca12209E85163ECb706334B02F9b1046DC4", - "txHash": "0x8b88b2eb45e97d11fac5e444ee4676680c6c02dc4a04d0db5380b2354301c7b0", - "kind": "transparent" - }, - { - "address": "0x0e14C49f8A9F9Bb764A44F2CFFa2b911C90f4706", - "txHash": "0x9582c736ce3cd1da96f0dd12f0d9b0cc7d0c5efc9cff521ea2098cfa46449420", - "kind": "transparent" - }, - { - "address": "0x5F61BA3FEBbe95bF4eAD8A57A0d08b4b3Ddf1299", - "txHash": "0x6a9b2e4aef3096683e592d10926edbc80eff060aa722f2c6e038776c3f06ceea", - "kind": "transparent" - }, - { - "address": "0x0E8b58e09fD4D4BcC5c8034bCfaAD759ca957341", - "txHash": "0x6ad7359d3af7df94e026dd3397b48488c08cdcf4c9d9c7a301449ffc002fe0eb", - "kind": "transparent" - }, - { - "address": "0x422571f07B865f53A37E6a8DCB1452d71be05539", - "txHash": "0x5ce4cd44b55fb7fe6ba86e753c524c1ac034bf785fbbbae89fec20c78372059e", - "kind": "transparent" - }, - { - "address": "0x319f83F42abA127C0b2BeB02C399bD7Ea738C640", - "txHash": "0x997b4570e3d5406b9c1993aac5777641903fb9dd13aa48d82c7203e666d2eb8a", - "kind": "transparent" - }, - { - "address": "0xc0478AB6d68D4cFddbcB9DbAA835086035cf4e4b", - "txHash": "0xe3a1754f647e036b4123c0cdce6641ac7f933b88295d1a5b199c29b54e10710a", - "kind": "transparent" - }, - { - "address": "0x15e8ac5d378dCE2FA29e37f58C217a373ED47474", - "txHash": "0x32f9fe2a2d4994c48b899fb8e8befb244c3d5b94a7042cfcd0d7e4effe681d26", - "kind": "transparent" - }, - { - "address": "0xb155BA71318c31f63C48FD435851C7C4786DF780", - "txHash": "0xa8b00ebe9f1beecf3d7101e7e2f02b30aca190a7634adbdfe78857b0fcef9cc2", - "kind": "transparent" - }, - { - "address": "0xa70d7460b0f4CCf0aD98e9DA0270d019B7C36A77", - "txHash": "0x31b2ede7e4a07372456edc482dd26a4cc5ad263f84ba50085edc168fe0dffc0b", - "kind": "transparent" - }, - { - "address": "0x57C72A091360E45d832dD665183B808D17Cc8663", - "txHash": "0x96397e22c1b748e89dbb85e69eac838e4c259c61e1b2c6a8ab381843b2af1e64", - "kind": "transparent" - }, - { - "address": "0x3e6AbEd1543E5a064A84B37060578E13B5f7d19e", - "txHash": "0x5cfa80e24ba2cb8bbffa32c442a304d8bb5bc073badff17a2e5c70753d5932f7", - "kind": "transparent" - }, - { - "address": "0x6e02a3A14C30aa276A727a966ce62456777e1F64", - "txHash": "0xdae0c1b1b50221efcdfda925d87c698121900fb6b93943da03ee2b8a84311c02", - "kind": "transparent" - }, - { - "address": "0x5Db106Eb18Fc2016a66912fc61F8438AfcE35a2A", - "txHash": "0xfc5c17618426ae9f963d56881cbec35eaf8f8e71b95f379ab0aea001f039bd0b", - "kind": "transparent" - }, - { - "address": "0xD78a5A4633F82DCBC20cDa4d66a4b14958FBBdc1", - "txHash": "0x0e309bd83e053d517931bf886747c7b0e06229b56adf9cdd39d084903cce8805", - "kind": "transparent" - }, - { - "address": "0xBe032d7ACab86DB1a353da36d30322192A393Df2", - "txHash": "0x71851256d27895e2f13034b206a0a2180ff1070539cd9cdaf446349e942a08cf", - "kind": "transparent" - }, - { - "address": "0x5fcCFE2c95797f4fC16A73AF3B18f6647c1699a5", - "txHash": "0xb24ac95e2b444d9aef00c9f3a5ec2bc558b2633519c688d4740346b07cdba5da", - "kind": "transparent" - }, - { - "address": "0x4Af0d93Ee1455E27c08671E3aa64e373679D3b24", - "txHash": "0x8b96e4149cd2276b5c4449bb7c661262e0a8b49c5e0223da377b989700619bd3", - "kind": "transparent" - }, - { - "address": "0x8f3e3cc7579929C16A0694b39ADcA7b08C66e99c", - "txHash": "0x145194d328409988ea6fccb79445e148eee741eba38c571a6af7a16b9889bcf1", - "kind": "transparent" - }, - { - "address": "0x3f1b33424aD8e0892150650e6320555d6728A4a9", - "txHash": "0x5b35a3fd52b3c1744ed406cfa5ab49fc4351b5dde6f43073eb402fdcf9d5d89f", - "kind": "transparent" - }, - { - "address": "0x5E0E84f137cC2E02326B15325b06923B0e833679", - "txHash": "0x94ebab48082093783920f1fe3ce58c2e11d9f49b36d0e8ac6895553c1a49b91a", - "kind": "transparent" - }, - { - "address": "0xC372934ABb2Cf1813BC7D7898B66cdf5304A7501", - "txHash": "0x4c988b6b057da2af85ac2e70a0e38a5d4bdc1b1b47c68bcfe8f285c81d555989", - "kind": "transparent" - }, - { - "address": "0xE4c80B1A245082DE2E7b506f90150A5cF1c5aD2b", - "txHash": "0x61e75350dbc413ac0e468603f58f6c7b931ccbf982037a928d20ce976ba6c19d", - "kind": "transparent" - }, - { - "address": "0xea536218BB310de8B3E20027407929733a03c5b3", - "txHash": "0xfeb1666f26210e82c9ed595484f31cc23b48cb60d02a4109be223ba5acf5cc7d", - "kind": "transparent" - }, - { - "address": "0xe543Be8Ef44967239D36D5b27aFF6eFb633EB68b", - "txHash": "0xeb9ad9c17fd75a00935277a710017f8c91d0422291bcf2262eb2ad222ae0bb60", - "kind": "transparent" - }, - { - "address": "0x78d855F4ea354B645E192EE6AD57492008037D8d", - "txHash": "0xddc0425aa34979a2972a0e387faa55e1e88d49fecc590a359ec3e01077a42b07", - "kind": "transparent" - }, - { - "address": "0x03Dc879db71A17dF7D7BE864c56A91A96a5cB01B", - "txHash": "0x255b91275b5267b78bfcac86ea18088c6bb8f1db46a7480154982a4648e517fc", - "kind": "transparent" - }, - { - "address": "0x8Ad67Fe18551892181edbE4c6CAdc728Baad3A55", - "txHash": "0xb032c8e4d78f9167af61079c30d6f33f5d4848e63ccd63bea91aef30112eb70f", - "kind": "transparent" - }, - { - "address": "0xFdD53fd7AC7C4Ce7e37E54439849aEAc5cbAB0A8", - "txHash": "0x0de28fe2603453ba14984e2a475609f7d934d2529d8f2abe0b8c1e83d8084c2a", - "kind": "transparent" - }, - { - "address": "0x22E3446f4A11d135d10112a6dff268adBe0ea067", - "txHash": "0xd85c578db1ded25e030ef51080dce2535ea47acd7498f3ad0ad387bad2d571e9", - "kind": "transparent" - }, - { - "address": "0xF25dDcd1ba25981d49707fb340d6D8946bf7244B", - "txHash": "0xea80369a5ac373838c073c231745b9508528883824600f800806604bec7b43b1", - "kind": "transparent" - }, - { - "address": "0xBEd8b790Fb7752E3333BD7B300979564E2E8DAb3", - "txHash": "0x284c8b6ace64e604d3c3ecf118a316e269c4d4f623935d40bb9229c47dab18a2", - "kind": "transparent" - }, - { - "address": "0xec324Fcbb7a2543fDa13c621468eBdaC32d5e8fe", - "txHash": "0xb111ab45e9c48be422cb89b2798aebf26f5e0f12e89d12f1d45f7d1ff88e761a", - "kind": "transparent" - }, - { - "address": "0xC75087e2419EA1aaab87eaa84b126fEBDb224DE2", - "txHash": "0x5f0f9a27da657c3a475e856719c7621929a42cc8e394ad87646754333ffd6ac8", - "kind": "transparent" - }, - { - "address": "0xa9121AD9D763ac58Df47291Cdb54Fb314F61D8B7", - "txHash": "0xa94dbdf6e61265d04bfab49677b179eddd7392b959a7b7f18cc8f44311aeb9dd", - "kind": "transparent" - }, - { - "address": "0x791CfB6eA887310cb12989C275B9780C53C49C26", - "txHash": "0xb132d9cb4d4bd89da24021c82ee8078f979aa76e89dd83bcdbcb02f097b9f705", - "kind": "transparent" - }, - { - "address": "0xB17bC270c8755150A5F7D05Ba72b470787cFDD32", - "txHash": "0xcb028c79370e58002eafb0a5da3720d9b42d0e1ad4d7adef0dd7084e54313974", - "kind": "transparent" - }, - { - "address": "0x6bf5Cb0Db09C0774b76Ce8acd11e3fcfB8f8600e", - "txHash": "0x9306e2beabfeac8b2d770e0ed699d0ad1c71169d40b120466c5d482321c8d9d9", - "kind": "transparent" - }, - { - "address": "0xBBAA02243e15742FE96F34d2B8B6B472C3bAe2AC", - "txHash": "0x462ab0029b700cfb885cb05e4354a1ec5cfeb2df81756b39aa139f45212d31e8", - "kind": "transparent" - }, - { - "address": "0x741ec626a5f3CAe1794A6D521dc1400ef7aE0F70", - "txHash": "0x67401c5abb1468b16180c5691fa645a2e0c833704e027c23f67d818e55ee0189", - "kind": "transparent" - }, - { - "address": "0x3dA7e2DEdA0829bC0d71df952fd71160A516634B", - "txHash": "0x2a22d95e2b58b769048a20365f8c894570f3527dae363abd6ac0d22b190b6133", - "kind": "transparent" - }, - { - "address": "0x79e7A77740C595985b6d87fF2976CfEA790D7ffF", - "txHash": "0x7456841c6b0ef8dbef1a3e2ea827b7f4f4b23f18700a448eeb919c911cbca22f", - "kind": "transparent" - }, - { - "address": "0xb395FCD53bF019055B019d9Cf5d41f18a1E23cCA", - "txHash": "0x2a7332e7559669444bc56c438ee6e7fbf2d504449f831445144e8ec475098cb6", - "kind": "transparent" - }, - { - "address": "0x339719819fF0E8A75324e75E7daDD5506efcCC9E", - "txHash": "0x367fe4e2996252500c74eaf7afd7396b0d3e43ca6d2c6853bc8592e56123d3f9", - "kind": "transparent" - }, - { - "address": "0x53d2Bb8Bd6061Fff3923939F2d1fCc8e26e20fAA", - "txHash": "0x34a2e4536fec68e825e2680d9c0598965eec0977670242509baf7f7815989bd8", - "kind": "transparent" - }, - { - "address": "0xc9E9F27215cF0858D0b7C006801CfA9C1dF5b67c", - "txHash": "0x6166ab8a5b89ab8dce9fb67745f2240469dc9eb5bfc67a6ab1dbbd8d9c057ca3", - "kind": "transparent" - }, - { - "address": "0x58215F146723174F7ec64110689321a8e99fEbaB", - "txHash": "0x3f8edfbf0f959bb26dfcebd7c310b3cb798080abc8fa5f84775c500466c3cd3e", - "kind": "transparent" - }, - { - "address": "0xCB5B324B884Fd952011735f33567CE429760c6ca", - "txHash": "0x630ffca192a02f3cb859fee7a2f183f9e2d31601f9ba8e16a3b9e796166f370f", - "kind": "transparent" - }, - { - "address": "0x15110F19a4E434cA74A93a6d08cEb452fa41ADb5", - "txHash": "0x365ab33f9575bc1d6d7deb8cd2eed2bb7fcd263fb8b2e36dc0ced5a1b866afb5", - "kind": "transparent" - }, - { - "address": "0x3C51482B01671dc104d476Ac1ad04F358Ba314aA", - "txHash": "0x8f01a6238448e2a7ecb8a354f5acae30ebaeef9b4dbcc504044eb2d08df8164f", - "kind": "transparent" - }, - { - "address": "0xEd97b55096264aBFd66cF3abe9C6F9737CCf699F", - "txHash": "0x3448ca5a2cb0684761450c260d50755161952814b462f41e048e4778850cbcf6", - "kind": "transparent" - }, - { - "address": "0x059a10bb36a3bb8A14853569e75B9dA788ba382A", - "txHash": "0x273633ecac0d54ec49c2be9a6d64b19dad16634fb97ac3601e9fc3ae30acdbe2", - "kind": "transparent" - }, - { - "address": "0x14d47F1028D3aE53BC444E9F92BfAD827d404FCD", - "txHash": "0x6a3a6e84fb7c9538c91334b8408b5a62b3e4faf66ac31a3dc9b44907f2c6857e", - "kind": "transparent" - }, - { - "address": "0x032D85c578B0ba9eF47099C68f7186Ff979560B8", - "txHash": "0xc68c286f9a1bcb8f736181bdacf027456b65452fa1269f081e1d3d0ddc382cb5", - "kind": "transparent" - }, - { - "address": "0xC0f73A7c53DD95F2335A751FaCAff04D4Dca4857", - "txHash": "0xf042c68224eeb6cdcabc9d404ca246c478c928d4a5ff78ca93df2ed54fb116cb", - "kind": "transparent" - }, - { - "address": "0xA695B0fABA90807C0e9aC744Db794A7928DBAa1C", - "txHash": "0xb07ba0bbc37d3fc2c912e9648fbc05f682a4b39e947ae443984a42310ae53f5e", - "kind": "transparent" - }, - { - "address": "0x6b55CC752E1636e6F842170C56347184820664aD", - "txHash": "0xdedfd6a56ff6237ec368f47a9cd8061444598c7dce50c6c12041640b9d653055", - "kind": "transparent" - }, - { - "address": "0x0e6f9de29e6A3445a51Ab234C39b8613cD2D9016", - "txHash": "0xd2fafc1ab8ba7d8ef28b8181579a0e3327221a7c15516ab89f27ac81637f3e47", - "kind": "transparent" - }, - { - "address": "0xD2f5D3A3bBe104Dc1df69Ab41D94d119663CA3ee", - "txHash": "0x3c512c55eaea90c1b8df865eefb7bb152617bc91825ae68bbf95c6bf081f04bf", - "kind": "transparent" - }, - { - "address": "0x009D79279dA6fdF758c39fca3a5A8c6F5b94500f", - "txHash": "0xd2e9ab9734abbdb428581dc085ab9927d91f9490af14e23e8b78403cd18bac20", - "kind": "transparent" - }, - { - "address": "0xbD8611a4a5C4b4A1bC1938b61767151EF34f27C9", - "txHash": "0x27852a7b1f60c785ec48c2b39a6858cf5b5a04c0110e7af8a3481135de47fcc0", - "kind": "transparent" - }, - { - "address": "0x39077db88eCfFD2E827E17001371ab657a8cE726", - "txHash": "0x55725c370f0e199082d1f347a2c0b65efd5dca6dd0e1e5f4134c709dfb749508", - "kind": "transparent" - }, - { - "address": "0xcb185aEbd746F53bBd6EDbfE7B32f5Bd0cbA7482", - "txHash": "0x02536333ac80415efd4a0f81b136ac8f60b2cbda6c1ddeca682bf3bc1d45fe50", - "kind": "transparent" - }, - { - "address": "0xB05f091D2C270748Da0D5EE023f0222C86143805", - "txHash": "0x0a926efb3bd9094816e4ae1aed56d0ba97667db820bd186b65128e51a1893401", - "kind": "transparent" - }, - { - "address": "0x6d733C7730Bc8fb3fd2777C03278317594FBD02E", - "txHash": "0x2c8fd0a00d197cb135db2c9c46838636ca76865f1a10431d1a3faa360f00ee0b", - "kind": "transparent" - }, - { - "address": "0xB54c796e60B428C7d46C8C2B71e968dF3d6403f7", - "txHash": "0xa291e363f10f027792bab0c2f27dfb3b83e798959607dea8a801d7873cff3aee", - "kind": "transparent" - }, - { - "address": "0x30EA00311Dd54d3c22a5E34421d1f91015808be2", - "txHash": "0xad1818dde6b060f39dc5a050934c73dff9778b291521f918caddfcff5bdb3ef4", - "kind": "transparent" - }, - { - "address": "0xeB8E3e957F062541a57a70443Faf14E5de27B6af", - "txHash": "0xde55dea2707894c733faee3d25024525804cb500c4aa404a74815f91f8900156", - "kind": "transparent" - }, - { - "address": "0xACb963A771E18AFd27c10653ba0948a147aFD7eC", - "txHash": "0xed501475d9381f1a8ce869454422d71ced2d112ae6e0d431212e81d9d96ab21e", - "kind": "transparent" - }, - { - "address": "0xD9EdD759518fb6cdE1e2A804848072847f8526bF", - "txHash": "0x9d495c404535965abd08aef4f83621dfeb6e97ad1fd5abd5b7f93491a0a91cf4", - "kind": "transparent" - }, - { - "address": "0x00860887a7d6C2871bC28d257514d47f96a5acC8", - "txHash": "0x4d8186d73ff31213f71e4f8cc58098d240cc352e55035125bc5b986e455cb96f", - "kind": "transparent" - }, - { - "address": "0xc3856cbB69284358F7E682AeEe10F72C40Eac0F0", - "txHash": "0x8e867780fd043d80d1e9e9a803c75be10b701b8cd7a0315752fd13f3d2723a0c", - "kind": "transparent" - }, - { - "address": "0xD0e8aa0037C0c9707bD7aC61659b5D9f97fE0B17", - "txHash": "0xabb5e3e1d2e9d7e48fd276f01b7902736ab56fdbff110bc9cbf4950b422d5773", - "kind": "transparent" - }, - { - "address": "0x036a52cFa76120C6ec33Ac9934588FDc137128F1", - "txHash": "0xafbbe593a00b4954757270f3d244dd241b9b156646dace7578c2d177ce3cbfeb", - "kind": "transparent" - }, - { - "address": "0x809C1AAacbab5634b10903A3A56511BBF8046C58", - "txHash": "0xda53686a0009324e584c1565593f676804fd10ef52bbd9e60703dfa6ba680b1e", - "kind": "transparent" - }, - { - "address": "0x4f3c9b9789d3241f934D8E124c69257893300dab", - "txHash": "0x4b5614cfeadf54be16f17fac66abd9cc6126e19667be55e2745bc7d9e1e07e44", - "kind": "transparent" - }, - { - "address": "0x5295Aeb93aF2811FBe6a1bA0B78086dfb3fe3656", - "txHash": "0x52dec6515472bd033fd8ba20f775e12ef3087576c3acd473bf6c66732a27c923", - "kind": "transparent" - }, - { - "address": "0x08a73c726aa7498d29250954094a6DD7eEBa1219", - "txHash": "0xc693755438011a804e89c35f3eec81e2de6b6ad58805d8a177aff1b274ec78f4", - "kind": "transparent" - }, - { - "address": "0x1C48D4822775d5A041824059eF0714F6331F2628", - "txHash": "0x7d6f8a35ae02c88d49e8daab8c3941a57cdab4a64324787f85b63f1887bcef87", - "kind": "transparent" - }, - { - "address": "0xdEE3B657b0d9aBCf0A44cD9f784e20053b43A3c2", - "txHash": "0x58ec9a049f75ad83ebf684b892e66383ff4e869eec1a46e2d3edd290e73cafcd", - "kind": "transparent" - }, - { - "address": "0x0EBBA0779532AE6c4af1b5dF6b460E8142086588", - "txHash": "0x0587902745921c66b5c075b6424260aa62d040f4aca8d30ff530897e54a66f2e", - "kind": "transparent" - }, - { - "address": "0x62944EC9B2519592Bace18F73239952362E16EBd", - "txHash": "0x3530cf5a06c6a0654dc496d201279ed198fdf2f5ea6be285560ffe11aae4f928", - "kind": "transparent" - }, - { - "address": "0x5D827Fa69177F34835D345EdfD9CC007cc716A69", - "txHash": "0x707840ab601e1545c202e1940bd2fb5e45dc83373ed12d3e029e262255c41136", - "kind": "transparent" - }, - { - "address": "0x4C2a3C30972c56E29f548f60e70Fa5bfCd26476E", - "txHash": "0xeb11e48587fd6314d51d48b1712fee1f45a47a2ba99ec9bba23aa24d48e9017a", - "kind": "transparent" - }, - { - "address": "0xcBD6d328CbbE43dEa0c82060CFf2aCbEB974A5EC", - "txHash": "0x3f933d5bb747cfe6369f9430381142591b7634666fb677375e99bf14e4aadddc", - "kind": "transparent" - }, - { - "address": "0xDD2e91DebFc52AE4C5e8232bAB80dFeA10C36d5A", - "txHash": "0x766d384bbbe054baf9092d3d4e3c93b79a4c0c84e8785633deae6230e1bfe699", - "kind": "transparent" - }, - { - "address": "0x555773A591B701a505CF414464F2065128e9cd78", - "txHash": "0x210807aa6f157f5fae9688ba9cc64750d67900779d87ad0e687c186bc603bf9c", - "kind": "transparent" - }, - { - "address": "0x1a7080DD9e1d1F238Ac1d878Ad371c43bE4c4551", - "txHash": "0x6404220867385ce767d1007de713b63d0cf4d9f1fef14d8466760aec92bde922", - "kind": "transparent" - }, - { - "address": "0x4C4B06c9473927524D04f01a7d196bb81c7D2212", - "txHash": "0xe7f5c0e0ac6886300bc7ff18e02b4be1edad27c5b888314ac4f35de7e277206b", - "kind": "transparent" - }, - { - "address": "0xC54678a2f441bFe01f4987f9007D538D784E3750", - "txHash": "0xbd60406103f95950d06d54ed9fcf944de3f517e181207f5411482acb742e2ce4", - "kind": "transparent" - }, - { - "address": "0x6f9028D6C92160101bE700c6a85FbDa4f913F3d6", - "txHash": "0x6a6a8236daa700b17496fdeda2ce769e909dcf3b6e652f766e5741f7ab891b1c", - "kind": "transparent" - }, - { - "address": "0x2ca4075125686BF568AA1491df2b555dE0Ed8f47", - "txHash": "0x2bc804a738452a518ad16365a0e303e74055027d7cc3e37754b652c5ce5d444d", - "kind": "transparent" - }, - { - "address": "0xb31ee22035c92F7fb115606821952fb4b2f5d27a", - "txHash": "0x5dce50ca7c31ebdb41010ca7ce2c0bc3ebe2d7d8993177c68707c614f8994d17", - "kind": "transparent" - }, - { - "address": "0x68fc3abaC4eECf6A8A0f9A70a07199eFE79eb36c", - "txHash": "0x82c9b3f4351efaa73e97b66bc0befc9788fc6c90b3a1312cf2bbc61bc3fa2e1c", - "kind": "transparent" - }, - { - "address": "0x7b338F648c56F7cfF9eF47bBF210c16ECde2BA58", - "txHash": "0xe2c4fd33929130fa7b049e40eae8dc9632e044c7ee6ae72d3639a4d407f87d85", - "kind": "transparent" - }, - { - "address": "0x8411D31a654c206413bd745b6557c6cb6ff1c59b", - "txHash": "0x71b1982ad832c30705c69cf7b037b1b9a4ef859bdc0c1c49f9f13afa021a8821", - "kind": "transparent" - }, - { - "address": "0xE541b6e4fEf38185Fd67C7d44aec63e7d955b7df", - "txHash": "0x628606a896065d41f809c61f8bbac46bc6726207a7a7233b15e204dedac7d2bc", - "kind": "transparent" - }, - { - "address": "0x762636D91f14FDCE36248e348F502346f9A0D9D3", - "txHash": "0x9b165d9b796448b3201ad887e2f393db34ae157a70bf113ecf307cbd8b4ebe0c", - "kind": "transparent" - }, - { - "address": "0xcB41996E9784545f0970f784Dc3684b21e765d61", - "txHash": "0xd7e0e66158825aaed400973cbb67f628cd9a03605dc521135cf6c1654ffdd9f2", - "kind": "transparent" - }, - { - "address": "0xc130eeb12e983A7dbf81C4E94Ec550914eE85c85", - "txHash": "0x22a112acb90bf7f90d2435d70305c7259203d7c93bb5e4aaf9e8dd670a6afa78", - "kind": "transparent" - }, - { - "address": "0x9B52309cB8b19E5d57B37c2D8ECA5F7Bb97eB81D", - "txHash": "0xd24e79c90d5f17613d19009342637bd0a9f7712829cc3a92731f97f893598f3e", - "kind": "transparent" - }, - { - "address": "0x92321d527A2E713f62412D79C74073E502CAd83d", - "txHash": "0xa0aebd28a86ec9540b7b2e42960ef4324f4939d44813458c420f0d6c8ae4fe4a", - "kind": "transparent" - }, - { - "address": "0x3B343Da74F8C515DAf68f001e894943f3501EE18", - "txHash": "0x771213f531ab086e1f0d1c691dd8f9f971f6d7e9919b407772832fe9212c7af3", - "kind": "transparent" - }, - { - "address": "0x1A311360f2aa88FB06770276A6B041C0054a7e2a", - "txHash": "0xa521fb40ff43bd44c4e40cd51a78dde65b4775c494e8bed89b9b4ac17c5ca57d", - "kind": "transparent" - }, - { - "address": "0x46120702F273aFA3124D8BACb56d33d216e2FA91", - "txHash": "0x15d9a75253e8b7c77d8e20fd1e8c389409a771016d226de5be42866508c6a7b9", - "kind": "transparent" - }, - { - "address": "0x266498f71fe098dAfF08Bb207018dEF9EFAd7593", - "txHash": "0x57464d454cbb44afc98d87ce47f2ca15526fc6f727559035c562c97b77c32cff", - "kind": "transparent" - }, - { - "address": "0x8f92F046325E5d2efBcF48094C80EAa3b3C49886", - "txHash": "0xfaa4c1c18c7c986d9d45e8a10adb827732e2836cc6835ff28eaceb8de6502022", - "kind": "transparent" - }, - { - "address": "0x70fD4FE4D5a53b28217173981F3782184AEE2E54", - "txHash": "0xdba09a19e96de2cb11319b2f540240729c7a60cd483fafc8d3431f5cfc2b0db9", - "kind": "transparent" - }, - { - "address": "0xa55620D9b01025E0FD9ac42F1Cfa931DBCf90210", - "txHash": "0xd07d77a71086ceb0bb53eca8e6389bb10f1861783ef23086d2232d6da5c1634d", - "kind": "transparent" - }, - { - "address": "0x0C683e8de2224BA05EcA0d3b264D2D6D0273878E", - "txHash": "0xd9cb975e0656d225b7679e44d2a262e41a0145b07adfcb79dbfc9929c7b64280", - "kind": "transparent" - }, - { - "address": "0x526Dc9d0f0bd6aab61f63d1067ea09b70A166453", - "txHash": "0xf11dda6d5f7e86da00b8413019dedfd39f95c8a159898e245c6850416a799260", - "kind": "transparent" - }, - { - "address": "0x1f5a46e3ad5E8926Af2e1E6D2903A74a9247E988", - "txHash": "0xd75f95f80dba098ca3cb4cbfde1ef7666741955aa7461462d698f33fa01a363c", - "kind": "transparent" - }, - { - "address": "0x7E8644F0047eE2598682c10AC53f6CFeC9F8A4ce", - "txHash": "0x946be58da1795d6e062664b1f05b5480ad989577d89ec5478d30430d3cab354f", - "kind": "transparent" - }, - { - "address": "0xD401c24041F42197a73AD7Ab4Bcab0cd502500B9", - "txHash": "0x413cd3c8403fd7d80ac66b83f56b4fb398d547399a18eee17e1df4b007d09f71", - "kind": "transparent" - }, - { - "address": "0x94925d057835d8658B71136E192b9283d7fcfd35", - "txHash": "0x1f56dbfe72f35c3b63080551ea2628fd78a773d5bddf6f20f700b5f5442423bb", - "kind": "transparent" - }, - { - "address": "0x786c58253C2cC3CB5e64360875B65382Ea450464", - "txHash": "0xd1f74157d76b3694ca60a05ac4e4e05a32ec1f313de8ae6a84f9bbaf8ebccf8a", - "kind": "transparent" - }, - { - "address": "0xC5318caf8570B9433d1E8f7B6b9f2f405e6f610A", - "txHash": "0xc5a666b75d2e1fbc6b8fee7de36775a163c5d5be8d7ba065d494d37718ef9fa6", - "kind": "transparent" - }, - { - "address": "0xAC53304a9962D10Db474a437b3288a06313d173d", - "txHash": "0x7ee5d883885789c148e7e9fd6c399426a1c97db032e2d51f70609bff87f3996e", - "kind": "transparent" - }, - { - "address": "0x7fc2c7c9789C1887edfcbf55a23f657b10361DeF", - "txHash": "0xa4b55877ed3c5797b03488e4e00ce1b9c191e6a4e31a62c1602fc8e358f1d0b0", - "kind": "transparent" - }, - { - "address": "0xFC2fad28dA5F67fBe426128CAe73dcfBC36b6181", - "txHash": "0x248d9dfd0d2a4d486d00f8c6870716437cd11fbceac04ad5b279d4045121f667", - "kind": "transparent" - }, - { - "address": "0x105DEaa46e65cfd2062d92E8D60301a9c306B883", - "txHash": "0x68111bbce0d864beb5689ae1eacfdf9ceb26489a1706dff8d9122e2b82a0d0f8", - "kind": "transparent" - }, - { - "address": "0xcDC2858Ef06B21D2c18152881cac98b873D39E12", - "txHash": "0x72c0b55c252951df05505820ee9e785e5f4b69ff509586a5d3222c4110cb3c1d", - "kind": "transparent" - }, - { - "address": "0xfB85C721f431FF9B49f95b623932963c59f2E150", - "txHash": "0x38d5d295b4df829806c3f66eda4379b581b35d607dd7b38a2abd475f6a6134dc", - "kind": "transparent" - }, - { - "address": "0x5C1fc0cd1904430261013d70341bB8Ef8E7Cc524", - "txHash": "0x1366d2989305a47a7ece397b451f7027dedbe0a4d6fae478c48cd21ab86a5d87", - "kind": "transparent" - }, - { - "address": "0xA8386DB9b494646FA7651B9b11144F1Ed17B10e2", - "txHash": "0x3e8f1a7160a435cf45fe0cf07120ee31c3a4ba6556443e821680fae8b680ab07", - "kind": "transparent" - }, - { - "address": "0xED2FF568ca87a2520AB78d262F58119f093ba862", - "txHash": "0x249cf32d55192b479e49ac52f7dd1d4366a4d11ff685bde5636d3ce713ed7155", - "kind": "transparent" - }, - { - "address": "0x2A149E2ef2d9F511fEf54ecb219d4d7321ca658B", - "txHash": "0x7e85c645788ec2cbb1de60f184faf1eb37d3d7613b4e946eeb71b9b4ce2636a1", - "kind": "transparent" - }, - { - "address": "0x0bF5a47A54325B169e2c333c95B43115e32996C7", - "txHash": "0x97b7f00dff337d0527cd22942bad2a06bff82aea082c9ee33854f544e6a6117d", - "kind": "transparent" - }, - { - "address": "0xD5A6D31c797DfE81fc97A409E8FF9FE1e7f1cCe1", - "txHash": "0x08aad733af9f35a69dfde1840ab6cc10e805180b5737239489c3bb971eb505f5", - "kind": "transparent" - }, - { - "address": "0x5B1265b5859d31725FE9B9F8fD7D58c7b20c615e", - "txHash": "0x12579b15a47266f2484087f00c57819a58b5cb5dc0ccfeddb4f7351182cda3db", - "kind": "transparent" - }, - { - "address": "0xfAFDf00dF8289A915EEd53Fb4966f74b91E48340", - "txHash": "0x5f5ca9ead432b2075a787e2ba033c09cb0a42a59c483618a1c9060ab05b9293b", - "kind": "transparent" - }, - { - "address": "0xE5c683277474e488C625942C74E757D16a2fb891", - "txHash": "0x42f45bfc580c07cf2ca946ec0a67676ed8afbf7a6a97d716ce47ecc776695b67", - "kind": "transparent" - }, - { - "address": "0xA02456d734C94a20cE6a24fcD5148673D0695c60", - "txHash": "0xa8fe94689f832587226fe471b26d9b70afc1b38493c0a178be8139798b847d35", - "kind": "transparent" - }, - { - "address": "0x940d197eF772de318bB56417028e7477aAD98f9a", - "txHash": "0x85cc995c769459b0823f83906bff298a7f06ecb111926ebe6876c0587f3c724a", - "kind": "transparent" - }, - { - "address": "0xAefd7A67026faD58Cc68a2344b5a41555195bb56", - "txHash": "0x5c0a35477af0c1e6e50ab6fe1ebbfcd7b7cf47eeaaa420143cb5744855b38d97", - "kind": "transparent" - }, - { - "address": "0x243ED8e38c0cb19B63bb783399f114cD75b93022", - "txHash": "0x4e72f3d2ff3ffbf74a779def993371b2913fd2e139e53a66262a03c935f0b609", - "kind": "transparent" - }, - { - "address": "0xac4e9d9c524E768c3714048841671A2575C82321", - "txHash": "0x3abad4902af88e267706e281a8b3b93fe00ed95243cfd3b68cee1342d6b1e379", - "kind": "transparent" - }, - { - "address": "0xA15fb8C9b9Fdb4CF824041702f9278e62411B91C", - "txHash": "0xb4acdd76d090d95fec5079521b7709d785e823c7aa3825192637cdbfdad00fd5", - "kind": "transparent" - }, - { - "address": "0x77db5Ea2E17dEbbE78699e30c600513694358e99", - "txHash": "0x092eecf3d6ac90d5c09e538524e69b328c13526a199f4e66494fa7307346c1b5", - "kind": "transparent" - }, - { - "address": "0x3E1DC3ee4146792a173274492AE40eD8b30b7e9E", - "txHash": "0xbada31935ca5a3e74cc490b5a3529b8988ca0c23c2fba7240e428cac19cf26bf", - "kind": "transparent" - }, - { - "address": "0x470902bea0979556E440C4432284Fa4ccE7495EC", - "txHash": "0x2bba72446a6e9f317452275a65ad47ce8745a7902f25c882dbd9bf1dccffbe93", - "kind": "transparent" - }, - { - "address": "0xec69ae11714eA9518E0e453Ce5Ba672f0b1C102a", - "txHash": "0x416b075e68762b91d7de47c08508feca695ed0993456ceecd2176dbde2923226", - "kind": "transparent" - }, - { - "address": "0x57f0907169Eb51b523652E35D05e423298A7d7c6", - "txHash": "0x82ec3900ea38e9626bac605992d35433080fbd7874db2e254a53cab090a94f18", - "kind": "transparent" - }, - { - "address": "0x4E7B51D5F44501f60FF9665D126C2376Fe376898", - "txHash": "0x92f73106e122d3c63a64c572cab279ac125af1180997e8fb62ca5a8831a05013", - "kind": "transparent" - }, - { - "address": "0x80b35aBE3c76FE7b470ECED53Ef6a2DAd2f09CFB", - "txHash": "0xe03abc94663fb81438b1d323f0666115a99fa2a5f03f04067104d0b2fba17bd4", - "kind": "transparent" - }, - { - "address": "0x24623D32ae66D48260c404267aeD7b097040F200", - "txHash": "0xcd84722e3e3e661320f4215ce37e27af240b00fb9476ab71950440d954447dd9", - "kind": "transparent" - }, - { - "address": "0x763458df5F100Af42f9e08f601a20C98Aa7Ea3e1", - "txHash": "0x7a08948fc708f7618a6acd4fa43375f578f4992de365e63f10a27b310e0f58d1", - "kind": "transparent" - }, - { - "address": "0xD9fe458bb808a36933C46EF1B70995a7350e4CaE", - "txHash": "0x713b2fa1e359d2811014d23d17cc0bb1624e182ad113e49337ace7a3daaa1de4", - "kind": "transparent" - }, - { - "address": "0x149A88f67CE43334e35Bbd515F60091c483726eF", - "txHash": "0x77714029b7d9ee82f468cc2fb88571c0046ec91253c3c6f6d8438a90a49a550e", - "kind": "transparent" - }, - { - "address": "0xDE2B66AB18aFA89fEdC64C8521975CFa42C8502c", - "txHash": "0xb4f27323704d9f269bae8b6fa130bb2b291c1c7fdc35b806a40cb2877ec98e42", - "kind": "transparent" - }, - { - "address": "0xa01193B2D277c0046262DB1FdB991B6Ca8Dad2C5", - "txHash": "0x839da53d9112b8024e55db8618bfe7184ad9ca1b66015a57a8181978a8cb402c", - "kind": "transparent" - }, - { - "address": "0x798795C60E271e9597f6F6eBF9911aC0f8F876f6", - "txHash": "0x9762127eaf4a0dfefe24cefad92e44a7ea21bfabacb0598727cf89ceb004667a", - "kind": "transparent" - }, - { - "address": "0x7D47A9e3b7eb44A2517A0cAB168801d9658cbBE2", - "txHash": "0x9bc4bf4d95bb56d7be13ac86df376f05bba976911317d946167d1d2f6a488095", - "kind": "transparent" - }, - { - "address": "0xc33734c3dA40BB419c7a81eCCD0197ac1932B0c6", - "txHash": "0x612dc8730b185d491b9350ff7f69e06068c229d34dd71f6f069dce7c947e332b", - "kind": "transparent" - }, - { - "address": "0xaD466dE0d9aC528C48Be237cE6E4b7dA84a2fbE9", - "txHash": "0x03d5fba7b802cd0afd6d34680579550974f2aedda2586f3d24bc60d7d73c6aac", - "kind": "transparent" - }, - { - "address": "0x3b053B4c32d850a803f10098f0204AEeD87f7eF1", - "txHash": "0x3b451f6c86d7c896eaa0101908068d2817f2c6ff4725d2e139f1355e622af44e", - "kind": "transparent" - }, - { - "address": "0x41e106c8d858F9b4d6aD856ef3709A880381658A", - "txHash": "0xbe58a2ecd36e3b38b87e7b3ab8ed74cca1159bdea25f2cec4a8b0066cca42ef3", - "kind": "transparent" - }, - { - "address": "0xA6227d410FcD544323018cbfeD0d70E28a600944", - "txHash": "0x01efe727f6bc93fe83e10e2e17d7c3e198e3fab30ca5595d08c156f3e2288144", - "kind": "transparent" - }, - { - "address": "0x6313D86340A337732C5350472b0AaE21702e11fa", - "txHash": "0x3771cf6b6ab3709724e49b6d7ec6d0feb71ce3783586018f145f7ed028de015a", - "kind": "transparent" - }, - { - "address": "0xA6916CD0b5BD1C861D6Bb4D1D6129dA656cEc15e", - "txHash": "0x57c6a665ba3c3960dea2997d0de127ad7ca3cf5a47a047e96d5b3154a6600b2b", - "kind": "transparent" - }, - { - "address": "0xADA16654667a74cf2988F2e38371F5f2d82E5F24", - "txHash": "0x637790de369f85b382f566bfc28724fd2f9220db9cea980c4aaf905c809fe9f6", - "kind": "transparent" - }, - { - "address": "0x4D20D1eFeE3288ba9aC0DA6AF28d50380d34d873", - "txHash": "0x617c6a3049c5646f7732105f926a1fe50d83de835badaed87d644990d995e491", - "kind": "transparent" - }, - { - "address": "0x6Ec31b5863a195225c9635e1B497B6d0F2558772", - "txHash": "0x02f2ceb21b5fbf834aa0609f358e71a1c457c909e7fcd1b21b8f9837a019a44d", - "kind": "transparent" - }, - { - "address": "0x3099d1A21122A7da36BFECd46c118295ef34F6D7", - "txHash": "0x4aae75ba6cc87128f72ea416bb1f2f0ef745e87a8316bf86984bf3741baa8aa2", - "kind": "transparent" - }, - { - "address": "0xDF1Ac46c5767d50F5105b7e80fA74EE0c4D682a8", - "txHash": "0x149fc8e718af3a38173a8aba73375ba7d8a72cfae56e13216b7829b3b62c3838", - "kind": "transparent" - }, - { - "address": "0xF657823E9bfCfD9170F24A98e0e2f50375c6e46a", - "txHash": "0x171811962736356eebfaada14cdfc18a5986254fbadfd016f2b42b2c3cfff839", - "kind": "transparent" - }, - { - "address": "0x278AeCb7352BA343eEd64BE5b3B6cb8ea8F13a5E", - "txHash": "0xa057490298698535734d1cf1bd5ea1f8d78541f4275fb46e8efb264e1b5152e6", - "kind": "transparent" - }, - { - "address": "0x5023C255F4dF08F435de346a8cf9B951aE1C85B6", - "txHash": "0x3c246fd6ddf4c03789119192ec4b607551243ec91bcd5677070871a763000044", - "kind": "transparent" - }, - { - "address": "0x30799b99A92226Dd113be8b917B570E3b4C7fe94", - "txHash": "0xf2f13298a966dd8c78d5f760f9c1db58401ac8c6dd73f56e8b1df61426392112", - "kind": "transparent" - }, - { - "address": "0x31739f8a8BdC16b972D84507159F714675B0278D", - "txHash": "0xf5a8660a68f8870d47651b6f357d58110ae75d237a0e9947dacf4014bcdfb6e9", - "kind": "transparent" - }, - { - "address": "0xE5e86cc905C2936749007ddea4DF5f70a91724FE", - "txHash": "0x31d07703db1068be2e948294d7f32e9ef4a25b6eab50a4969400785ee1ea8999", - "kind": "transparent" - }, - { - "address": "0xdeD3d549Eb0938C833cDb5e9146CFBa750bD7aA1", - "txHash": "0xa21b771c50ff192ce05aba4dcd2b8e458a30ef7c6c10ee7c5f9d004db20322f3", - "kind": "transparent" - }, - { - "address": "0xfaD5e3C1A383989BdA996f8B8b4b3C137da68152", - "txHash": "0x1a729eb4006d529d8e815f1b30960779975f31c9f821579f1d92d762111ba3b2", - "kind": "transparent" - }, - { - "address": "0xB02a233da3f04336e47e13370D2CAe432DF8eA4A", - "txHash": "0xb536790c9129d0bd10fcd496183a22093f49b22cc808213b9ab4d2090c35174d", - "kind": "transparent" - }, - { - "address": "0xbeE8B084603e0E0840Eb43C4329dB47A5ed9eE01", - "txHash": "0xcc07bd728c9531a1e841ab1f5e18d49f4ce102d0025e3bea0d160ffc967e201e", - "kind": "transparent" - }, - { - "address": "0x59Aa82f76F1878abDa75DE6FA6563Df29E8B5BB5", - "txHash": "0x321cb4e7f2c2e4be335934e74b6069533ff734202c751729d774dbce644fdc94", - "kind": "transparent" - }, - { - "address": "0x2f763457975BD267479aF79BF6bD3b9D5DE625F0", - "txHash": "0x5d967983b47ddf3519cab0cbe942488064253eaf1204848dc93fe9eb82570339", - "kind": "transparent" - }, - { - "address": "0xb0516a412772fcf22D30A049fA9e26ccaaD05919", - "txHash": "0x5f097222e86b1278af19441bb28ac6652264aabc4a2028f7e64db623685bc01a", - "kind": "transparent" - }, - { - "address": "0x32952b0DAdF9e7CE1C14C153709064e81097588D", - "txHash": "0xd3e3995408b8529bfcc74c05f1db633d7151f840b8d3cca001423deacf313e48", - "kind": "transparent" - }, - { - "address": "0xbC734760175823bb16A72fa95Ca8957f36E99a3e", - "txHash": "0xd2125d1f0980bd9953de9e3904397e27b12d61a8c8948bb40091d4a2bfb5c862", - "kind": "transparent" - }, - { - "address": "0x5caE1385A7B2711c69C0FC806F595c3aa73dD917", - "txHash": "0x716fa3d7a1a879f30579cde1c641a537d4933806b17de129a654bfcc87fa5802", - "kind": "transparent" - }, - { - "address": "0x92F855A0A8cC8639c03bf165999E0a687Db2a7ea", - "txHash": "0x527ff4045f2d95ef5a9830075df8423e0141dc12f32c5ea28410c620ab00a3c2", - "kind": "transparent" - }, - { - "address": "0x596c9f78DB7803AcC3eFC48570C20Aae0c038D79", - "txHash": "0xd31b47913425360b157e418d9268d819111e7522372dab3aa7b5e43b9e605cbf", - "kind": "transparent" - }, - { - "address": "0xbb4B5aEcCFe4081a31F360CD02511b5434e90a8e", - "txHash": "0x9ce204d31439a9e6f6eae08d686c602b5dfb3ff7890e5ed089edcfccbcef01b9", - "kind": "transparent" - }, - { - "address": "0xAbB9Cc40770A9b8290B5dAeCaEeae0Fafc08cb01", - "txHash": "0x64aaf690b00e78fe6dd8316f48a80cadba63ce2f8f86f7bfa6b78e5dbc67ef96", - "kind": "transparent" - }, - { - "address": "0xc37c403dD63C455ca738E5C596Eb30C0F9beA44b", - "txHash": "0x814e2ca1f4628a8585737336ac7f88b2c29b1881777795f56e1a2f1184631980", - "kind": "transparent" - }, - { - "address": "0xA5633Cb0189A7e07b6b238ba67c5356708628068", - "txHash": "0xed9023c19f170f874cf894f398f68711036428eeda70f34941f84e2eec719930", - "kind": "transparent" - }, - { - "address": "0x021B763a3477068AB26e9D6AE040EC7a453f2714", - "txHash": "0x593755fbed5d9f488f29c9024100113ff5bd4265ca79d8a65905f0fd820f7fdc", - "kind": "transparent" - }, - { - "address": "0x795CAE1611456B6bd98c19eABbaAfe5259c0541c", - "txHash": "0x13db92c5a44cb9b1005714c573d3758789ad3660a72eedfad339db18c8ea492d", - "kind": "transparent" - }, - { - "address": "0xe45c6e34109D303c677F12D86fdfe2e5C172d2a3", - "txHash": "0x14adf10e75cdcd684540b8b46da5766e79846882ea783529217eeb265bf4a8d0", - "kind": "transparent" - }, - { - "address": "0x09BCe1f27f98E102d1632923022a748269E0ffe3", - "txHash": "0x57903a0ae3efc946682621497c40e91fd7a45c6064d300e1dd48c581e860b3d7", - "kind": "transparent" - }, - { - "address": "0x179cF5C4927e5c9D9A32D84e3942fFbbB09A6B16", - "txHash": "0x8ce9a48220dfc6e9f43daf62fc15b088fee7f6841f26a46e28611be177b1e7b3", - "kind": "transparent" - }, - { - "address": "0xB0222388edd4206CA110C3C20176eC6298Ff7E67", - "txHash": "0x912992907827997f47a3d9d4c3528dd2da1239f564bc041836b8ec6f5ce64e00", - "kind": "transparent" - }, - { - "address": "0x1555eea53aacE9b6B712E1a3Ade1350511bd0584", - "txHash": "0x253b6edf52e4d078fc059c1b19b37a279d13182d2621dedb684853d248dfc68c", - "kind": "transparent" - }, - { - "address": "0xE1e7b16B8265523Be96eD049F5850362736B0B67", - "txHash": "0x74a734f4f4fea4f8f54f3530f5cd208819072d8ebdd4d815a03effc0c64adeea", - "kind": "transparent" - }, - { - "address": "0x7D63942aa06DB6317f4D170A0872A4d8FC729b48", - "txHash": "0x2cb2f81142d4d84010978f1e28965b38b3634bf163960bc9a0c7a4101ac6d4f9", - "kind": "transparent" - }, - { - "address": "0x74bcDdaEC92548c064915778Dc95D347BE2DaE5B", - "txHash": "0xbdbc87a02f83917fd7bfa9af8eecb08e848f60c14ebeee3be723a1a572cb1392", - "kind": "transparent" - }, - { - "address": "0xAF72923e4dFB5ACDA3a91DCD0A2fbEB37369dCc1", - "txHash": "0x60e409e6773161098230297a75f3b6acc33af812a22307a3ba3a2ede84d02efe", - "kind": "transparent" - }, - { - "address": "0x81641AE3b55c49B39126d096c82E360B37588fa5", - "txHash": "0x450437d22465814bfc5d7ec1da6c0bc80998cc7efbaa4078ff9e50e7c078df62", - "kind": "transparent" - }, - { - "address": "0xC0683013168fee54b5c6163e1a57646f9ADf0261", - "txHash": "0xffc341941e24b7ffbcd2755fcc9c942d0fd897c76024784237aab9a9829d588e", - "kind": "transparent" - }, - { - "address": "0x0468FE4CAd3c867A0125970432962A54146329A8", - "txHash": "0xa7756fe00ff7724abf8dcb285f1e9a7af96787fb28477d1aa88047390be1ed22", - "kind": "transparent" - }, - { - "address": "0xbda76D58A4d31f1becD1755E442a122C557Cb8b3", - "txHash": "0xbca77415d09287a828b135f3841de2165709dc7518aa4fd39dcaacdeb396d789", - "kind": "transparent" - }, - { - "address": "0xa30afffe21c6FE433e9b620ddd82934782D417B2", - "txHash": "0xd4a00269c0a7986170d9856f6d68bec750c80c38c05933d4f936a822a33fb8c6", - "kind": "transparent" - }, - { - "address": "0x28898561331f93c35376Be431f2D4c45897e0C33", - "txHash": "0xb6e8418fcd566b156eb3df4bf3bc4b68b8c2b5d2aa65c0586f4cf107af2bee08", - "kind": "transparent" - }, - { - "address": "0x86d372ede1B6e17BF931663f96E23a6661D0dBEe", - "txHash": "0xfc50fc3a77fa398328069b725d9d3f5d512bd1574b00bc2bb1013aae0d39b63b", - "kind": "transparent" - }, - { - "address": "0x2c0E8280Ae4282BdD9Ed35caeF6f9f9DF6E2Cb4F", - "txHash": "0x2606fc323293fbfffd6aa3fcb72754ab1add3e4be068b21ed3898143aeeb7257", - "kind": "transparent" - }, - { - "address": "0xDD48C6779e192a5bE2d5e6db4a62664Bb810b844", - "txHash": "0x4c9afaed65d07471b82530f61a1ba5457741e8735ee43dbf77b1e96097cbb581", - "kind": "transparent" - }, - { - "address": "0x4e0ba9Fd59Fec306627a1ad468b878e55Ade8e37", - "txHash": "0xe8fbcd2bcbde5679e8d9e11a4f605feab900ccaa1887c692c9b50e76628317fc", - "kind": "transparent" - }, - { - "address": "0xA77a136a1fa2D20B6012705b907f90a92023F8a3", - "txHash": "0xe2850e24626f6aa7642b37051575d8ca4faa4dfec70052d4e18e160c20a947b6", - "kind": "transparent" - }, - { - "address": "0x54F0087a0C7025a4ED92f916eB9bfD198d3e2DEA", - "txHash": "0xaa688a4e7f743bf87cbf213d16b07cc21f1a4b3feee40777b5d36290305349a6", - "kind": "transparent" - }, - { - "address": "0x6c3D73921eb9D6FB61953e63Aef542Cd2C4adBb2", - "txHash": "0x0494bec701bc111edd5747271be829a6931daf47c952d27da84caa31cba223c9", - "kind": "transparent" - }, - { - "address": "0xdd3DF924838B9491943Eeaf078b87d3F4c741770", - "txHash": "0xbf56cb291809b32601a27b231ad227407cae5746fd94f4eb3083f2a06b205480", - "kind": "transparent" - }, - { - "address": "0xEb9772567A73Ac2fC881D6f45C4699808dc95371", - "txHash": "0xe85a3a11c3223333503239644dd8f1ce10f66cf058f9f1c35b983d10e8c7ada9", - "kind": "transparent" - }, - { - "address": "0x0cd79d59E50e0fBb9E2cFe2DFb586d5b607334c8", - "txHash": "0xe1f602767303af5a38f65148f7b3ca5141945b397a01e0136fce467126d6ec34", - "kind": "transparent" - }, - { - "address": "0x6E10AF94FC60c412A263b95b7774aaa8283eA8C0", - "txHash": "0x59993a64b368d5354570f884be1a466fc5c96067a0bca1b77eee49ef4c3679e5", - "kind": "transparent" - }, - { - "address": "0xB606C96F78c2Ef51eFf278Ec6dE92f0fF6C37C1e", - "txHash": "0xe0cbb3d0f7cacca2fe1fe344fa3697a821cf0875592c01e5ccdf74fc75d2f4cb", - "kind": "transparent" - }, - { - "address": "0x179F28740d0116AB8dFD91c077040D3EB58c5e78", - "txHash": "0xf0280ab28f082a2281b1cb45ec6e9bc239eb66b22d81a91a7afa98f049053d07", - "kind": "transparent" - }, - { - "address": "0xC169DDbeD54dA6f8a42AA09fE3bB4281c4F565f8", - "txHash": "0xe401422eec3bbd9ab5a2f62893a40b696894a159dd7b4bb457647e2405acbf88", - "kind": "transparent" - }, - { - "address": "0xAd73Ab69eF8B6713c26FB753DA831c37AA815433", - "txHash": "0xf53b0e403dffc9e4bbf86b3af17b1ad8067cf778b89abe612515e45a984b173c", - "kind": "transparent" - }, - { - "address": "0x69Ad8d2A45c02E57056305E0F732bc412B8E3153", - "txHash": "0x86524c86db7f7e2818788c299953a5a1b00633dacbd244d64f8625b68fe8d205", - "kind": "transparent" - }, - { - "address": "0x84CCdC63c042ebA4123B2dd0CEe26ce502a63398", - "txHash": "0x66e0550cf53527cf52f6f7e5e68dde697edfe9a7233a0acd0ca58338985ec843", - "kind": "transparent" - }, - { - "address": "0x429D3b99Be46A764360124f19D2c7FC697B2ADa9", - "txHash": "0x6c3da1ad16cb2c45c0b32e91c395a43c25e8fbb8298943479b1e05330fac5bdd", - "kind": "transparent" - }, - { - "address": "0x80656aFb807B3D8e571d97a955A2B643429bb301", - "txHash": "0x43eb3d909fa8d5115ed43c49956c8993ba67e789885cb0a674cf93fa17873119", - "kind": "transparent" - }, - { - "address": "0x1dD691e0C5657ecB49682339a2803959B9FE77dA", - "txHash": "0x9d1e5df2c83b7878492a1c9193ed35f1f943047ca618d787f49ca1ed66ce6a2b", - "kind": "transparent" - }, - { - "address": "0x88955B267276a193087bF3E6C0EEbbD51C6F98eF", - "txHash": "0x359c4a04710e64910289cd5e5d68a4f6323555fea0a8ac5d53a6237803316d83", - "kind": "transparent" - }, - { - "address": "0x65b9C16e382AB4a8fdD913f3f99ec1B1ad11951D", - "txHash": "0xab1b885520318749f4faf71d5dbb7e4782c293a832d8496cbe4375ba5dd29526", - "kind": "transparent" - }, - { - "address": "0x742F7A4B0901DAFD289CBF0fb5043dF4430B4E21", - "txHash": "0xdcea44c0ecef5990eef4f0e28b6239643c9c42c4de9d56fc69eafa75b430bf94", - "kind": "transparent" - }, - { - "address": "0xA0f88719Af1a249EE42ef8d2ab89649B4bc3D573", - "txHash": "0x1ac78455102a370731e2208f49c9369b65ab2851c65aae8eefe779f1642e1fe2", - "kind": "transparent" - }, - { - "address": "0x7b0b96C1b27e774E7EE7DAC9F3489EAfFa3bE93b", - "txHash": "0xc29ff53dead95b9508878321dac6bb9d1694f0b652d9e8e6da7c8552efbde2c3", - "kind": "transparent" - }, - { - "address": "0x8D69aF07bcACA4b7Ae6f31C253594BeabDAA7073", - "txHash": "0x4408dd5eb063aa6d1256fd64e1e5df9b064769d24f17dd4dc432f8ad97b2c38b", - "kind": "transparent" - }, - { - "address": "0xd28Cb5df472E605c63401BA347fa5a3381Dc7301", - "txHash": "0x0c23a2999b5a4786119408f4414e72f29686c2a0566b5fc258cb48c5936e039e", - "kind": "transparent" - }, - { - "address": "0x3D712aF6347ecb8108fFae98BFe08EeC09825861", - "txHash": "0x1edc795fddf997a011c06cb595513b1d89db3b54ba78fd64710e7401c27d94d0", - "kind": "transparent" - }, - { - "address": "0x50657C318a5c5fbccD767caf7F652bfA1aEA15e7", - "txHash": "0x0f88c79dfb1d6145d6a9d310b0105635af5aed7615bac3072f571b83b2edb24c", - "kind": "transparent" - }, - { - "address": "0xE82567c51fF364ed9798EFE5F424b58ec8fF005f", - "txHash": "0xb072ad536f2a884df8ce5cded7a22873595153284913cc467b832191999a5c15", - "kind": "transparent" - }, - { - "address": "0xa072153bAE371e8F3455BC834B5911368EB0FD69", - "txHash": "0x7123c6a62fee9310d37c8873bb4e9f7e119bb10aa0f06635f580c0ac704727b8", - "kind": "transparent" - }, - { - "address": "0x8DCA9E3b4220022d310Ce0F2e1F814F6dD8A6929", - "txHash": "0xe3e3869274a3de180a89a60c8fe7a0bf0110b6011c981aafd505fac03d0af5d3", - "kind": "transparent" - }, - { - "address": "0x7885E4b081a82CCE3820ca6B4F93103Cead2aA89", - "txHash": "0x56e77758478de29b259f1d1c7d8a33d0fe72ceb3ea6a90c4d1a6c6bbc8d7543e", - "kind": "transparent" - }, - { - "address": "0xE61fFEb67d3DfE643e622c308DD014B798055061", - "txHash": "0xde971b06614a6a1071432a2c59596409c594aba028af307045fe3390cf69ab6a", - "kind": "transparent" - }, - { - "address": "0x25e7e0Bc216D23c5C9F741EbeD5aD9D7da72a864", - "txHash": "0x89263e1a6505a0ea73108c964334c88946620585f1b53c2791da60d5768f4585", - "kind": "transparent" - }, - { - "address": "0xa1637ad50596a2Ab6AF9fF662cD557CC39e11cB5", - "txHash": "0x8b19bb183a88fc6ec8356a4e563b62b566c5b85032915b063bb8956135908385", - "kind": "transparent" - }, - { - "address": "0xe3b22dc53Ef39F687B1f924E641a093D5AA760eb", - "txHash": "0x0dccd67eedd413b8e9817e66b28fd3ec59b7e38f78b7c27df0347d8cbe7589fc", - "kind": "transparent" - }, - { - "address": "0xC4D9b5A4E9AaA08a4FC48d5F1458b070F5587988", - "txHash": "0x7ed6b2e9675e9a2b188203524fbf694cbceecea461dc99f04048e19113688403", - "kind": "transparent" - }, - { - "address": "0x3F1888A11F4D49B52AA52811fcAb31EaA3d138a0", - "txHash": "0xdcff2b2d438da4ca4efc0f78d9590399802e307c899f4dc9dda1fca1b03048ea", - "kind": "transparent" - }, - { - "address": "0x12A4507ab29Ee217FE6C42a728DdeB984b414300", - "txHash": "0x1cbf70557716fe12e4bdf360815c3b2f1e6dd8a8c1b6a0631ddb6ae44f448f88", - "kind": "transparent" - }, - { - "address": "0x8Fed85fa99bA7E4D299154094edEA5f519E9A979", - "txHash": "0xfdaa3b0e7813989c3f9a0bf138c07c956da1be1e2dfe59013a1de8303effa12f", - "kind": "transparent" - }, - { - "address": "0xa02393bEf919efFE46c42b0b249a679A9803bddb", - "txHash": "0x6ff89a3ebdb69aced2e61f7d5f05c726eec907a267132cf52b9859137bface78", - "kind": "transparent" - }, - { - "address": "0x5ccAB338f48a1e09Ac8EDEf40f7cC3D689EC9e1A", - "txHash": "0xd99eb1be972023aeac3da7ca12ee802892df22b75f8d095e6dc56b01ff0d8b0a", - "kind": "transparent" - }, - { - "address": "0x132fD33aE527533eAf549E35912575012772b55c", - "txHash": "0xee0a5a0428dce87ed59d92a020854e636ae962d9a693437257d8fdf4ee742ac8", - "kind": "transparent" - }, - { - "address": "0xb5796DEd10fc1bFa5659a89607d0A3daaB178792", - "txHash": "0x6be5c584be1aa177daf155beb9960f563faf0db6f53ae0274eea43989678d90a", - "kind": "transparent" - }, - { - "address": "0xe15eB50498A7264C9A63720e8fDD7021dFc3FE67", - "txHash": "0x9d2385a22f30fa4d7fb1bce23625afcc463077f5273d3c89969af32ff4daf273", - "kind": "transparent" - }, - { - "address": "0x67b6C5FF0d4D59575dc14596E94553eF89A61CE1", - "txHash": "0xc10496c8bc1e1f3b24e9db73eae85a5d913f344d360f23945cee70bcf33500c3", - "kind": "transparent" - }, - { - "address": "0xcDC70c75D361B7849abb326B96aECD8b4e8987D9", - "txHash": "0x95f14ef6202031845efc57295a22a4aa6e90780ba3b77a475ed1184576d64632", - "kind": "transparent" - }, - { - "address": "0x65b0F91F1098bECF56ADd147B9b34de80B5D1177", - "txHash": "0xb1305734ea994b4849e4796059490cd885ff530c0652892d65d259ae89694f49", - "kind": "transparent" - } - ], - "impls": { - "59cdcb1b80b5cf919106299d12b46155420aa9a79eae333f3f94218d0c8c28a2": { - "address": "0xd3AE2f2a59BD15e27178e11AD54386284eCe58c8", - "txHash": "0x822def4963216c7a89c5bd6323117013ac1d209815fd03b6b54bca845b0221fd", - "layout": { - "solcVersion": "0.8.17", - "storage": [ - { - "label": "_initialized", - "offset": 0, - "slot": "0", - "type": "t_uint8", - "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", - "retypedFrom": "bool" - }, - { - "label": "_initializing", - "offset": 1, - "slot": "0", - "type": "t_bool", - "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" - }, - { - "label": "__gap", - "offset": 0, - "slot": "1", - "type": "t_array(t_uint256)50_storage", - "contract": "ContextUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" - }, - { - "label": "_owner", - "offset": 0, - "slot": "51", - "type": "t_address", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" - }, - { - "label": "__gap", - "offset": 0, - "slot": "52", - "type": "t_array(t_uint256)49_storage", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" - }, - { - "label": "_currentValidators", - "offset": 0, - "slot": "101", - "type": "t_array(t_address)dyn_storage", - "contract": "ValidatorSetHbbft", - "src": "contracts/ValidatorSetHbbft.sol:19" - }, - { - "label": "_pendingValidators", - "offset": 0, - "slot": "102", - "type": "t_array(t_address)dyn_storage", - "contract": "ValidatorSetHbbft", - "src": "contracts/ValidatorSetHbbft.sol:20" - }, - { - "label": "_previousValidators", - "offset": 0, - "slot": "103", - "type": "t_array(t_address)dyn_storage", - "contract": "ValidatorSetHbbft", - "src": "contracts/ValidatorSetHbbft.sol:21" - }, - { - "label": "_maliceReportedForBlock", - "offset": 0, - "slot": "104", - "type": "t_mapping(t_address,t_mapping(t_uint256,t_array(t_address)dyn_storage))", - "contract": "ValidatorSetHbbft", - "src": "contracts/ValidatorSetHbbft.sol:24" - }, - { - "label": "banCounter", - "offset": 0, - "slot": "105", - "type": "t_mapping(t_address,t_uint256)", - "contract": "ValidatorSetHbbft", - "src": "contracts/ValidatorSetHbbft.sol:28" - }, - { - "label": "bannedUntil", - "offset": 0, - "slot": "106", - "type": "t_mapping(t_address,t_uint256)", - "contract": "ValidatorSetHbbft", - "src": "contracts/ValidatorSetHbbft.sol:31" - }, - { - "label": "bannedDelegatorsUntil", - "offset": 0, - "slot": "107", - "type": "t_mapping(t_address,t_uint256)", - "contract": "ValidatorSetHbbft", - "src": "contracts/ValidatorSetHbbft.sol:35" - }, - { - "label": "banReason", - "offset": 0, - "slot": "108", - "type": "t_mapping(t_address,t_bytes32)", - "contract": "ValidatorSetHbbft", - "src": "contracts/ValidatorSetHbbft.sol:39" - }, - { - "label": "blockRewardContract", - "offset": 0, - "slot": "109", - "type": "t_address", - "contract": "ValidatorSetHbbft", - "src": "contracts/ValidatorSetHbbft.sol:42" - }, - { - "label": "isValidator", - "offset": 0, - "slot": "110", - "type": "t_mapping(t_address,t_bool)", - "contract": "ValidatorSetHbbft", - "src": "contracts/ValidatorSetHbbft.sol:46" - }, - { - "label": "isValidatorPrevious", - "offset": 0, - "slot": "111", - "type": "t_mapping(t_address,t_bool)", - "contract": "ValidatorSetHbbft", - "src": "contracts/ValidatorSetHbbft.sol:50" - }, - { - "label": "miningByStakingAddress", - "offset": 0, - "slot": "112", - "type": "t_mapping(t_address,t_address)", - "contract": "ValidatorSetHbbft", - "src": "contracts/ValidatorSetHbbft.sol:54" - }, - { - "label": "randomContract", - "offset": 0, - "slot": "113", - "type": "t_address", - "contract": "ValidatorSetHbbft", - "src": "contracts/ValidatorSetHbbft.sol:57" - }, - { - "label": "reportingCounter", - "offset": 0, - "slot": "114", - "type": "t_mapping(t_address,t_mapping(t_uint256,t_uint256))", - "contract": "ValidatorSetHbbft", - "src": "contracts/ValidatorSetHbbft.sol:62" - }, - { - "label": "reportingCounterTotal", - "offset": 0, - "slot": "115", - "type": "t_mapping(t_uint256,t_uint256)", - "contract": "ValidatorSetHbbft", - "src": "contracts/ValidatorSetHbbft.sol:67" - }, - { - "label": "stakingByMiningAddress", - "offset": 0, - "slot": "116", - "type": "t_mapping(t_address,t_address)", - "contract": "ValidatorSetHbbft", - "src": "contracts/ValidatorSetHbbft.sol:71" - }, - { - "label": "stakingContract", - "offset": 0, - "slot": "117", - "type": "t_contract(IStakingHbbft)10187", - "contract": "ValidatorSetHbbft", - "src": "contracts/ValidatorSetHbbft.sol:74" - }, - { - "label": "keyGenHistoryContract", - "offset": 0, - "slot": "118", - "type": "t_contract(IKeyGenHistory)9952", - "contract": "ValidatorSetHbbft", - "src": "contracts/ValidatorSetHbbft.sol:77" - }, - { - "label": "validatorCounter", - "offset": 0, - "slot": "119", - "type": "t_mapping(t_address,t_uint256)", - "contract": "ValidatorSetHbbft", - "src": "contracts/ValidatorSetHbbft.sol:80" - }, - { - "label": "validatorAvailableSinceLastWrite", - "offset": 0, - "slot": "120", - "type": "t_mapping(t_address,t_uint256)", - "contract": "ValidatorSetHbbft", - "src": "contracts/ValidatorSetHbbft.sol:83" - }, - { - "label": "validatorAvailableSince", - "offset": 0, - "slot": "121", - "type": "t_mapping(t_address,t_uint256)", - "contract": "ValidatorSetHbbft", - "src": "contracts/ValidatorSetHbbft.sol:91" - }, - { - "label": "maxValidators", - "offset": 0, - "slot": "122", - "type": "t_uint256", - "contract": "ValidatorSetHbbft", - "src": "contracts/ValidatorSetHbbft.sol:94" - }, - { - "label": "banDuration", - "offset": 0, - "slot": "123", - "type": "t_uint256", - "contract": "ValidatorSetHbbft", - "src": "contracts/ValidatorSetHbbft.sol:97" - }, - { - "label": "validatorInactivityThreshold", - "offset": 0, - "slot": "124", - "type": "t_uint256", - "contract": "ValidatorSetHbbft", - "src": "contracts/ValidatorSetHbbft.sol:100" - }, - { - "label": "_systemAddress", - "offset": 0, - "slot": "125", - "type": "t_address", - "contract": "ValidatorSetHbbftMock", - "src": "contracts/mockContracts/ValidatorSetHbbftMock.sol:6" - }, - { - "label": "_isFullHealth", - "offset": 20, - "slot": "125", - "type": "t_bool", - "contract": "ValidatorSetHbbftMock", - "src": "contracts/mockContracts/ValidatorSetHbbftMock.sol:7" - } - ], - "types": { - "t_address": { - "label": "address", - "numberOfBytes": "20" - }, - "t_array(t_address)dyn_storage": { - "label": "address[]", - "numberOfBytes": "32" - }, - "t_array(t_uint256)49_storage": { - "label": "uint256[49]", - "numberOfBytes": "1568" - }, - "t_array(t_uint256)50_storage": { - "label": "uint256[50]", - "numberOfBytes": "1600" - }, - "t_bool": { - "label": "bool", - "numberOfBytes": "1" - }, - "t_bytes32": { - "label": "bytes32", - "numberOfBytes": "32" - }, - "t_contract(IKeyGenHistory)9952": { - "label": "contract IKeyGenHistory", - "numberOfBytes": "20" - }, - "t_contract(IStakingHbbft)10187": { - "label": "contract IStakingHbbft", - "numberOfBytes": "20" - }, - "t_mapping(t_address,t_address)": { - "label": "mapping(address => address)", - "numberOfBytes": "32" - }, - "t_mapping(t_address,t_bool)": { - "label": "mapping(address => bool)", - "numberOfBytes": "32" - }, - "t_mapping(t_address,t_bytes32)": { - "label": "mapping(address => bytes32)", - "numberOfBytes": "32" - }, - "t_mapping(t_address,t_mapping(t_uint256,t_array(t_address)dyn_storage))": { - "label": "mapping(address => mapping(uint256 => address[]))", - "numberOfBytes": "32" - }, - "t_mapping(t_address,t_mapping(t_uint256,t_uint256))": { - "label": "mapping(address => mapping(uint256 => uint256))", - "numberOfBytes": "32" - }, - "t_mapping(t_address,t_uint256)": { - "label": "mapping(address => uint256)", - "numberOfBytes": "32" - }, - "t_mapping(t_uint256,t_array(t_address)dyn_storage)": { - "label": "mapping(uint256 => address[])", - "numberOfBytes": "32" - }, - "t_mapping(t_uint256,t_uint256)": { - "label": "mapping(uint256 => uint256)", - "numberOfBytes": "32" - }, - "t_uint256": { - "label": "uint256", - "numberOfBytes": "32" - }, - "t_uint8": { - "label": "uint8", - "numberOfBytes": "1" - } - } - } - }, - "dd70ac6db40ee4420821ca8c24efc4a83be5c578620e8ba229c227b8c8408908": { - "address": "0x8629b55d96cE3a8d1Edfa0612E4C74E5f45ADAC7", - "txHash": "0xdca0086ef15efc78dc01ca46969fb42a109dfbe90d08cbe9df559b7916e21c72", - "layout": { - "solcVersion": "0.8.17", - "storage": [ - { - "label": "_initialized", - "offset": 0, - "slot": "0", - "type": "t_uint8", - "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", - "retypedFrom": "bool" - }, - { - "label": "_initializing", - "offset": 1, - "slot": "0", - "type": "t_bool", - "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" - }, - { - "label": "__gap", - "offset": 0, - "slot": "1", - "type": "t_array(t_uint256)50_storage", - "contract": "ContextUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" - }, - { - "label": "_owner", - "offset": 0, - "slot": "51", - "type": "t_address", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" - }, - { - "label": "__gap", - "offset": 0, - "slot": "52", - "type": "t_array(t_uint256)49_storage", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" - }, - { - "label": "_epochsPoolGotRewardFor", - "offset": 0, - "slot": "101", - "type": "t_mapping(t_address,t_array(t_uint256)dyn_storage)", - "contract": "BlockRewardHbbftBase", - "src": "contracts/base/BlockRewardHbbftBase.sol:24" - }, - { - "label": "epochPoolNativeReward", - "offset": 0, - "slot": "102", - "type": "t_mapping(t_uint256,t_mapping(t_address,t_uint256))", - "contract": "BlockRewardHbbftBase", - "src": "contracts/base/BlockRewardHbbftBase.sol:28" - }, - { - "label": "nativeRewardUndistributed", - "offset": 0, - "slot": "103", - "type": "t_uint256", - "contract": "BlockRewardHbbftBase", - "src": "contracts/base/BlockRewardHbbftBase.sol:32" - }, - { - "label": "snapshotPoolTotalStakeAmount", - "offset": 0, - "slot": "104", - "type": "t_mapping(t_uint256,t_mapping(t_address,t_uint256))", - "contract": "BlockRewardHbbftBase", - "src": "contracts/base/BlockRewardHbbftBase.sol:36" - }, - { - "label": "snapshotPoolValidatorStakeAmount", - "offset": 0, - "slot": "105", - "type": "t_mapping(t_uint256,t_mapping(t_address,t_uint256))", - "contract": "BlockRewardHbbftBase", - "src": "contracts/base/BlockRewardHbbftBase.sol:41" - }, - { - "label": "validatorMinRewardPercent", - "offset": 0, - "slot": "106", - "type": "t_mapping(t_uint256,t_uint256)", - "contract": "BlockRewardHbbftBase", - "src": "contracts/base/BlockRewardHbbftBase.sol:49" - }, - { - "label": "deltaPot", - "offset": 0, - "slot": "107", - "type": "t_uint256", - "contract": "BlockRewardHbbftBase", - "src": "contracts/base/BlockRewardHbbftBase.sol:52" - }, - { - "label": "deltaPotPayoutFraction", - "offset": 0, - "slot": "108", - "type": "t_uint256", - "contract": "BlockRewardHbbftBase", - "src": "contracts/base/BlockRewardHbbftBase.sol:56" - }, - { - "label": "reinsertPot", - "offset": 0, - "slot": "109", - "type": "t_uint256", - "contract": "BlockRewardHbbftBase", - "src": "contracts/base/BlockRewardHbbftBase.sol:61" - }, - { - "label": "reinsertPotPayoutFraction", - "offset": 0, - "slot": "110", - "type": "t_uint256", - "contract": "BlockRewardHbbftBase", - "src": "contracts/base/BlockRewardHbbftBase.sol:65" - }, - { - "label": "validatorSetContract", - "offset": 0, - "slot": "111", - "type": "t_contract(IValidatorSetHbbft)2640", - "contract": "BlockRewardHbbftBase", - "src": "contracts/base/BlockRewardHbbftBase.sol:68" - }, - { - "label": "governancePotAddress", - "offset": 0, - "slot": "112", - "type": "t_address_payable", - "contract": "BlockRewardHbbftBase", - "src": "contracts/base/BlockRewardHbbftBase.sol:71" - }, - { - "label": "governancePotShareNominator", - "offset": 0, - "slot": "113", - "type": "t_uint256", - "contract": "BlockRewardHbbftBase", - "src": "contracts/base/BlockRewardHbbftBase.sol:75" - }, - { - "label": "governancePotShareDenominator", - "offset": 0, - "slot": "114", - "type": "t_uint256", - "contract": "BlockRewardHbbftBase", - "src": "contracts/base/BlockRewardHbbftBase.sol:79" - }, - { - "label": "__gap", - "offset": 0, - "slot": "115", - "type": "t_array(t_uint256)50_storage", - "contract": "BlockRewardHbbftBase", - "src": "contracts/base/BlockRewardHbbftBase.sol:676" - }, - { - "label": "_systemAddress", - "offset": 0, - "slot": "165", - "type": "t_address", - "contract": "BlockRewardHbbftMock", - "src": "contracts/mockContracts/BlockRewardHbbftMock.sol:6" - } - ], - "types": { - "t_address": { - "label": "address", - "numberOfBytes": "20" - }, - "t_address_payable": { - "label": "address payable", - "numberOfBytes": "20" - }, - "t_array(t_uint256)49_storage": { - "label": "uint256[49]", - "numberOfBytes": "1568" - }, - "t_array(t_uint256)50_storage": { - "label": "uint256[50]", - "numberOfBytes": "1600" - }, - "t_array(t_uint256)dyn_storage": { - "label": "uint256[]", - "numberOfBytes": "32" - }, - "t_bool": { - "label": "bool", - "numberOfBytes": "1" - }, - "t_contract(IValidatorSetHbbft)2640": { - "label": "contract IValidatorSetHbbft", - "numberOfBytes": "20" - }, - "t_mapping(t_address,t_array(t_uint256)dyn_storage)": { - "label": "mapping(address => uint256[])", - "numberOfBytes": "32" - }, - "t_mapping(t_address,t_uint256)": { - "label": "mapping(address => uint256)", - "numberOfBytes": "32" - }, - "t_mapping(t_uint256,t_mapping(t_address,t_uint256))": { - "label": "mapping(uint256 => mapping(address => uint256))", - "numberOfBytes": "32" - }, - "t_mapping(t_uint256,t_uint256)": { - "label": "mapping(uint256 => uint256)", - "numberOfBytes": "32" - }, - "t_uint256": { - "label": "uint256", - "numberOfBytes": "32" - }, - "t_uint8": { - "label": "uint8", - "numberOfBytes": "1" - } - } - } - }, - "23b40d0b03ac82f0d587ce95f82040e5852febd0f922c6733542ee6c268bd5b8": { - "address": "0xb67De1FB89F3f788d0D83fa4Bc9647D5376594c8", - "txHash": "0x79c8e13e8b0993dcbeab1953b5322dc205bab708cef9a76f2bc51d304d81d66e", - "layout": { - "solcVersion": "0.8.17", - "storage": [ - { - "label": "_initialized", - "offset": 0, - "slot": "0", - "type": "t_uint8", - "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", - "retypedFrom": "bool" - }, - { - "label": "_initializing", - "offset": 1, - "slot": "0", - "type": "t_bool", - "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" - }, - { - "label": "__gap", - "offset": 0, - "slot": "1", - "type": "t_array(t_uint256)50_storage", - "contract": "ContextUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" - }, - { - "label": "_owner", - "offset": 0, - "slot": "51", - "type": "t_address", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" - }, - { - "label": "__gap", - "offset": 0, - "slot": "52", - "type": "t_array(t_uint256)49_storage", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" - }, - { - "label": "deprecated1", - "offset": 0, - "slot": "101", - "type": "t_uint256", - "contract": "RandomHbbft", - "src": "contracts/RandomHbbft.sol:20" - }, - { - "label": "randomHistory", - "offset": 0, - "slot": "102", - "type": "t_mapping(t_uint256,t_uint256)", - "contract": "RandomHbbft", - "src": "contracts/RandomHbbft.sol:25" - }, - { - "label": "unhealthiness", - "offset": 0, - "slot": "103", - "type": "t_struct(BitMap)680_storage", - "contract": "RandomHbbft", - "src": "contracts/RandomHbbft.sol:27" - }, - { - "label": "validatorSetContract", - "offset": 0, - "slot": "104", - "type": "t_contract(IValidatorSetHbbft)16123", - "contract": "RandomHbbft", - "src": "contracts/RandomHbbft.sol:30" - } - ], - "types": { - "t_address": { - "label": "address", - "numberOfBytes": "20" - }, - "t_array(t_uint256)49_storage": { - "label": "uint256[49]", - "numberOfBytes": "1568" - }, - "t_array(t_uint256)50_storage": { - "label": "uint256[50]", - "numberOfBytes": "1600" - }, - "t_bool": { - "label": "bool", - "numberOfBytes": "1" - }, - "t_contract(IValidatorSetHbbft)16123": { - "label": "contract IValidatorSetHbbft", - "numberOfBytes": "20" - }, - "t_mapping(t_uint256,t_uint256)": { - "label": "mapping(uint256 => uint256)", - "numberOfBytes": "32" - }, - "t_struct(BitMap)680_storage": { - "label": "struct BitMapsUpgradeable.BitMap", - "members": [ - { - "label": "_data", - "type": "t_mapping(t_uint256,t_uint256)", - "offset": 0, - "slot": "0" - } - ], - "numberOfBytes": "32" - }, - "t_uint256": { - "label": "uint256", - "numberOfBytes": "32" - }, - "t_uint8": { - "label": "uint8", - "numberOfBytes": "1" - } - } - } - }, - "b8198bb0fb814533ab71bc71c57c97032ba272f19ec9eb61292965b15fd5b04b": { - "address": "0x29c59B380343361B390840AA90aD6f6CfCF255Ba", - "txHash": "0x82cc45ef19c81eb54588e54ca7f4d9044c45a0d6329be6f706d282758b440f82", - "layout": { - "solcVersion": "0.8.17", - "storage": [ - { - "label": "_initialized", - "offset": 0, - "slot": "0", - "type": "t_uint8", - "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", - "retypedFrom": "bool" - }, - { - "label": "_initializing", - "offset": 1, - "slot": "0", - "type": "t_bool", - "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" - }, - { - "label": "__gap", - "offset": 0, - "slot": "1", - "type": "t_array(t_uint256)50_storage", - "contract": "ContextUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" - }, - { - "label": "_owner", - "offset": 0, - "slot": "51", - "type": "t_address", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" - }, - { - "label": "__gap", - "offset": 0, - "slot": "52", - "type": "t_array(t_uint256)49_storage", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" - }, - { - "label": "_pools", - "offset": 0, - "slot": "101", - "type": "t_array(t_address)dyn_storage", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:17" - }, - { - "label": "_poolsInactive", - "offset": 0, - "slot": "102", - "type": "t_array(t_address)dyn_storage", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:18" - }, - { - "label": "_poolsToBeElected", - "offset": 0, - "slot": "103", - "type": "t_array(t_address)dyn_storage", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:19" - }, - { - "label": "_poolsToBeRemoved", - "offset": 0, - "slot": "104", - "type": "t_array(t_address)dyn_storage", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:20" - }, - { - "label": "_poolsLikelihood", - "offset": 0, - "slot": "105", - "type": "t_array(t_uint256)dyn_storage", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:21" - }, - { - "label": "_poolsLikelihoodSum", - "offset": 0, - "slot": "106", - "type": "t_uint256", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:22" - }, - { - "label": "_poolDelegators", - "offset": 0, - "slot": "107", - "type": "t_mapping(t_address,t_array(t_address)dyn_storage)", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:23" - }, - { - "label": "_poolDelegatorsInactive", - "offset": 0, - "slot": "108", - "type": "t_mapping(t_address,t_array(t_address)dyn_storage)", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:24" - }, - { - "label": "_stakeAmountByEpoch", - "offset": 0, - "slot": "109", - "type": "t_mapping(t_address,t_mapping(t_address,t_mapping(t_uint256,t_uint256)))", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:25" - }, - { - "label": "candidateMinStake", - "offset": 0, - "slot": "110", - "type": "t_uint256", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:29" - }, - { - "label": "delegatorMinStake", - "offset": 0, - "slot": "111", - "type": "t_uint256", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:32" - }, - { - "label": "delegatorStakeSnapshot", - "offset": 0, - "slot": "112", - "type": "t_mapping(t_address,t_mapping(t_address,t_mapping(t_uint256,t_uint256)))", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:38" - }, - { - "label": "orderedWithdrawAmount", - "offset": 0, - "slot": "113", - "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:44" - }, - { - "label": "orderedWithdrawAmountTotal", - "offset": 0, - "slot": "114", - "type": "t_mapping(t_address,t_uint256)", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:49" - }, - { - "label": "orderWithdrawEpoch", - "offset": 0, - "slot": "115", - "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:55" - }, - { - "label": "poolDelegatorIndex", - "offset": 0, - "slot": "116", - "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:62" - }, - { - "label": "poolDelegatorInactiveIndex", - "offset": 0, - "slot": "117", - "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:69" - }, - { - "label": "poolInactiveIndex", - "offset": 0, - "slot": "118", - "type": "t_mapping(t_address,t_uint256)", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:74" - }, - { - "label": "poolIndex", - "offset": 0, - "slot": "119", - "type": "t_mapping(t_address,t_uint256)", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:80" - }, - { - "label": "poolToBeElectedIndex", - "offset": 0, - "slot": "120", - "type": "t_mapping(t_address,t_uint256)", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:87" - }, - { - "label": "poolToBeRemovedIndex", - "offset": 0, - "slot": "121", - "type": "t_mapping(t_address,t_uint256)", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:94" - }, - { - "label": "rewardWasTaken", - "offset": 0, - "slot": "122", - "type": "t_mapping(t_address,t_mapping(t_address,t_mapping(t_uint256,t_bool)))", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:100" - }, - { - "label": "stakeAmount", - "offset": 0, - "slot": "123", - "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:106" - }, - { - "label": "stakeFirstEpoch", - "offset": 0, - "slot": "124", - "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:112" - }, - { - "label": "stakeLastEpoch", - "offset": 0, - "slot": "125", - "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:118" - }, - { - "label": "stakingWithdrawDisallowPeriod", - "offset": 0, - "slot": "126", - "type": "t_uint256", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:122" - }, - { - "label": "stakingEpoch", - "offset": 0, - "slot": "127", - "type": "t_uint256", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:125" - }, - { - "label": "stakingFixedEpochDuration", - "offset": 0, - "slot": "128", - "type": "t_uint256", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:129" - }, - { - "label": "stakingTransitionTimeframeLength", - "offset": 0, - "slot": "129", - "type": "t_uint256", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:132" - }, - { - "label": "stakingEpochStartTime", - "offset": 0, - "slot": "130", - "type": "t_uint256", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:136" - }, - { - "label": "stakingEpochStartBlock", - "offset": 0, - "slot": "131", - "type": "t_uint256", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:143" - }, - { - "label": "currentKeyGenExtraTimeWindow", - "offset": 0, - "slot": "132", - "type": "t_uint256", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:149" - }, - { - "label": "stakeAmountTotal", - "offset": 0, - "slot": "133", - "type": "t_mapping(t_address,t_uint256)", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:154" - }, - { - "label": "validatorSetContract", - "offset": 0, - "slot": "134", - "type": "t_contract(IValidatorSetHbbft)5027", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:157" - }, - { - "label": "poolInfo", - "offset": 0, - "slot": "135", - "type": "t_mapping(t_address,t_struct(PoolInfo)1354_storage)", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:165" - }, - { - "label": "maxStakeAmount", - "offset": 0, - "slot": "136", - "type": "t_uint256", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:169" - }, - { - "label": "abandonedAndRemoved", - "offset": 0, - "slot": "137", - "type": "t_mapping(t_address,t_bool)", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:171" - }, - { - "label": "__gap", - "offset": 0, - "slot": "138", - "type": "t_array(t_uint256)50_storage", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:1682" - }, - { - "label": "validatorSetContractMock", - "offset": 0, - "slot": "188", - "type": "t_contract(IValidatorSetHbbft)5027", - "contract": "StakingHbbftMock", - "src": "contracts/mockContracts/StakingHbbftMock.sol:6" - } - ], - "types": { - "t_address": { - "label": "address", - "numberOfBytes": "20" - }, - "t_array(t_address)dyn_storage": { - "label": "address[]", - "numberOfBytes": "32" - }, - "t_array(t_uint256)49_storage": { - "label": "uint256[49]", - "numberOfBytes": "1568" - }, - "t_array(t_uint256)50_storage": { - "label": "uint256[50]", - "numberOfBytes": "1600" - }, - "t_array(t_uint256)dyn_storage": { - "label": "uint256[]", - "numberOfBytes": "32" - }, - "t_bool": { - "label": "bool", - "numberOfBytes": "1" - }, - "t_bytes16": { - "label": "bytes16", - "numberOfBytes": "16" - }, - "t_bytes2": { - "label": "bytes2", - "numberOfBytes": "2" - }, - "t_bytes_storage": { - "label": "bytes", - "numberOfBytes": "32" - }, - "t_contract(IValidatorSetHbbft)5027": { - "label": "contract IValidatorSetHbbft", - "numberOfBytes": "20" - }, - "t_mapping(t_address,t_array(t_address)dyn_storage)": { - "label": "mapping(address => address[])", - "numberOfBytes": "32" - }, - "t_mapping(t_address,t_bool)": { - "label": "mapping(address => bool)", - "numberOfBytes": "32" - }, - "t_mapping(t_address,t_mapping(t_address,t_mapping(t_uint256,t_bool)))": { - "label": "mapping(address => mapping(address => mapping(uint256 => bool)))", - "numberOfBytes": "32" - }, - "t_mapping(t_address,t_mapping(t_address,t_mapping(t_uint256,t_uint256)))": { - "label": "mapping(address => mapping(address => mapping(uint256 => uint256)))", - "numberOfBytes": "32" - }, - "t_mapping(t_address,t_mapping(t_address,t_uint256))": { - "label": "mapping(address => mapping(address => uint256))", - "numberOfBytes": "32" - }, - "t_mapping(t_address,t_mapping(t_uint256,t_bool))": { - "label": "mapping(address => mapping(uint256 => bool))", - "numberOfBytes": "32" - }, - "t_mapping(t_address,t_mapping(t_uint256,t_uint256))": { - "label": "mapping(address => mapping(uint256 => uint256))", - "numberOfBytes": "32" - }, - "t_mapping(t_address,t_struct(PoolInfo)1354_storage)": { - "label": "mapping(address => struct StakingHbbftBase.PoolInfo)", - "numberOfBytes": "32" - }, - "t_mapping(t_address,t_uint256)": { - "label": "mapping(address => uint256)", - "numberOfBytes": "32" - }, - "t_mapping(t_uint256,t_bool)": { - "label": "mapping(uint256 => bool)", - "numberOfBytes": "32" - }, - "t_mapping(t_uint256,t_uint256)": { - "label": "mapping(uint256 => uint256)", - "numberOfBytes": "32" - }, - "t_struct(PoolInfo)1354_storage": { - "label": "struct StakingHbbftBase.PoolInfo", - "members": [ - { - "label": "publicKey", - "type": "t_bytes_storage", - "offset": 0, - "slot": "0" - }, - { - "label": "internetAddress", - "type": "t_bytes16", - "offset": 0, - "slot": "1" - }, - { - "label": "port", - "type": "t_bytes2", - "offset": 16, - "slot": "1" - } - ], - "numberOfBytes": "64" - }, - "t_uint256": { - "label": "uint256", - "numberOfBytes": "32" - }, - "t_uint8": { - "label": "uint8", - "numberOfBytes": "1" - } - } - } - }, - "8486602c735f59e1cc618a1773e4577c47e22a9e303d2ab28b727fc01f0a1898": { - "address": "0x2053193D7278887844172dD6777B8365bFff29cB", - "txHash": "0x1db74637e2d57b14bee82cc06e1958dbb93dda7653ab8cc3f60664953dfb5e46", - "layout": { - "solcVersion": "0.8.17", - "storage": [ - { - "label": "_initialized", - "offset": 0, - "slot": "0", - "type": "t_uint8", - "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", - "retypedFrom": "bool" - }, - { - "label": "_initializing", - "offset": 1, - "slot": "0", - "type": "t_bool", - "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" - }, - { - "label": "__gap", - "offset": 0, - "slot": "1", - "type": "t_array(t_uint256)50_storage", - "contract": "ContextUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" - }, - { - "label": "_owner", - "offset": 0, - "slot": "51", - "type": "t_address", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" - }, - { - "label": "__gap", - "offset": 0, - "slot": "52", - "type": "t_array(t_uint256)49_storage", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" - }, - { - "label": "validatorSet", - "offset": 0, - "slot": "101", - "type": "t_array(t_address)dyn_storage", - "contract": "KeyGenHistory", - "src": "contracts/KeyGenHistory.sol:15" - }, - { - "label": "parts", - "offset": 0, - "slot": "102", - "type": "t_mapping(t_address,t_bytes_storage)", - "contract": "KeyGenHistory", - "src": "contracts/KeyGenHistory.sol:17" - }, - { - "label": "acks", - "offset": 0, - "slot": "103", - "type": "t_mapping(t_address,t_array(t_bytes_storage)dyn_storage)", - "contract": "KeyGenHistory", - "src": "contracts/KeyGenHistory.sol:18" - }, - { - "label": "numberOfPartsWritten", - "offset": 0, - "slot": "104", - "type": "t_uint128", - "contract": "KeyGenHistory", - "src": "contracts/KeyGenHistory.sol:21" - }, - { - "label": "numberOfAcksWritten", - "offset": 16, - "slot": "104", - "type": "t_uint128", - "contract": "KeyGenHistory", - "src": "contracts/KeyGenHistory.sol:24" - }, - { - "label": "validatorSetContract", - "offset": 0, - "slot": "105", - "type": "t_contract(IValidatorSetHbbft)16123", - "contract": "KeyGenHistory", - "src": "contracts/KeyGenHistory.sol:27" - }, - { - "label": "currentKeyGenRound", - "offset": 0, - "slot": "106", - "type": "t_uint256", - "contract": "KeyGenHistory", - "src": "contracts/KeyGenHistory.sol:37" - } - ], - "types": { - "t_address": { - "label": "address", - "numberOfBytes": "20" - }, - "t_array(t_address)dyn_storage": { - "label": "address[]", - "numberOfBytes": "32" - }, - "t_array(t_bytes_storage)dyn_storage": { - "label": "bytes[]", - "numberOfBytes": "32" - }, - "t_array(t_uint256)49_storage": { - "label": "uint256[49]", - "numberOfBytes": "1568" - }, - "t_array(t_uint256)50_storage": { - "label": "uint256[50]", - "numberOfBytes": "1600" - }, - "t_bool": { - "label": "bool", - "numberOfBytes": "1" - }, - "t_bytes_storage": { - "label": "bytes", - "numberOfBytes": "32" - }, - "t_contract(IValidatorSetHbbft)16123": { - "label": "contract IValidatorSetHbbft", - "numberOfBytes": "20" - }, - "t_mapping(t_address,t_array(t_bytes_storage)dyn_storage)": { - "label": "mapping(address => bytes[])", - "numberOfBytes": "32" - }, - "t_mapping(t_address,t_bytes_storage)": { - "label": "mapping(address => bytes)", - "numberOfBytes": "32" - }, - "t_uint128": { - "label": "uint128", - "numberOfBytes": "16" - }, - "t_uint256": { - "label": "uint256", - "numberOfBytes": "32" - }, - "t_uint8": { - "label": "uint8", - "numberOfBytes": "1" - } - } - } - }, - "54a89993c5a701cf54c58e164f70b17334667ec5d2a2cf43c9db4d2c946f2e33": { - "address": "0x2b1aE60eFccC43e60d571a5b50245D1448114400", - "txHash": "0xcd780944f359b098e229b36d790429aaae6dc2782ecd453fa84e2cfb0541fca5", - "layout": { - "solcVersion": "0.8.17", - "storage": [ - { - "label": "_initialized", - "offset": 0, - "slot": "0", - "type": "t_uint8", - "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", - "retypedFrom": "bool" - }, - { - "label": "_initializing", - "offset": 1, - "slot": "0", - "type": "t_bool", - "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" - }, - { - "label": "__gap", - "offset": 0, - "slot": "1", - "type": "t_array(t_uint256)50_storage", - "contract": "ContextUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" - }, - { - "label": "_owner", - "offset": 0, - "slot": "51", - "type": "t_address", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" - }, - { - "label": "__gap", - "offset": 0, - "slot": "52", - "type": "t_array(t_uint256)49_storage", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" - }, - { - "label": "_certified", - "offset": 0, - "slot": "101", - "type": "t_mapping(t_address,t_bool)", - "contract": "CertifierHbbft", - "src": "contracts/CertifierHbbft.sol:19" - }, - { - "label": "validatorSetContract", - "offset": 0, - "slot": "102", - "type": "t_contract(IValidatorSetHbbft)16123", - "contract": "CertifierHbbft", - "src": "contracts/CertifierHbbft.sol:22" - } - ], - "types": { - "t_address": { - "label": "address", - "numberOfBytes": "20" - }, - "t_array(t_uint256)49_storage": { - "label": "uint256[49]", - "numberOfBytes": "1568" - }, - "t_array(t_uint256)50_storage": { - "label": "uint256[50]", - "numberOfBytes": "1600" - }, - "t_bool": { - "label": "bool", - "numberOfBytes": "1" - }, - "t_contract(IValidatorSetHbbft)16123": { - "label": "contract IValidatorSetHbbft", - "numberOfBytes": "20" - }, - "t_mapping(t_address,t_bool)": { - "label": "mapping(address => bool)", - "numberOfBytes": "32" - }, - "t_uint256": { - "label": "uint256", - "numberOfBytes": "32" - }, - "t_uint8": { - "label": "uint8", - "numberOfBytes": "1" - } - } - } - }, - "0d50ce186abad894297035dcfe58a40b5e734e21c65a0e3566d80dfe32fc7517": { - "address": "0x36e55e5a047581c3Ec9055Ffe144b5f5B21b60a9", - "txHash": "0x6cd72cb20e00df77975bca698cfede9097a5351c9c39d315feef826f2fd508d1", - "layout": { - "solcVersion": "0.8.17", - "storage": [ - { - "label": "_initialized", - "offset": 0, - "slot": "0", - "type": "t_uint8", - "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", - "retypedFrom": "bool" - }, - { - "label": "_initializing", - "offset": 1, - "slot": "0", - "type": "t_bool", - "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" - }, - { - "label": "__gap", - "offset": 0, - "slot": "1", - "type": "t_array(t_uint256)50_storage", - "contract": "ContextUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" - }, - { - "label": "_owner", - "offset": 0, - "slot": "51", - "type": "t_address", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" - }, - { - "label": "__gap", - "offset": 0, - "slot": "52", - "type": "t_array(t_uint256)49_storage", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" - }, - { - "label": "_allowedSenders", - "offset": 0, - "slot": "101", - "type": "t_array(t_address)dyn_storage", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:23" - }, - { - "label": "certifierContract", - "offset": 0, - "slot": "102", - "type": "t_contract(ICertifier)9911", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:26" - }, - { - "label": "keyGenHistoryContract", - "offset": 0, - "slot": "103", - "type": "t_contract(IKeyGenHistory)9952", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:29" - }, - { - "label": "isSenderAllowed", - "offset": 0, - "slot": "104", - "type": "t_mapping(t_address,t_bool)", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:34" - }, - { - "label": "validatorSetContract", - "offset": 0, - "slot": "105", - "type": "t_contract(IValidatorSetHbbft)10396", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:37" - }, - { - "label": "minimumGasPrice", - "offset": 0, - "slot": "106", - "type": "t_uint256", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:41" - }, - { - "label": "blockGasLimit", - "offset": 0, - "slot": "107", - "type": "t_uint256", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:46" - } - ], - "types": { - "t_address": { - "label": "address", - "numberOfBytes": "20" - }, - "t_array(t_address)dyn_storage": { - "label": "address[]", - "numberOfBytes": "32" - }, - "t_array(t_uint256)49_storage": { - "label": "uint256[49]", - "numberOfBytes": "1568" - }, - "t_array(t_uint256)50_storage": { - "label": "uint256[50]", - "numberOfBytes": "1600" - }, - "t_bool": { - "label": "bool", - "numberOfBytes": "1" - }, - "t_contract(ICertifier)9911": { - "label": "contract ICertifier", - "numberOfBytes": "20" - }, - "t_contract(IKeyGenHistory)9952": { - "label": "contract IKeyGenHistory", - "numberOfBytes": "20" - }, - "t_contract(IValidatorSetHbbft)10396": { - "label": "contract IValidatorSetHbbft", - "numberOfBytes": "20" - }, - "t_mapping(t_address,t_bool)": { - "label": "mapping(address => bool)", - "numberOfBytes": "32" - }, - "t_uint256": { - "label": "uint256", - "numberOfBytes": "32" - }, - "t_uint8": { - "label": "uint8", - "numberOfBytes": "1" - } - } - } - }, - "425c8b7948e93bd8f43fbc6f624b683c659e5ad12b6b415fd180ef276c139567": { - "address": "0xd54A236b53483b97f4759E8090d520b80cD5521b", - "txHash": "0x9e0acfdee5b9aeab303a9224edcbffc13b828c7ac280ae3ee2f33a4167b9bc28", - "layout": { - "solcVersion": "0.8.17", - "storage": [ - { - "label": "_initialized", - "offset": 0, - "slot": "0", - "type": "t_uint8", - "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", - "retypedFrom": "bool" - }, - { - "label": "_initializing", - "offset": 1, - "slot": "0", - "type": "t_bool", - "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" - }, - { - "label": "__gap", - "offset": 0, - "slot": "1", - "type": "t_array(t_uint256)50_storage", - "contract": "ContextUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" - }, - { - "label": "_owner", - "offset": 0, - "slot": "51", - "type": "t_address", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" - }, - { - "label": "__gap", - "offset": 0, - "slot": "52", - "type": "t_array(t_uint256)49_storage", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" - }, - { - "label": "_allowedSenders", - "offset": 0, - "slot": "101", - "type": "t_array(t_address)dyn_storage", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:23" - }, - { - "label": "certifierContract", - "offset": 0, - "slot": "102", - "type": "t_contract(ICertifier)9911", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:26" - }, - { - "label": "keyGenHistoryContract", - "offset": 0, - "slot": "103", - "type": "t_contract(IKeyGenHistory)9952", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:29" - }, - { - "label": "isSenderAllowed", - "offset": 0, - "slot": "104", - "type": "t_mapping(t_address,t_bool)", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:34" - }, - { - "label": "validatorSetContract", - "offset": 0, - "slot": "105", - "type": "t_contract(IValidatorSetHbbft)10396", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:37" - }, - { - "label": "minimumGasPrice", - "offset": 0, - "slot": "106", - "type": "t_uint256", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:41" - }, - { - "label": "blockGasLimit", - "offset": 0, - "slot": "107", - "type": "t_uint256", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:46" - } - ], - "types": { - "t_address": { - "label": "address", - "numberOfBytes": "20" - }, - "t_array(t_address)dyn_storage": { - "label": "address[]", - "numberOfBytes": "32" - }, - "t_array(t_uint256)49_storage": { - "label": "uint256[49]", - "numberOfBytes": "1568" - }, - "t_array(t_uint256)50_storage": { - "label": "uint256[50]", - "numberOfBytes": "1600" - }, - "t_bool": { - "label": "bool", - "numberOfBytes": "1" - }, - "t_contract(ICertifier)9911": { - "label": "contract ICertifier", - "numberOfBytes": "20" - }, - "t_contract(IKeyGenHistory)9952": { - "label": "contract IKeyGenHistory", - "numberOfBytes": "20" - }, - "t_contract(IValidatorSetHbbft)10396": { - "label": "contract IValidatorSetHbbft", - "numberOfBytes": "20" - }, - "t_mapping(t_address,t_bool)": { - "label": "mapping(address => bool)", - "numberOfBytes": "32" - }, - "t_uint256": { - "label": "uint256", - "numberOfBytes": "32" - }, - "t_uint8": { - "label": "uint8", - "numberOfBytes": "1" - } - } - } - }, - "5ea1f7c1d2b2cf8e5456887f5f3dff040f5fcd371d645d743390c906a79b9715": { - "address": "0xc89eaede75C180309dEb2b8947A62801FA936d59", - "txHash": "0xef1d4d0819a05f3b488793bb36d91fe533a15115242470984da25ef2ac185004", - "layout": { - "solcVersion": "0.8.17", - "storage": [ - { - "label": "_initialized", - "offset": 0, - "slot": "0", - "type": "t_uint8", - "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", - "retypedFrom": "bool" - }, - { - "label": "_initializing", - "offset": 1, - "slot": "0", - "type": "t_bool", - "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" - }, - { - "label": "__gap", - "offset": 0, - "slot": "1", - "type": "t_array(t_uint256)50_storage", - "contract": "ContextUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" - }, - { - "label": "_owner", - "offset": 0, - "slot": "51", - "type": "t_address", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" - }, - { - "label": "__gap", - "offset": 0, - "slot": "52", - "type": "t_array(t_uint256)49_storage", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" - }, - { - "label": "_currentValidators", - "offset": 0, - "slot": "101", - "type": "t_array(t_address)dyn_storage", - "contract": "ValidatorSetHbbft", - "src": "contracts/ValidatorSetHbbft.sol:19" - }, - { - "label": "_pendingValidators", - "offset": 0, - "slot": "102", - "type": "t_array(t_address)dyn_storage", - "contract": "ValidatorSetHbbft", - "src": "contracts/ValidatorSetHbbft.sol:20" - }, - { - "label": "_previousValidators", - "offset": 0, - "slot": "103", - "type": "t_array(t_address)dyn_storage", - "contract": "ValidatorSetHbbft", - "src": "contracts/ValidatorSetHbbft.sol:21" - }, - { - "label": "_maliceReportedForBlock", - "offset": 0, - "slot": "104", - "type": "t_mapping(t_address,t_mapping(t_uint256,t_array(t_address)dyn_storage))", - "contract": "ValidatorSetHbbft", - "src": "contracts/ValidatorSetHbbft.sol:24" - }, - { - "label": "banCounter", - "offset": 0, - "slot": "105", - "type": "t_mapping(t_address,t_uint256)", - "contract": "ValidatorSetHbbft", - "src": "contracts/ValidatorSetHbbft.sol:28" - }, - { - "label": "bannedUntil", - "offset": 0, - "slot": "106", - "type": "t_mapping(t_address,t_uint256)", - "contract": "ValidatorSetHbbft", - "src": "contracts/ValidatorSetHbbft.sol:31" - }, - { - "label": "bannedDelegatorsUntil", - "offset": 0, - "slot": "107", - "type": "t_mapping(t_address,t_uint256)", - "contract": "ValidatorSetHbbft", - "src": "contracts/ValidatorSetHbbft.sol:35" - }, - { - "label": "banReason", - "offset": 0, - "slot": "108", - "type": "t_mapping(t_address,t_bytes32)", - "contract": "ValidatorSetHbbft", - "src": "contracts/ValidatorSetHbbft.sol:39" - }, - { - "label": "blockRewardContract", - "offset": 0, - "slot": "109", - "type": "t_address", - "contract": "ValidatorSetHbbft", - "src": "contracts/ValidatorSetHbbft.sol:42" - }, - { - "label": "isValidator", - "offset": 0, - "slot": "110", - "type": "t_mapping(t_address,t_bool)", - "contract": "ValidatorSetHbbft", - "src": "contracts/ValidatorSetHbbft.sol:46" - }, - { - "label": "isValidatorPrevious", - "offset": 0, - "slot": "111", - "type": "t_mapping(t_address,t_bool)", - "contract": "ValidatorSetHbbft", - "src": "contracts/ValidatorSetHbbft.sol:50" - }, - { - "label": "miningByStakingAddress", - "offset": 0, - "slot": "112", - "type": "t_mapping(t_address,t_address)", - "contract": "ValidatorSetHbbft", - "src": "contracts/ValidatorSetHbbft.sol:54" - }, - { - "label": "randomContract", - "offset": 0, - "slot": "113", - "type": "t_address", - "contract": "ValidatorSetHbbft", - "src": "contracts/ValidatorSetHbbft.sol:57" - }, - { - "label": "reportingCounter", - "offset": 0, - "slot": "114", - "type": "t_mapping(t_address,t_mapping(t_uint256,t_uint256))", - "contract": "ValidatorSetHbbft", - "src": "contracts/ValidatorSetHbbft.sol:62" - }, - { - "label": "reportingCounterTotal", - "offset": 0, - "slot": "115", - "type": "t_mapping(t_uint256,t_uint256)", - "contract": "ValidatorSetHbbft", - "src": "contracts/ValidatorSetHbbft.sol:67" - }, - { - "label": "stakingByMiningAddress", - "offset": 0, - "slot": "116", - "type": "t_mapping(t_address,t_address)", - "contract": "ValidatorSetHbbft", - "src": "contracts/ValidatorSetHbbft.sol:71" - }, - { - "label": "stakingContract", - "offset": 0, - "slot": "117", - "type": "t_contract(IStakingHbbft)3496", - "contract": "ValidatorSetHbbft", - "src": "contracts/ValidatorSetHbbft.sol:74" - }, - { - "label": "keyGenHistoryContract", - "offset": 0, - "slot": "118", - "type": "t_contract(IKeyGenHistory)3261", - "contract": "ValidatorSetHbbft", - "src": "contracts/ValidatorSetHbbft.sol:77" - }, - { - "label": "validatorCounter", - "offset": 0, - "slot": "119", - "type": "t_mapping(t_address,t_uint256)", - "contract": "ValidatorSetHbbft", - "src": "contracts/ValidatorSetHbbft.sol:80" - }, - { - "label": "validatorAvailableSinceLastWrite", - "offset": 0, - "slot": "120", - "type": "t_mapping(t_address,t_uint256)", - "contract": "ValidatorSetHbbft", - "src": "contracts/ValidatorSetHbbft.sol:83" - }, - { - "label": "validatorAvailableSince", - "offset": 0, - "slot": "121", - "type": "t_mapping(t_address,t_uint256)", - "contract": "ValidatorSetHbbft", - "src": "contracts/ValidatorSetHbbft.sol:91" - }, - { - "label": "maxValidators", - "offset": 0, - "slot": "122", - "type": "t_uint256", - "contract": "ValidatorSetHbbft", - "src": "contracts/ValidatorSetHbbft.sol:94" - }, - { - "label": "banDuration", - "offset": 0, - "slot": "123", - "type": "t_uint256", - "contract": "ValidatorSetHbbft", - "src": "contracts/ValidatorSetHbbft.sol:97" - }, - { - "label": "validatorInactivityThreshold", - "offset": 0, - "slot": "124", - "type": "t_uint256", - "contract": "ValidatorSetHbbft", - "src": "contracts/ValidatorSetHbbft.sol:100" - }, - { - "label": "_systemAddress", - "offset": 0, - "slot": "125", - "type": "t_address", - "contract": "ValidatorSetHbbftMock", - "src": "contracts/mockContracts/ValidatorSetHbbftMock.sol:6" - }, - { - "label": "_isFullHealth", - "offset": 20, - "slot": "125", - "type": "t_bool", - "contract": "ValidatorSetHbbftMock", - "src": "contracts/mockContracts/ValidatorSetHbbftMock.sol:7" - } - ], - "types": { - "t_address": { - "label": "address", - "numberOfBytes": "20" - }, - "t_array(t_address)dyn_storage": { - "label": "address[]", - "numberOfBytes": "32" - }, - "t_array(t_uint256)49_storage": { - "label": "uint256[49]", - "numberOfBytes": "1568" - }, - "t_array(t_uint256)50_storage": { - "label": "uint256[50]", - "numberOfBytes": "1600" - }, - "t_bool": { - "label": "bool", - "numberOfBytes": "1" - }, - "t_bytes32": { - "label": "bytes32", - "numberOfBytes": "32" - }, - "t_contract(IKeyGenHistory)3261": { - "label": "contract IKeyGenHistory", - "numberOfBytes": "20" - }, - "t_contract(IStakingHbbft)3496": { - "label": "contract IStakingHbbft", - "numberOfBytes": "20" - }, - "t_mapping(t_address,t_address)": { - "label": "mapping(address => address)", - "numberOfBytes": "32" - }, - "t_mapping(t_address,t_bool)": { - "label": "mapping(address => bool)", - "numberOfBytes": "32" - }, - "t_mapping(t_address,t_bytes32)": { - "label": "mapping(address => bytes32)", - "numberOfBytes": "32" - }, - "t_mapping(t_address,t_mapping(t_uint256,t_array(t_address)dyn_storage))": { - "label": "mapping(address => mapping(uint256 => address[]))", - "numberOfBytes": "32" - }, - "t_mapping(t_address,t_mapping(t_uint256,t_uint256))": { - "label": "mapping(address => mapping(uint256 => uint256))", - "numberOfBytes": "32" - }, - "t_mapping(t_address,t_uint256)": { - "label": "mapping(address => uint256)", - "numberOfBytes": "32" - }, - "t_mapping(t_uint256,t_array(t_address)dyn_storage)": { - "label": "mapping(uint256 => address[])", - "numberOfBytes": "32" - }, - "t_mapping(t_uint256,t_uint256)": { - "label": "mapping(uint256 => uint256)", - "numberOfBytes": "32" - }, - "t_uint256": { - "label": "uint256", - "numberOfBytes": "32" - }, - "t_uint8": { - "label": "uint8", - "numberOfBytes": "1" - } - } - } - }, - "1a9dfbbdbf9541398037214bb063e3c4e8504556df118ef52db513b39a5b65eb": { - "address": "0x7c4E44Fcf0f6d81FE3e7a0D9C5ef9A058E211F2e", - "txHash": "0x056af918c9b183d039a1bc316636cba593998ffbf9babb6af3dd45dc64ea6805", - "layout": { - "solcVersion": "0.8.17", - "storage": [ - { - "label": "earlyEpochEnd", - "offset": 0, - "slot": "0", - "type": "t_mapping(t_uint256,t_bool)", - "contract": "ConnectivityTrackerHbbftMock", - "src": "contracts/mockContracts/ConnectivityTrackerHbbftMock.sol:5" - } - ], - "types": { - "t_bool": { - "label": "bool", - "numberOfBytes": "1" - }, - "t_mapping(t_uint256,t_bool)": { - "label": "mapping(uint256 => bool)", - "numberOfBytes": "32" - }, - "t_uint256": { - "label": "uint256", - "numberOfBytes": "32" - } - } - } - }, - "5db6dc84d836d9d77e34ff1003a827c6a0613fae958c153e790f94ff8808c7b3": { - "address": "0xa08c2E48CB81f67BeD56548cfE81d8070d349bfF", - "txHash": "0x44a77702d3cc831159042e1e08a5b3092a8f8221eaa704567aee2646574fb6ff", - "layout": { - "solcVersion": "0.8.17", - "storage": [ - { - "label": "_initialized", - "offset": 0, - "slot": "0", - "type": "t_uint8", - "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", - "retypedFrom": "bool" - }, - { - "label": "_initializing", - "offset": 1, - "slot": "0", - "type": "t_bool", - "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" - }, - { - "label": "__gap", - "offset": 0, - "slot": "1", - "type": "t_array(t_uint256)50_storage", - "contract": "ContextUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" - }, - { - "label": "_owner", - "offset": 0, - "slot": "51", - "type": "t_address", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" - }, - { - "label": "__gap", - "offset": 0, - "slot": "52", - "type": "t_array(t_uint256)49_storage", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" - }, - { - "label": "_currentValidators", - "offset": 0, - "slot": "101", - "type": "t_array(t_address)dyn_storage", - "contract": "ValidatorSetHbbft", - "src": "contracts/ValidatorSetHbbft.sol:19" - }, - { - "label": "_pendingValidators", - "offset": 0, - "slot": "102", - "type": "t_array(t_address)dyn_storage", - "contract": "ValidatorSetHbbft", - "src": "contracts/ValidatorSetHbbft.sol:20" - }, - { - "label": "_previousValidators", - "offset": 0, - "slot": "103", - "type": "t_array(t_address)dyn_storage", - "contract": "ValidatorSetHbbft", - "src": "contracts/ValidatorSetHbbft.sol:21" - }, - { - "label": "_maliceReportedForBlock", - "offset": 0, - "slot": "104", - "type": "t_mapping(t_address,t_mapping(t_uint256,t_array(t_address)dyn_storage))", - "contract": "ValidatorSetHbbft", - "src": "contracts/ValidatorSetHbbft.sol:24" - }, - { - "label": "banCounter", - "offset": 0, - "slot": "105", - "type": "t_mapping(t_address,t_uint256)", - "contract": "ValidatorSetHbbft", - "src": "contracts/ValidatorSetHbbft.sol:28" - }, - { - "label": "bannedUntil", - "offset": 0, - "slot": "106", - "type": "t_mapping(t_address,t_uint256)", - "contract": "ValidatorSetHbbft", - "src": "contracts/ValidatorSetHbbft.sol:31" - }, - { - "label": "bannedDelegatorsUntil", - "offset": 0, - "slot": "107", - "type": "t_mapping(t_address,t_uint256)", - "contract": "ValidatorSetHbbft", - "src": "contracts/ValidatorSetHbbft.sol:35" - }, - { - "label": "banReason", - "offset": 0, - "slot": "108", - "type": "t_mapping(t_address,t_bytes32)", - "contract": "ValidatorSetHbbft", - "src": "contracts/ValidatorSetHbbft.sol:39" - }, - { - "label": "blockRewardContract", - "offset": 0, - "slot": "109", - "type": "t_address", - "contract": "ValidatorSetHbbft", - "src": "contracts/ValidatorSetHbbft.sol:42" - }, - { - "label": "isValidator", - "offset": 0, - "slot": "110", - "type": "t_mapping(t_address,t_bool)", - "contract": "ValidatorSetHbbft", - "src": "contracts/ValidatorSetHbbft.sol:46" - }, - { - "label": "isValidatorPrevious", - "offset": 0, - "slot": "111", - "type": "t_mapping(t_address,t_bool)", - "contract": "ValidatorSetHbbft", - "src": "contracts/ValidatorSetHbbft.sol:50" - }, - { - "label": "miningByStakingAddress", - "offset": 0, - "slot": "112", - "type": "t_mapping(t_address,t_address)", - "contract": "ValidatorSetHbbft", - "src": "contracts/ValidatorSetHbbft.sol:54" - }, - { - "label": "randomContract", - "offset": 0, - "slot": "113", - "type": "t_address", - "contract": "ValidatorSetHbbft", - "src": "contracts/ValidatorSetHbbft.sol:57" - }, - { - "label": "reportingCounter", - "offset": 0, - "slot": "114", - "type": "t_mapping(t_address,t_mapping(t_uint256,t_uint256))", - "contract": "ValidatorSetHbbft", - "src": "contracts/ValidatorSetHbbft.sol:62" - }, - { - "label": "reportingCounterTotal", - "offset": 0, - "slot": "115", - "type": "t_mapping(t_uint256,t_uint256)", - "contract": "ValidatorSetHbbft", - "src": "contracts/ValidatorSetHbbft.sol:67" - }, - { - "label": "stakingByMiningAddress", - "offset": 0, - "slot": "116", - "type": "t_mapping(t_address,t_address)", - "contract": "ValidatorSetHbbft", - "src": "contracts/ValidatorSetHbbft.sol:71" - }, - { - "label": "stakingContract", - "offset": 0, - "slot": "117", - "type": "t_contract(IStakingHbbft)15906", - "contract": "ValidatorSetHbbft", - "src": "contracts/ValidatorSetHbbft.sol:74" - }, - { - "label": "keyGenHistoryContract", - "offset": 0, - "slot": "118", - "type": "t_contract(IKeyGenHistory)15555", - "contract": "ValidatorSetHbbft", - "src": "contracts/ValidatorSetHbbft.sol:77" - }, - { - "label": "validatorCounter", - "offset": 0, - "slot": "119", - "type": "t_mapping(t_address,t_uint256)", - "contract": "ValidatorSetHbbft", - "src": "contracts/ValidatorSetHbbft.sol:80" - }, - { - "label": "validatorAvailableSinceLastWrite", - "offset": 0, - "slot": "120", - "type": "t_mapping(t_address,t_uint256)", - "contract": "ValidatorSetHbbft", - "src": "contracts/ValidatorSetHbbft.sol:83" - }, - { - "label": "validatorAvailableSince", - "offset": 0, - "slot": "121", - "type": "t_mapping(t_address,t_uint256)", - "contract": "ValidatorSetHbbft", - "src": "contracts/ValidatorSetHbbft.sol:91" - }, - { - "label": "maxValidators", - "offset": 0, - "slot": "122", - "type": "t_uint256", - "contract": "ValidatorSetHbbft", - "src": "contracts/ValidatorSetHbbft.sol:94" - }, - { - "label": "banDuration", - "offset": 0, - "slot": "123", - "type": "t_uint256", - "contract": "ValidatorSetHbbft", - "src": "contracts/ValidatorSetHbbft.sol:97" - }, - { - "label": "validatorInactivityThreshold", - "offset": 0, - "slot": "124", - "type": "t_uint256", - "contract": "ValidatorSetHbbft", - "src": "contracts/ValidatorSetHbbft.sol:100" - }, - { - "label": "_systemAddress", - "offset": 0, - "slot": "125", - "type": "t_address", - "contract": "ValidatorSetHbbftMock", - "src": "contracts/mockContracts/ValidatorSetHbbftMock.sol:6" - }, - { - "label": "_isFullHealth", - "offset": 20, - "slot": "125", - "type": "t_bool", - "contract": "ValidatorSetHbbftMock", - "src": "contracts/mockContracts/ValidatorSetHbbftMock.sol:7" - } - ], - "types": { - "t_address": { - "label": "address", - "numberOfBytes": "20" - }, - "t_array(t_address)dyn_storage": { - "label": "address[]", - "numberOfBytes": "32" - }, - "t_array(t_uint256)49_storage": { - "label": "uint256[49]", - "numberOfBytes": "1568" - }, - "t_array(t_uint256)50_storage": { - "label": "uint256[50]", - "numberOfBytes": "1600" - }, - "t_bool": { - "label": "bool", - "numberOfBytes": "1" - }, - "t_bytes32": { - "label": "bytes32", - "numberOfBytes": "32" - }, - "t_contract(IKeyGenHistory)15555": { - "label": "contract IKeyGenHistory", - "numberOfBytes": "20" - }, - "t_contract(IStakingHbbft)15906": { - "label": "contract IStakingHbbft", - "numberOfBytes": "20" - }, - "t_mapping(t_address,t_address)": { - "label": "mapping(address => address)", - "numberOfBytes": "32" - }, - "t_mapping(t_address,t_bool)": { - "label": "mapping(address => bool)", - "numberOfBytes": "32" - }, - "t_mapping(t_address,t_bytes32)": { - "label": "mapping(address => bytes32)", - "numberOfBytes": "32" - }, - "t_mapping(t_address,t_mapping(t_uint256,t_array(t_address)dyn_storage))": { - "label": "mapping(address => mapping(uint256 => address[]))", - "numberOfBytes": "32" - }, - "t_mapping(t_address,t_mapping(t_uint256,t_uint256))": { - "label": "mapping(address => mapping(uint256 => uint256))", - "numberOfBytes": "32" - }, - "t_mapping(t_address,t_uint256)": { - "label": "mapping(address => uint256)", - "numberOfBytes": "32" - }, - "t_mapping(t_uint256,t_array(t_address)dyn_storage)": { - "label": "mapping(uint256 => address[])", - "numberOfBytes": "32" - }, - "t_mapping(t_uint256,t_uint256)": { - "label": "mapping(uint256 => uint256)", - "numberOfBytes": "32" - }, - "t_uint256": { - "label": "uint256", - "numberOfBytes": "32" - }, - "t_uint8": { - "label": "uint8", - "numberOfBytes": "1" - } - } - } - }, - "b253aaafa8667dc72524549f7ff60686d8a9322563a5831a7fcecfe91a9ab346": { - "address": "0x9d0cADf89939B62905666BFD54545e3bb76dfCDb", - "txHash": "0xf74d021046b82d863dfc0c26f6e5058d09cef9c5d44ce459dee85b848e509aea", - "layout": { - "solcVersion": "0.8.17", - "storage": [ - { - "label": "_initialized", - "offset": 0, - "slot": "0", - "type": "t_uint8", - "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", - "retypedFrom": "bool" - }, - { - "label": "_initializing", - "offset": 1, - "slot": "0", - "type": "t_bool", - "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" - }, - { - "label": "__gap", - "offset": 0, - "slot": "1", - "type": "t_array(t_uint256)50_storage", - "contract": "ContextUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" - }, - { - "label": "_owner", - "offset": 0, - "slot": "51", - "type": "t_address", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" - }, - { - "label": "__gap", - "offset": 0, - "slot": "52", - "type": "t_array(t_uint256)49_storage", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" - }, - { - "label": "_epochsPoolGotRewardFor", - "offset": 0, - "slot": "101", - "type": "t_mapping(t_address,t_array(t_uint256)dyn_storage)", - "contract": "BlockRewardHbbftBase", - "src": "contracts/base/BlockRewardHbbftBase.sol:24" - }, - { - "label": "epochPoolNativeReward", - "offset": 0, - "slot": "102", - "type": "t_mapping(t_uint256,t_mapping(t_address,t_uint256))", - "contract": "BlockRewardHbbftBase", - "src": "contracts/base/BlockRewardHbbftBase.sol:28" - }, - { - "label": "nativeRewardUndistributed", - "offset": 0, - "slot": "103", - "type": "t_uint256", - "contract": "BlockRewardHbbftBase", - "src": "contracts/base/BlockRewardHbbftBase.sol:32" - }, - { - "label": "snapshotPoolTotalStakeAmount", - "offset": 0, - "slot": "104", - "type": "t_mapping(t_uint256,t_mapping(t_address,t_uint256))", - "contract": "BlockRewardHbbftBase", - "src": "contracts/base/BlockRewardHbbftBase.sol:36" - }, - { - "label": "snapshotPoolValidatorStakeAmount", - "offset": 0, - "slot": "105", - "type": "t_mapping(t_uint256,t_mapping(t_address,t_uint256))", - "contract": "BlockRewardHbbftBase", - "src": "contracts/base/BlockRewardHbbftBase.sol:41" - }, - { - "label": "validatorMinRewardPercent", - "offset": 0, - "slot": "106", - "type": "t_mapping(t_uint256,t_uint256)", - "contract": "BlockRewardHbbftBase", - "src": "contracts/base/BlockRewardHbbftBase.sol:49" - }, - { - "label": "deltaPot", - "offset": 0, - "slot": "107", - "type": "t_uint256", - "contract": "BlockRewardHbbftBase", - "src": "contracts/base/BlockRewardHbbftBase.sol:52" - }, - { - "label": "deltaPotPayoutFraction", - "offset": 0, - "slot": "108", - "type": "t_uint256", - "contract": "BlockRewardHbbftBase", - "src": "contracts/base/BlockRewardHbbftBase.sol:56" - }, - { - "label": "reinsertPot", - "offset": 0, - "slot": "109", - "type": "t_uint256", - "contract": "BlockRewardHbbftBase", - "src": "contracts/base/BlockRewardHbbftBase.sol:61" - }, - { - "label": "reinsertPotPayoutFraction", - "offset": 0, - "slot": "110", - "type": "t_uint256", - "contract": "BlockRewardHbbftBase", - "src": "contracts/base/BlockRewardHbbftBase.sol:65" - }, - { - "label": "validatorSetContract", - "offset": 0, - "slot": "111", - "type": "t_contract(IValidatorSetHbbft)7839", - "contract": "BlockRewardHbbftBase", - "src": "contracts/base/BlockRewardHbbftBase.sol:68" - }, - { - "label": "governancePotAddress", - "offset": 0, - "slot": "112", - "type": "t_address_payable", - "contract": "BlockRewardHbbftBase", - "src": "contracts/base/BlockRewardHbbftBase.sol:71" - }, - { - "label": "governancePotShareNominator", - "offset": 0, - "slot": "113", - "type": "t_uint256", - "contract": "BlockRewardHbbftBase", - "src": "contracts/base/BlockRewardHbbftBase.sol:75" - }, - { - "label": "governancePotShareDenominator", - "offset": 0, - "slot": "114", - "type": "t_uint256", - "contract": "BlockRewardHbbftBase", - "src": "contracts/base/BlockRewardHbbftBase.sol:79" - }, - { - "label": "connectivityTracker", - "offset": 0, - "slot": "115", - "type": "t_address", - "contract": "BlockRewardHbbftBase", - "src": "contracts/base/BlockRewardHbbftBase.sol:82" - }, - { - "label": "earlyEpochEnd", - "offset": 20, - "slot": "115", - "type": "t_bool", - "contract": "BlockRewardHbbftBase", - "src": "contracts/base/BlockRewardHbbftBase.sol:85" - }, - { - "label": "__gap", - "offset": 0, - "slot": "116", - "type": "t_array(t_uint256)49_storage", - "contract": "BlockRewardHbbftBase", - "src": "contracts/base/BlockRewardHbbftBase.sol:708" - }, - { - "label": "_systemAddress", - "offset": 0, - "slot": "165", - "type": "t_address", - "contract": "BlockRewardHbbftMock", - "src": "contracts/mockContracts/BlockRewardHbbftMock.sol:6" - } - ], - "types": { - "t_address": { - "label": "address", - "numberOfBytes": "20" - }, - "t_address_payable": { - "label": "address payable", - "numberOfBytes": "20" - }, - "t_array(t_uint256)49_storage": { - "label": "uint256[49]", - "numberOfBytes": "1568" - }, - "t_array(t_uint256)50_storage": { - "label": "uint256[50]", - "numberOfBytes": "1600" - }, - "t_array(t_uint256)dyn_storage": { - "label": "uint256[]", - "numberOfBytes": "32" - }, - "t_bool": { - "label": "bool", - "numberOfBytes": "1" - }, - "t_contract(IValidatorSetHbbft)7839": { - "label": "contract IValidatorSetHbbft", - "numberOfBytes": "20" - }, - "t_mapping(t_address,t_array(t_uint256)dyn_storage)": { - "label": "mapping(address => uint256[])", - "numberOfBytes": "32" - }, - "t_mapping(t_address,t_uint256)": { - "label": "mapping(address => uint256)", - "numberOfBytes": "32" - }, - "t_mapping(t_uint256,t_mapping(t_address,t_uint256))": { - "label": "mapping(uint256 => mapping(address => uint256))", - "numberOfBytes": "32" - }, - "t_mapping(t_uint256,t_uint256)": { - "label": "mapping(uint256 => uint256)", - "numberOfBytes": "32" - }, - "t_uint256": { - "label": "uint256", - "numberOfBytes": "32" - }, - "t_uint8": { - "label": "uint8", - "numberOfBytes": "1" - } - } - } - }, - "b8256f1c33c18e4cab41555b7386c695295c86377c9d07cd300a9c8aad5e86d5": { - "address": "0x7C82b0dA004De1ebD85C3dA62b297d348C7c4866", - "txHash": "0x95d2f918b8c38776d71b76729303b85725ae501396c1a557cc1f08506122b5d7", - "layout": { - "solcVersion": "0.8.17", - "storage": [ - { - "label": "_initialized", - "offset": 0, - "slot": "0", - "type": "t_uint8", - "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", - "retypedFrom": "bool" - }, - { - "label": "_initializing", - "offset": 1, - "slot": "0", - "type": "t_bool", - "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" - }, - { - "label": "__gap", - "offset": 0, - "slot": "1", - "type": "t_array(t_uint256)50_storage", - "contract": "ContextUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" - }, - { - "label": "_owner", - "offset": 0, - "slot": "51", - "type": "t_address", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" - }, - { - "label": "__gap", - "offset": 0, - "slot": "52", - "type": "t_array(t_uint256)49_storage", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" - }, - { - "label": "_pools", - "offset": 0, - "slot": "101", - "type": "t_array(t_address)dyn_storage", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:17" - }, - { - "label": "_poolsInactive", - "offset": 0, - "slot": "102", - "type": "t_array(t_address)dyn_storage", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:18" - }, - { - "label": "_poolsToBeElected", - "offset": 0, - "slot": "103", - "type": "t_array(t_address)dyn_storage", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:19" - }, - { - "label": "_poolsToBeRemoved", - "offset": 0, - "slot": "104", - "type": "t_array(t_address)dyn_storage", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:20" - }, - { - "label": "_poolsLikelihood", - "offset": 0, - "slot": "105", - "type": "t_array(t_uint256)dyn_storage", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:21" - }, - { - "label": "_poolsLikelihoodSum", - "offset": 0, - "slot": "106", - "type": "t_uint256", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:22" - }, - { - "label": "_poolDelegators", - "offset": 0, - "slot": "107", - "type": "t_mapping(t_address,t_array(t_address)dyn_storage)", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:23" - }, - { - "label": "_poolDelegatorsInactive", - "offset": 0, - "slot": "108", - "type": "t_mapping(t_address,t_array(t_address)dyn_storage)", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:24" - }, - { - "label": "_stakeAmountByEpoch", - "offset": 0, - "slot": "109", - "type": "t_mapping(t_address,t_mapping(t_address,t_mapping(t_uint256,t_uint256)))", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:25" - }, - { - "label": "candidateMinStake", - "offset": 0, - "slot": "110", - "type": "t_uint256", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:29" - }, - { - "label": "delegatorMinStake", - "offset": 0, - "slot": "111", - "type": "t_uint256", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:32" - }, - { - "label": "delegatorStakeSnapshot", - "offset": 0, - "slot": "112", - "type": "t_mapping(t_address,t_mapping(t_address,t_mapping(t_uint256,t_uint256)))", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:38" - }, - { - "label": "orderedWithdrawAmount", - "offset": 0, - "slot": "113", - "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:44" - }, - { - "label": "orderedWithdrawAmountTotal", - "offset": 0, - "slot": "114", - "type": "t_mapping(t_address,t_uint256)", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:49" - }, - { - "label": "orderWithdrawEpoch", - "offset": 0, - "slot": "115", - "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:55" - }, - { - "label": "poolDelegatorIndex", - "offset": 0, - "slot": "116", - "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:62" - }, - { - "label": "poolDelegatorInactiveIndex", - "offset": 0, - "slot": "117", - "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:69" - }, - { - "label": "poolInactiveIndex", - "offset": 0, - "slot": "118", - "type": "t_mapping(t_address,t_uint256)", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:74" - }, - { - "label": "poolIndex", - "offset": 0, - "slot": "119", - "type": "t_mapping(t_address,t_uint256)", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:80" - }, - { - "label": "poolToBeElectedIndex", - "offset": 0, - "slot": "120", - "type": "t_mapping(t_address,t_uint256)", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:87" - }, - { - "label": "poolToBeRemovedIndex", - "offset": 0, - "slot": "121", - "type": "t_mapping(t_address,t_uint256)", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:94" - }, - { - "label": "rewardWasTaken", - "offset": 0, - "slot": "122", - "type": "t_mapping(t_address,t_mapping(t_address,t_mapping(t_uint256,t_bool)))", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:100" - }, - { - "label": "stakeAmount", - "offset": 0, - "slot": "123", - "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:106" - }, - { - "label": "stakeFirstEpoch", - "offset": 0, - "slot": "124", - "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:112" - }, - { - "label": "stakeLastEpoch", - "offset": 0, - "slot": "125", - "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:118" - }, - { - "label": "stakingWithdrawDisallowPeriod", - "offset": 0, - "slot": "126", - "type": "t_uint256", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:122" - }, - { - "label": "stakingEpoch", - "offset": 0, - "slot": "127", - "type": "t_uint256", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:125" - }, - { - "label": "stakingFixedEpochDuration", - "offset": 0, - "slot": "128", - "type": "t_uint256", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:129" - }, - { - "label": "stakingTransitionTimeframeLength", - "offset": 0, - "slot": "129", - "type": "t_uint256", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:132" - }, - { - "label": "stakingEpochStartTime", - "offset": 0, - "slot": "130", - "type": "t_uint256", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:136" - }, - { - "label": "stakingEpochStartBlock", - "offset": 0, - "slot": "131", - "type": "t_uint256", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:143" - }, - { - "label": "currentKeyGenExtraTimeWindow", - "offset": 0, - "slot": "132", - "type": "t_uint256", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:149" - }, - { - "label": "stakeAmountTotal", - "offset": 0, - "slot": "133", - "type": "t_mapping(t_address,t_uint256)", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:154" - }, - { - "label": "validatorSetContract", - "offset": 0, - "slot": "134", - "type": "t_contract(IValidatorSetHbbft)5059", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:157" - }, - { - "label": "poolInfo", - "offset": 0, - "slot": "135", - "type": "t_mapping(t_address,t_struct(PoolInfo)1354_storage)", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:165" - }, - { - "label": "maxStakeAmount", - "offset": 0, - "slot": "136", - "type": "t_uint256", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:169" - }, - { - "label": "abandonedAndRemoved", - "offset": 0, - "slot": "137", - "type": "t_mapping(t_address,t_bool)", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:171" - }, - { - "label": "__gap", - "offset": 0, - "slot": "138", - "type": "t_array(t_uint256)50_storage", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:1691" - }, - { - "label": "validatorSetContractMock", - "offset": 0, - "slot": "188", - "type": "t_contract(IValidatorSetHbbft)5059", - "contract": "StakingHbbftMock", - "src": "contracts/mockContracts/StakingHbbftMock.sol:6" - } - ], - "types": { - "t_address": { - "label": "address", - "numberOfBytes": "20" - }, - "t_array(t_address)dyn_storage": { - "label": "address[]", - "numberOfBytes": "32" - }, - "t_array(t_uint256)49_storage": { - "label": "uint256[49]", - "numberOfBytes": "1568" - }, - "t_array(t_uint256)50_storage": { - "label": "uint256[50]", - "numberOfBytes": "1600" - }, - "t_array(t_uint256)dyn_storage": { - "label": "uint256[]", - "numberOfBytes": "32" - }, - "t_bool": { - "label": "bool", - "numberOfBytes": "1" - }, - "t_bytes16": { - "label": "bytes16", - "numberOfBytes": "16" - }, - "t_bytes2": { - "label": "bytes2", - "numberOfBytes": "2" - }, - "t_bytes_storage": { - "label": "bytes", - "numberOfBytes": "32" - }, - "t_contract(IValidatorSetHbbft)5059": { - "label": "contract IValidatorSetHbbft", - "numberOfBytes": "20" - }, - "t_mapping(t_address,t_array(t_address)dyn_storage)": { - "label": "mapping(address => address[])", - "numberOfBytes": "32" - }, - "t_mapping(t_address,t_bool)": { - "label": "mapping(address => bool)", - "numberOfBytes": "32" - }, - "t_mapping(t_address,t_mapping(t_address,t_mapping(t_uint256,t_bool)))": { - "label": "mapping(address => mapping(address => mapping(uint256 => bool)))", - "numberOfBytes": "32" - }, - "t_mapping(t_address,t_mapping(t_address,t_mapping(t_uint256,t_uint256)))": { - "label": "mapping(address => mapping(address => mapping(uint256 => uint256)))", - "numberOfBytes": "32" - }, - "t_mapping(t_address,t_mapping(t_address,t_uint256))": { - "label": "mapping(address => mapping(address => uint256))", - "numberOfBytes": "32" - }, - "t_mapping(t_address,t_mapping(t_uint256,t_bool))": { - "label": "mapping(address => mapping(uint256 => bool))", - "numberOfBytes": "32" - }, - "t_mapping(t_address,t_mapping(t_uint256,t_uint256))": { - "label": "mapping(address => mapping(uint256 => uint256))", - "numberOfBytes": "32" - }, - "t_mapping(t_address,t_struct(PoolInfo)1354_storage)": { - "label": "mapping(address => struct StakingHbbftBase.PoolInfo)", - "numberOfBytes": "32" - }, - "t_mapping(t_address,t_uint256)": { - "label": "mapping(address => uint256)", - "numberOfBytes": "32" - }, - "t_mapping(t_uint256,t_bool)": { - "label": "mapping(uint256 => bool)", - "numberOfBytes": "32" - }, - "t_mapping(t_uint256,t_uint256)": { - "label": "mapping(uint256 => uint256)", - "numberOfBytes": "32" - }, - "t_struct(PoolInfo)1354_storage": { - "label": "struct StakingHbbftBase.PoolInfo", - "members": [ - { - "label": "publicKey", - "type": "t_bytes_storage", - "offset": 0, - "slot": "0" - }, - { - "label": "internetAddress", - "type": "t_bytes16", - "offset": 0, - "slot": "1" - }, - { - "label": "port", - "type": "t_bytes2", - "offset": 16, - "slot": "1" - } - ], - "numberOfBytes": "64" - }, - "t_uint256": { - "label": "uint256", - "numberOfBytes": "32" - }, - "t_uint8": { - "label": "uint8", - "numberOfBytes": "1" - } - } - } - }, - "1f2ccbc421e257c787e57286bb8afd8f7bdd502d47f868883ac7b89fc792d9ed": { - "address": "0x4B66CE8632e97eC216b08834674D39499370a135", - "txHash": "0xc10981aa3832d6a859362ba4e7de76ae777db6ae5441ad82658836ef08e0b42b", - "layout": { - "solcVersion": "0.8.17", - "storage": [ - { - "label": "_initialized", - "offset": 0, - "slot": "0", - "type": "t_uint8", - "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", - "retypedFrom": "bool" - }, - { - "label": "_initializing", - "offset": 1, - "slot": "0", - "type": "t_bool", - "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" - }, - { - "label": "__gap", - "offset": 0, - "slot": "1", - "type": "t_array(t_uint256)50_storage", - "contract": "ContextUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" - }, - { - "label": "_owner", - "offset": 0, - "slot": "51", - "type": "t_address", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" - }, - { - "label": "__gap", - "offset": 0, - "slot": "52", - "type": "t_array(t_uint256)49_storage", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" - }, - { - "label": "_epochsPoolGotRewardFor", - "offset": 0, - "slot": "101", - "type": "t_mapping(t_address,t_array(t_uint256)dyn_storage)", - "contract": "BlockRewardHbbftBase", - "src": "contracts/base/BlockRewardHbbftBase.sol:24" - }, - { - "label": "epochPoolNativeReward", - "offset": 0, - "slot": "102", - "type": "t_mapping(t_uint256,t_mapping(t_address,t_uint256))", - "contract": "BlockRewardHbbftBase", - "src": "contracts/base/BlockRewardHbbftBase.sol:28" - }, - { - "label": "nativeRewardUndistributed", - "offset": 0, - "slot": "103", - "type": "t_uint256", - "contract": "BlockRewardHbbftBase", - "src": "contracts/base/BlockRewardHbbftBase.sol:32" - }, - { - "label": "snapshotPoolTotalStakeAmount", - "offset": 0, - "slot": "104", - "type": "t_mapping(t_uint256,t_mapping(t_address,t_uint256))", - "contract": "BlockRewardHbbftBase", - "src": "contracts/base/BlockRewardHbbftBase.sol:36" - }, - { - "label": "snapshotPoolValidatorStakeAmount", - "offset": 0, - "slot": "105", - "type": "t_mapping(t_uint256,t_mapping(t_address,t_uint256))", - "contract": "BlockRewardHbbftBase", - "src": "contracts/base/BlockRewardHbbftBase.sol:41" - }, - { - "label": "validatorMinRewardPercent", - "offset": 0, - "slot": "106", - "type": "t_mapping(t_uint256,t_uint256)", - "contract": "BlockRewardHbbftBase", - "src": "contracts/base/BlockRewardHbbftBase.sol:49" - }, - { - "label": "deltaPot", - "offset": 0, - "slot": "107", - "type": "t_uint256", - "contract": "BlockRewardHbbftBase", - "src": "contracts/base/BlockRewardHbbftBase.sol:52" - }, - { - "label": "deltaPotPayoutFraction", - "offset": 0, - "slot": "108", - "type": "t_uint256", - "contract": "BlockRewardHbbftBase", - "src": "contracts/base/BlockRewardHbbftBase.sol:56" - }, - { - "label": "reinsertPot", - "offset": 0, - "slot": "109", - "type": "t_uint256", - "contract": "BlockRewardHbbftBase", - "src": "contracts/base/BlockRewardHbbftBase.sol:61" - }, - { - "label": "reinsertPotPayoutFraction", - "offset": 0, - "slot": "110", - "type": "t_uint256", - "contract": "BlockRewardHbbftBase", - "src": "contracts/base/BlockRewardHbbftBase.sol:65" - }, - { - "label": "validatorSetContract", - "offset": 0, - "slot": "111", - "type": "t_contract(IValidatorSetHbbft)16123", - "contract": "BlockRewardHbbftBase", - "src": "contracts/base/BlockRewardHbbftBase.sol:68" - }, - { - "label": "governancePotAddress", - "offset": 0, - "slot": "112", - "type": "t_address_payable", - "contract": "BlockRewardHbbftBase", - "src": "contracts/base/BlockRewardHbbftBase.sol:71" - }, - { - "label": "governancePotShareNominator", - "offset": 0, - "slot": "113", - "type": "t_uint256", - "contract": "BlockRewardHbbftBase", - "src": "contracts/base/BlockRewardHbbftBase.sol:75" - }, - { - "label": "governancePotShareDenominator", - "offset": 0, - "slot": "114", - "type": "t_uint256", - "contract": "BlockRewardHbbftBase", - "src": "contracts/base/BlockRewardHbbftBase.sol:79" - }, - { - "label": "connectivityTracker", - "offset": 0, - "slot": "115", - "type": "t_address", - "contract": "BlockRewardHbbftBase", - "src": "contracts/base/BlockRewardHbbftBase.sol:82" - }, - { - "label": "earlyEpochEnd", - "offset": 20, - "slot": "115", - "type": "t_bool", - "contract": "BlockRewardHbbftBase", - "src": "contracts/base/BlockRewardHbbftBase.sol:85" - }, - { - "label": "__gap", - "offset": 0, - "slot": "116", - "type": "t_array(t_uint256)49_storage", - "contract": "BlockRewardHbbftBase", - "src": "contracts/base/BlockRewardHbbftBase.sol:708" - }, - { - "label": "allowedParameterRange", - "offset": 0, - "slot": "165", - "type": "t_mapping(t_bytes4,t_struct(ParameterRange)2905_storage)", - "contract": "BlockRewardHbbft", - "src": "contracts/BlockRewardHbbft.sol:22" - }, - { - "label": "_systemAddress", - "offset": 0, - "slot": "166", - "type": "t_address", - "contract": "BlockRewardHbbftMock", - "src": "contracts/mockContracts/BlockRewardHbbftMock.sol:6" - } - ], - "types": { - "t_address": { - "label": "address", - "numberOfBytes": "20" - }, - "t_address_payable": { - "label": "address payable", - "numberOfBytes": "20" - }, - "t_array(t_uint256)49_storage": { - "label": "uint256[49]", - "numberOfBytes": "1568" - }, - "t_array(t_uint256)50_storage": { - "label": "uint256[50]", - "numberOfBytes": "1600" - }, - "t_array(t_uint256)dyn_storage": { - "label": "uint256[]", - "numberOfBytes": "32" - }, - "t_bool": { - "label": "bool", - "numberOfBytes": "1" - }, - "t_bytes4": { - "label": "bytes4", - "numberOfBytes": "4" - }, - "t_contract(IValidatorSetHbbft)16123": { - "label": "contract IValidatorSetHbbft", - "numberOfBytes": "20" - }, - "t_mapping(t_address,t_array(t_uint256)dyn_storage)": { - "label": "mapping(address => uint256[])", - "numberOfBytes": "32" - }, - "t_mapping(t_address,t_uint256)": { - "label": "mapping(address => uint256)", - "numberOfBytes": "32" - }, - "t_mapping(t_bytes4,t_struct(ParameterRange)2905_storage)": { - "label": "mapping(bytes4 => struct BlockRewardHbbft.ParameterRange)", - "numberOfBytes": "32" - }, - "t_mapping(t_uint256,t_mapping(t_address,t_uint256))": { - "label": "mapping(uint256 => mapping(address => uint256))", - "numberOfBytes": "32" - }, - "t_mapping(t_uint256,t_uint256)": { - "label": "mapping(uint256 => uint256)", - "numberOfBytes": "32" - }, - "t_struct(ParameterRange)2905_storage": { - "label": "struct BlockRewardHbbft.ParameterRange", - "members": [ - { - "label": "getter", - "type": "t_bytes4", - "offset": 0, - "slot": "0" - }, - { - "label": "range", - "type": "t_array(t_uint256)dyn_storage", - "offset": 0, - "slot": "1" - } - ], - "numberOfBytes": "64" - }, - "t_uint256": { - "label": "uint256", - "numberOfBytes": "32" - }, - "t_uint8": { - "label": "uint8", - "numberOfBytes": "1" - } - } - } - }, - "4f745b8d0844d91b3bd5bec066ed74156a99d05e0d34b22662e4cd9788a255ef": { - "address": "0x2761bFE3b693DCB2bAc4d6937522C3B7Cb782c3A", - "txHash": "0x018cfab35288b8b1ffc331899f8260100b023074f1d45ac8bd5cea295616e439", - "layout": { - "solcVersion": "0.8.17", - "storage": [ - { - "label": "_initialized", - "offset": 0, - "slot": "0", - "type": "t_uint8", - "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", - "retypedFrom": "bool" - }, - { - "label": "_initializing", - "offset": 1, - "slot": "0", - "type": "t_bool", - "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" - }, - { - "label": "__gap", - "offset": 0, - "slot": "1", - "type": "t_array(t_uint256)50_storage", - "contract": "ContextUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" - }, - { - "label": "_owner", - "offset": 0, - "slot": "51", - "type": "t_address", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" - }, - { - "label": "__gap", - "offset": 0, - "slot": "52", - "type": "t_array(t_uint256)49_storage", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" - }, - { - "label": "_pools", - "offset": 0, - "slot": "101", - "type": "t_array(t_address)dyn_storage", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:17" - }, - { - "label": "_poolsInactive", - "offset": 0, - "slot": "102", - "type": "t_array(t_address)dyn_storage", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:18" - }, - { - "label": "_poolsToBeElected", - "offset": 0, - "slot": "103", - "type": "t_array(t_address)dyn_storage", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:19" - }, - { - "label": "_poolsToBeRemoved", - "offset": 0, - "slot": "104", - "type": "t_array(t_address)dyn_storage", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:20" - }, - { - "label": "_poolsLikelihood", - "offset": 0, - "slot": "105", - "type": "t_array(t_uint256)dyn_storage", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:21" - }, - { - "label": "_poolsLikelihoodSum", - "offset": 0, - "slot": "106", - "type": "t_uint256", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:22" - }, - { - "label": "_poolDelegators", - "offset": 0, - "slot": "107", - "type": "t_mapping(t_address,t_array(t_address)dyn_storage)", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:23" - }, - { - "label": "_poolDelegatorsInactive", - "offset": 0, - "slot": "108", - "type": "t_mapping(t_address,t_array(t_address)dyn_storage)", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:24" - }, - { - "label": "_stakeAmountByEpoch", - "offset": 0, - "slot": "109", - "type": "t_mapping(t_address,t_mapping(t_address,t_mapping(t_uint256,t_uint256)))", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:25" - }, - { - "label": "candidateMinStake", - "offset": 0, - "slot": "110", - "type": "t_uint256", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:29" - }, - { - "label": "delegatorMinStake", - "offset": 0, - "slot": "111", - "type": "t_uint256", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:32" - }, - { - "label": "delegatorStakeSnapshot", - "offset": 0, - "slot": "112", - "type": "t_mapping(t_address,t_mapping(t_address,t_mapping(t_uint256,t_uint256)))", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:38" - }, - { - "label": "orderedWithdrawAmount", - "offset": 0, - "slot": "113", - "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:44" - }, - { - "label": "orderedWithdrawAmountTotal", - "offset": 0, - "slot": "114", - "type": "t_mapping(t_address,t_uint256)", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:49" - }, - { - "label": "orderWithdrawEpoch", - "offset": 0, - "slot": "115", - "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:55" - }, - { - "label": "poolDelegatorIndex", - "offset": 0, - "slot": "116", - "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:62" - }, - { - "label": "poolDelegatorInactiveIndex", - "offset": 0, - "slot": "117", - "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:69" - }, - { - "label": "poolInactiveIndex", - "offset": 0, - "slot": "118", - "type": "t_mapping(t_address,t_uint256)", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:74" - }, - { - "label": "poolIndex", - "offset": 0, - "slot": "119", - "type": "t_mapping(t_address,t_uint256)", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:80" - }, - { - "label": "poolToBeElectedIndex", - "offset": 0, - "slot": "120", - "type": "t_mapping(t_address,t_uint256)", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:87" - }, - { - "label": "poolToBeRemovedIndex", - "offset": 0, - "slot": "121", - "type": "t_mapping(t_address,t_uint256)", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:94" - }, - { - "label": "rewardWasTaken", - "offset": 0, - "slot": "122", - "type": "t_mapping(t_address,t_mapping(t_address,t_mapping(t_uint256,t_bool)))", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:100" - }, - { - "label": "stakeAmount", - "offset": 0, - "slot": "123", - "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:106" - }, - { - "label": "stakeFirstEpoch", - "offset": 0, - "slot": "124", - "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:112" - }, - { - "label": "stakeLastEpoch", - "offset": 0, - "slot": "125", - "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:118" - }, - { - "label": "stakingWithdrawDisallowPeriod", - "offset": 0, - "slot": "126", - "type": "t_uint256", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:122" - }, - { - "label": "stakingEpoch", - "offset": 0, - "slot": "127", - "type": "t_uint256", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:125" - }, - { - "label": "stakingFixedEpochDuration", - "offset": 0, - "slot": "128", - "type": "t_uint256", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:129" - }, - { - "label": "stakingTransitionTimeframeLength", - "offset": 0, - "slot": "129", - "type": "t_uint256", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:132" - }, - { - "label": "stakingEpochStartTime", - "offset": 0, - "slot": "130", - "type": "t_uint256", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:136" - }, - { - "label": "stakingEpochStartBlock", - "offset": 0, - "slot": "131", - "type": "t_uint256", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:143" - }, - { - "label": "currentKeyGenExtraTimeWindow", - "offset": 0, - "slot": "132", - "type": "t_uint256", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:149" - }, - { - "label": "stakeAmountTotal", - "offset": 0, - "slot": "133", - "type": "t_mapping(t_address,t_uint256)", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:154" - }, - { - "label": "validatorSetContract", - "offset": 0, - "slot": "134", - "type": "t_contract(IValidatorSetHbbft)16123", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:157" - }, - { - "label": "poolInfo", - "offset": 0, - "slot": "135", - "type": "t_mapping(t_address,t_struct(PoolInfo)12155_storage)", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:165" - }, - { - "label": "maxStakeAmount", - "offset": 0, - "slot": "136", - "type": "t_uint256", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:169" - }, - { - "label": "abandonedAndRemoved", - "offset": 0, - "slot": "137", - "type": "t_mapping(t_address,t_bool)", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:171" - }, - { - "label": "__gap", - "offset": 0, - "slot": "138", - "type": "t_array(t_uint256)50_storage", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:1692" - }, - { - "label": "allowedParameterRange", - "offset": 0, - "slot": "188", - "type": "t_mapping(t_bytes4,t_struct(ParameterRange)5855_storage)", - "contract": "StakingHbbft", - "src": "contracts/StakingHbbft.sol:30" - }, - { - "label": "validatorSetContractMock", - "offset": 0, - "slot": "189", - "type": "t_contract(IValidatorSetHbbft)16123", - "contract": "StakingHbbftMock", - "src": "contracts/mockContracts/StakingHbbftMock.sol:6" - } - ], - "types": { - "t_address": { - "label": "address", - "numberOfBytes": "20" - }, - "t_array(t_address)dyn_storage": { - "label": "address[]", - "numberOfBytes": "32" - }, - "t_array(t_uint256)49_storage": { - "label": "uint256[49]", - "numberOfBytes": "1568" - }, - "t_array(t_uint256)50_storage": { - "label": "uint256[50]", - "numberOfBytes": "1600" - }, - "t_array(t_uint256)dyn_storage": { - "label": "uint256[]", - "numberOfBytes": "32" - }, - "t_bool": { - "label": "bool", - "numberOfBytes": "1" - }, - "t_bytes16": { - "label": "bytes16", - "numberOfBytes": "16" - }, - "t_bytes2": { - "label": "bytes2", - "numberOfBytes": "2" - }, - "t_bytes4": { - "label": "bytes4", - "numberOfBytes": "4" - }, - "t_bytes_storage": { - "label": "bytes", - "numberOfBytes": "32" - }, - "t_contract(IValidatorSetHbbft)16123": { - "label": "contract IValidatorSetHbbft", - "numberOfBytes": "20" - }, - "t_mapping(t_address,t_array(t_address)dyn_storage)": { - "label": "mapping(address => address[])", - "numberOfBytes": "32" - }, - "t_mapping(t_address,t_bool)": { - "label": "mapping(address => bool)", - "numberOfBytes": "32" - }, - "t_mapping(t_address,t_mapping(t_address,t_mapping(t_uint256,t_bool)))": { - "label": "mapping(address => mapping(address => mapping(uint256 => bool)))", - "numberOfBytes": "32" - }, - "t_mapping(t_address,t_mapping(t_address,t_mapping(t_uint256,t_uint256)))": { - "label": "mapping(address => mapping(address => mapping(uint256 => uint256)))", - "numberOfBytes": "32" - }, - "t_mapping(t_address,t_mapping(t_address,t_uint256))": { - "label": "mapping(address => mapping(address => uint256))", - "numberOfBytes": "32" - }, - "t_mapping(t_address,t_mapping(t_uint256,t_bool))": { - "label": "mapping(address => mapping(uint256 => bool))", - "numberOfBytes": "32" - }, - "t_mapping(t_address,t_mapping(t_uint256,t_uint256))": { - "label": "mapping(address => mapping(uint256 => uint256))", - "numberOfBytes": "32" - }, - "t_mapping(t_address,t_struct(PoolInfo)12155_storage)": { - "label": "mapping(address => struct StakingHbbftBase.PoolInfo)", - "numberOfBytes": "32" - }, - "t_mapping(t_address,t_uint256)": { - "label": "mapping(address => uint256)", - "numberOfBytes": "32" - }, - "t_mapping(t_bytes4,t_struct(ParameterRange)5855_storage)": { - "label": "mapping(bytes4 => struct StakingHbbft.ParameterRange)", - "numberOfBytes": "32" - }, - "t_mapping(t_uint256,t_bool)": { - "label": "mapping(uint256 => bool)", - "numberOfBytes": "32" - }, - "t_mapping(t_uint256,t_uint256)": { - "label": "mapping(uint256 => uint256)", - "numberOfBytes": "32" - }, - "t_struct(ParameterRange)5855_storage": { - "label": "struct StakingHbbft.ParameterRange", - "members": [ - { - "label": "getter", - "type": "t_bytes4", - "offset": 0, - "slot": "0" - }, - { - "label": "range", - "type": "t_array(t_uint256)dyn_storage", - "offset": 0, - "slot": "1" - } - ], - "numberOfBytes": "64" - }, - "t_struct(PoolInfo)12155_storage": { - "label": "struct StakingHbbftBase.PoolInfo", - "members": [ - { - "label": "publicKey", - "type": "t_bytes_storage", - "offset": 0, - "slot": "0" - }, - { - "label": "internetAddress", - "type": "t_bytes16", - "offset": 0, - "slot": "1" - }, - { - "label": "port", - "type": "t_bytes2", - "offset": 16, - "slot": "1" - } - ], - "numberOfBytes": "64" - }, - "t_uint256": { - "label": "uint256", - "numberOfBytes": "32" - }, - "t_uint8": { - "label": "uint8", - "numberOfBytes": "1" - } - } - } - }, - "851ee97e31255d29c3a3bc85602ff3d00e798593270ab1064c0b533d0c1808dc": { - "address": "0xF3dF8Ba2B7696Bf57e2B52EAB320AEdbB2aE22a8", - "txHash": "0x64736d4a4cddcd1af2b6e77aad9c7737807d874dce0488e97ef50ba17d2a4aa5", - "layout": { - "solcVersion": "0.8.17", - "storage": [ - { - "label": "_initialized", - "offset": 0, - "slot": "0", - "type": "t_uint8", - "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", - "retypedFrom": "bool" - }, - { - "label": "_initializing", - "offset": 1, - "slot": "0", - "type": "t_bool", - "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" - }, - { - "label": "__gap", - "offset": 0, - "slot": "1", - "type": "t_array(t_uint256)50_storage", - "contract": "ContextUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" - }, - { - "label": "_owner", - "offset": 0, - "slot": "51", - "type": "t_address", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" - }, - { - "label": "__gap", - "offset": 0, - "slot": "52", - "type": "t_array(t_uint256)49_storage", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" - }, - { - "label": "validatorSetContract", - "offset": 0, - "slot": "101", - "type": "t_contract(IValidatorSetHbbft)16123", - "contract": "ConnectivityTrackerHbbft", - "src": "contracts/ConnectivityTrackerHbbft.sol:22" - }, - { - "label": "stakingContract", - "offset": 0, - "slot": "102", - "type": "t_contract(IStakingHbbft)15906", - "contract": "ConnectivityTrackerHbbft", - "src": "contracts/ConnectivityTrackerHbbft.sol:23" - }, - { - "label": "blockRewardContract", - "offset": 0, - "slot": "103", - "type": "t_contract(IBlockRewardHbbft)15424", - "contract": "ConnectivityTrackerHbbft", - "src": "contracts/ConnectivityTrackerHbbft.sol:24" - }, - { - "label": "minReportAgeBlocks", - "offset": 0, - "slot": "104", - "type": "t_uint256", - "contract": "ConnectivityTrackerHbbft", - "src": "contracts/ConnectivityTrackerHbbft.sol:26" - }, - { - "label": "earlyEpochEndToleranceLevel", - "offset": 0, - "slot": "105", - "type": "t_uint256", - "contract": "ConnectivityTrackerHbbft", - "src": "contracts/ConnectivityTrackerHbbft.sol:27" - }, - { - "label": "isEarlyEpochEnd", - "offset": 0, - "slot": "106", - "type": "t_mapping(t_uint256,t_bool)", - "contract": "ConnectivityTrackerHbbft", - "src": "contracts/ConnectivityTrackerHbbft.sol:29" - }, - { - "label": "_flaggedValidators", - "offset": 0, - "slot": "107", - "type": "t_mapping(t_uint256,t_struct(AddressSet)1136_storage)", - "contract": "ConnectivityTrackerHbbft", - "src": "contracts/ConnectivityTrackerHbbft.sol:31" - }, - { - "label": "_reporters", - "offset": 0, - "slot": "108", - "type": "t_mapping(t_uint256,t_mapping(t_address,t_struct(AddressSet)1136_storage))", - "contract": "ConnectivityTrackerHbbft", - "src": "contracts/ConnectivityTrackerHbbft.sol:32" - } - ], - "types": { - "t_address": { - "label": "address", - "numberOfBytes": "20" - }, - "t_array(t_bytes32)dyn_storage": { - "label": "bytes32[]", - "numberOfBytes": "32" - }, - "t_array(t_uint256)49_storage": { - "label": "uint256[49]", - "numberOfBytes": "1568" - }, - "t_array(t_uint256)50_storage": { - "label": "uint256[50]", - "numberOfBytes": "1600" - }, - "t_bool": { - "label": "bool", - "numberOfBytes": "1" - }, - "t_bytes32": { - "label": "bytes32", - "numberOfBytes": "32" - }, - "t_contract(IBlockRewardHbbft)15424": { - "label": "contract IBlockRewardHbbft", - "numberOfBytes": "20" - }, - "t_contract(IStakingHbbft)15906": { - "label": "contract IStakingHbbft", - "numberOfBytes": "20" - }, - "t_contract(IValidatorSetHbbft)16123": { - "label": "contract IValidatorSetHbbft", - "numberOfBytes": "20" - }, - "t_mapping(t_address,t_struct(AddressSet)1136_storage)": { - "label": "mapping(address => struct EnumerableSetUpgradeable.AddressSet)", - "numberOfBytes": "32" - }, - "t_mapping(t_bytes32,t_uint256)": { - "label": "mapping(bytes32 => uint256)", - "numberOfBytes": "32" - }, - "t_mapping(t_uint256,t_bool)": { - "label": "mapping(uint256 => bool)", - "numberOfBytes": "32" - }, - "t_mapping(t_uint256,t_mapping(t_address,t_struct(AddressSet)1136_storage))": { - "label": "mapping(uint256 => mapping(address => struct EnumerableSetUpgradeable.AddressSet))", - "numberOfBytes": "32" - }, - "t_mapping(t_uint256,t_struct(AddressSet)1136_storage)": { - "label": "mapping(uint256 => struct EnumerableSetUpgradeable.AddressSet)", - "numberOfBytes": "32" - }, - "t_struct(AddressSet)1136_storage": { - "label": "struct EnumerableSetUpgradeable.AddressSet", - "members": [ - { - "label": "_inner", - "type": "t_struct(Set)821_storage", - "offset": 0, - "slot": "0" - } - ], - "numberOfBytes": "64" - }, - "t_struct(Set)821_storage": { - "label": "struct EnumerableSetUpgradeable.Set", - "members": [ - { - "label": "_values", - "type": "t_array(t_bytes32)dyn_storage", - "offset": 0, - "slot": "0" - }, - { - "label": "_indexes", - "type": "t_mapping(t_bytes32,t_uint256)", - "offset": 0, - "slot": "1" - } - ], - "numberOfBytes": "64" - }, - "t_uint256": { - "label": "uint256", - "numberOfBytes": "32" - }, - "t_uint8": { - "label": "uint8", - "numberOfBytes": "1" - } - } - } - }, - "d5e65d8e6ea9b2ce84a2dac7bc5fbff7cdc0e71e4136de896e031da129de9bc3": { - "address": "0xaeee4cF69a7db08DD14006709011D43E19E138a7", - "txHash": "0xd6523e80006b41e863ab6008cc5542906cb8be3c5257eacd5331e440b20319b5", - "layout": { - "solcVersion": "0.8.17", - "storage": [ - { - "label": "_initialized", - "offset": 0, - "slot": "0", - "type": "t_uint8", - "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", - "retypedFrom": "bool" - }, - { - "label": "_initializing", - "offset": 1, - "slot": "0", - "type": "t_bool", - "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" - }, - { - "label": "__gap", - "offset": 0, - "slot": "1", - "type": "t_array(t_uint256)50_storage", - "contract": "ContextUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" - }, - { - "label": "_owner", - "offset": 0, - "slot": "51", - "type": "t_address", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" - }, - { - "label": "__gap", - "offset": 0, - "slot": "52", - "type": "t_array(t_uint256)49_storage", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" - }, - { - "label": "_allowedSenders", - "offset": 0, - "slot": "101", - "type": "t_array(t_address)dyn_storage", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:23" - }, - { - "label": "certifierContract", - "offset": 0, - "slot": "102", - "type": "t_contract(ICertifier)2063", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:26" - }, - { - "label": "keyGenHistoryContract", - "offset": 0, - "slot": "103", - "type": "t_contract(IKeyGenHistory)2154", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:29" - }, - { - "label": "isSenderAllowed", - "offset": 0, - "slot": "104", - "type": "t_mapping(t_address,t_bool)", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:34" - }, - { - "label": "validatorSetContract", - "offset": 0, - "slot": "105", - "type": "t_contract(IValidatorSetHbbft)2563", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:37" - }, - { - "label": "minimumGasPrice", - "offset": 0, - "slot": "106", - "type": "t_uint256", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:41" - }, - { - "label": "blockGasLimit", - "offset": 0, - "slot": "107", - "type": "t_uint256", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:44" - }, - { - "label": "connectivityTracker", - "offset": 0, - "slot": "108", - "type": "t_contract(IConnectivityTrackerHbbft)2113", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:47" - }, - { - "label": "allowedParameterRange", - "offset": 0, - "slot": "109", - "type": "t_mapping(t_bytes4,t_struct(ParameterRange)733_storage)", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:62" - } - ], - "types": { - "t_address": { - "label": "address", - "numberOfBytes": "20" - }, - "t_array(t_address)dyn_storage": { - "label": "address[]", - "numberOfBytes": "32" - }, - "t_array(t_uint256)49_storage": { - "label": "uint256[49]", - "numberOfBytes": "1568" - }, - "t_array(t_uint256)50_storage": { - "label": "uint256[50]", - "numberOfBytes": "1600" - }, - "t_array(t_uint256)dyn_storage": { - "label": "uint256[]", - "numberOfBytes": "32" - }, - "t_bool": { - "label": "bool", - "numberOfBytes": "1" - }, - "t_bytes4": { - "label": "bytes4", - "numberOfBytes": "4" - }, - "t_contract(ICertifier)2063": { - "label": "contract ICertifier", - "numberOfBytes": "20" - }, - "t_contract(IConnectivityTrackerHbbft)2113": { - "label": "contract IConnectivityTrackerHbbft", - "numberOfBytes": "20" - }, - "t_contract(IKeyGenHistory)2154": { - "label": "contract IKeyGenHistory", - "numberOfBytes": "20" - }, - "t_contract(IValidatorSetHbbft)2563": { - "label": "contract IValidatorSetHbbft", - "numberOfBytes": "20" - }, - "t_mapping(t_address,t_bool)": { - "label": "mapping(address => bool)", - "numberOfBytes": "32" - }, - "t_mapping(t_bytes4,t_struct(ParameterRange)733_storage)": { - "label": "mapping(bytes4 => struct TxPermissionHbbft.ParameterRange)", - "numberOfBytes": "32" - }, - "t_struct(ParameterRange)733_storage": { - "label": "struct TxPermissionHbbft.ParameterRange", - "members": [ - { - "label": "getter", - "type": "t_bytes4", - "offset": 0, - "slot": "0" - }, - { - "label": "range", - "type": "t_array(t_uint256)dyn_storage", - "offset": 0, - "slot": "1" - } - ], - "numberOfBytes": "64" - }, - "t_uint256": { - "label": "uint256", - "numberOfBytes": "32" - }, - "t_uint8": { - "label": "uint8", - "numberOfBytes": "1" - } - } - } - }, - "d292f33ddf87882f4fbb41d66e99731876e69ddd00cd0a473894f168aa4c6320": { - "address": "0x38783b83732f872a21EB0D40800DdBFa1F8BBbda", - "txHash": "0x4d2ea9fec8a8d3e3e84afbd5f1eae5c23ca3cf196acddc9ce63d5b89fd4a46c4", - "layout": { - "solcVersion": "0.8.17", - "storage": [ - { - "label": "_initialized", - "offset": 0, - "slot": "0", - "type": "t_uint8", - "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", - "retypedFrom": "bool" - }, - { - "label": "_initializing", - "offset": 1, - "slot": "0", - "type": "t_bool", - "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" - }, - { - "label": "__gap", - "offset": 0, - "slot": "1", - "type": "t_array(t_uint256)50_storage", - "contract": "ContextUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" - }, - { - "label": "_owner", - "offset": 0, - "slot": "51", - "type": "t_address", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" - }, - { - "label": "__gap", - "offset": 0, - "slot": "52", - "type": "t_array(t_uint256)49_storage", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" - }, - { - "label": "_allowedSenders", - "offset": 0, - "slot": "101", - "type": "t_array(t_address)dyn_storage", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:23" - }, - { - "label": "certifierContract", - "offset": 0, - "slot": "102", - "type": "t_contract(ICertifier)2063", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:26" - }, - { - "label": "keyGenHistoryContract", - "offset": 0, - "slot": "103", - "type": "t_contract(IKeyGenHistory)2154", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:29" - }, - { - "label": "isSenderAllowed", - "offset": 0, - "slot": "104", - "type": "t_mapping(t_address,t_bool)", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:34" - }, - { - "label": "validatorSetContract", - "offset": 0, - "slot": "105", - "type": "t_contract(IValidatorSetHbbft)2563", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:37" - }, - { - "label": "minimumGasPrice", - "offset": 0, - "slot": "106", - "type": "t_uint256", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:41" - }, - { - "label": "blockGasLimit", - "offset": 0, - "slot": "107", - "type": "t_uint256", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:44" - }, - { - "label": "connectivityTracker", - "offset": 0, - "slot": "108", - "type": "t_contract(IConnectivityTrackerHbbft)2113", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:47" - }, - { - "label": "allowedParameterRange", - "offset": 0, - "slot": "109", - "type": "t_mapping(t_bytes4,t_struct(ParameterRange)733_storage)", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:62" - } - ], - "types": { - "t_address": { - "label": "address", - "numberOfBytes": "20" - }, - "t_array(t_address)dyn_storage": { - "label": "address[]", - "numberOfBytes": "32" - }, - "t_array(t_uint256)49_storage": { - "label": "uint256[49]", - "numberOfBytes": "1568" - }, - "t_array(t_uint256)50_storage": { - "label": "uint256[50]", - "numberOfBytes": "1600" - }, - "t_array(t_uint256)dyn_storage": { - "label": "uint256[]", - "numberOfBytes": "32" - }, - "t_bool": { - "label": "bool", - "numberOfBytes": "1" - }, - "t_bytes4": { - "label": "bytes4", - "numberOfBytes": "4" - }, - "t_contract(ICertifier)2063": { - "label": "contract ICertifier", - "numberOfBytes": "20" - }, - "t_contract(IConnectivityTrackerHbbft)2113": { - "label": "contract IConnectivityTrackerHbbft", - "numberOfBytes": "20" - }, - "t_contract(IKeyGenHistory)2154": { - "label": "contract IKeyGenHistory", - "numberOfBytes": "20" - }, - "t_contract(IValidatorSetHbbft)2563": { - "label": "contract IValidatorSetHbbft", - "numberOfBytes": "20" - }, - "t_mapping(t_address,t_bool)": { - "label": "mapping(address => bool)", - "numberOfBytes": "32" - }, - "t_mapping(t_bytes4,t_struct(ParameterRange)733_storage)": { - "label": "mapping(bytes4 => struct TxPermissionHbbft.ParameterRange)", - "numberOfBytes": "32" - }, - "t_struct(ParameterRange)733_storage": { - "label": "struct TxPermissionHbbft.ParameterRange", - "members": [ - { - "label": "getter", - "type": "t_bytes4", - "offset": 0, - "slot": "0" - }, - { - "label": "range", - "type": "t_array(t_uint256)dyn_storage", - "offset": 0, - "slot": "1" - } - ], - "numberOfBytes": "64" - }, - "t_uint256": { - "label": "uint256", - "numberOfBytes": "32" - }, - "t_uint8": { - "label": "uint8", - "numberOfBytes": "1" - } - } - } - }, - "f2618fb6f1404cfebe2304d3fd43526c558cbe0fa61335ecfdf7a3e90471ca56": { - "address": "0x991A3d2Ecb9e93031af1FCb2c72Bc48DE275Baba", - "txHash": "0x0f482171c1e6755543743859fa2a632df13fb0ffc631ef42ae43d0ef8f6e8316", - "layout": { - "solcVersion": "0.8.17", - "storage": [ - { - "label": "_initialized", - "offset": 0, - "slot": "0", - "type": "t_uint8", - "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", - "retypedFrom": "bool" - }, - { - "label": "_initializing", - "offset": 1, - "slot": "0", - "type": "t_bool", - "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" - }, - { - "label": "__gap", - "offset": 0, - "slot": "1", - "type": "t_array(t_uint256)50_storage", - "contract": "ContextUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" - }, - { - "label": "_owner", - "offset": 0, - "slot": "51", - "type": "t_address", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" - }, - { - "label": "__gap", - "offset": 0, - "slot": "52", - "type": "t_array(t_uint256)49_storage", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" - }, - { - "label": "_allowedSenders", - "offset": 0, - "slot": "101", - "type": "t_array(t_address)dyn_storage", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:23" - }, - { - "label": "certifierContract", - "offset": 0, - "slot": "102", - "type": "t_contract(ICertifier)2185", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:26" - }, - { - "label": "keyGenHistoryContract", - "offset": 0, - "slot": "103", - "type": "t_contract(IKeyGenHistory)2276", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:29" - }, - { - "label": "isSenderAllowed", - "offset": 0, - "slot": "104", - "type": "t_mapping(t_address,t_bool)", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:34" - }, - { - "label": "validatorSetContract", - "offset": 0, - "slot": "105", - "type": "t_contract(IValidatorSetHbbft)2685", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:37" - }, - { - "label": "minimumGasPrice", - "offset": 0, - "slot": "106", - "type": "t_uint256", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:41" - }, - { - "label": "blockGasLimit", - "offset": 0, - "slot": "107", - "type": "t_uint256", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:44" - }, - { - "label": "connectivityTracker", - "offset": 0, - "slot": "108", - "type": "t_contract(IConnectivityTrackerHbbft)2235", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:47" - }, - { - "label": "allowedParameterRange", - "offset": 0, - "slot": "109", - "type": "t_mapping(t_bytes4,t_struct(ParameterRange)733_storage)", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:62" - } - ], - "types": { - "t_address": { - "label": "address", - "numberOfBytes": "20" - }, - "t_array(t_address)dyn_storage": { - "label": "address[]", - "numberOfBytes": "32" - }, - "t_array(t_uint256)49_storage": { - "label": "uint256[49]", - "numberOfBytes": "1568" - }, - "t_array(t_uint256)50_storage": { - "label": "uint256[50]", - "numberOfBytes": "1600" - }, - "t_array(t_uint256)dyn_storage": { - "label": "uint256[]", - "numberOfBytes": "32" - }, - "t_bool": { - "label": "bool", - "numberOfBytes": "1" - }, - "t_bytes4": { - "label": "bytes4", - "numberOfBytes": "4" - }, - "t_contract(ICertifier)2185": { - "label": "contract ICertifier", - "numberOfBytes": "20" - }, - "t_contract(IConnectivityTrackerHbbft)2235": { - "label": "contract IConnectivityTrackerHbbft", - "numberOfBytes": "20" - }, - "t_contract(IKeyGenHistory)2276": { - "label": "contract IKeyGenHistory", - "numberOfBytes": "20" - }, - "t_contract(IValidatorSetHbbft)2685": { - "label": "contract IValidatorSetHbbft", - "numberOfBytes": "20" - }, - "t_mapping(t_address,t_bool)": { - "label": "mapping(address => bool)", - "numberOfBytes": "32" - }, - "t_mapping(t_bytes4,t_struct(ParameterRange)733_storage)": { - "label": "mapping(bytes4 => struct TxPermissionHbbft.ParameterRange)", - "numberOfBytes": "32" - }, - "t_struct(ParameterRange)733_storage": { - "label": "struct TxPermissionHbbft.ParameterRange", - "members": [ - { - "label": "getter", - "type": "t_bytes4", - "offset": 0, - "slot": "0" - }, - { - "label": "range", - "type": "t_array(t_uint256)dyn_storage", - "offset": 0, - "slot": "1" - } - ], - "numberOfBytes": "64" - }, - "t_uint256": { - "label": "uint256", - "numberOfBytes": "32" - }, - "t_uint8": { - "label": "uint8", - "numberOfBytes": "1" - } - } - } - }, - "ce0de3fbaef6f646a393198698534549b9cf92e74615524d1c21491fda2d8078": { - "address": "0xa761f59fAbE8639ea6253b4b7a5eC5D3b477644b", - "txHash": "0xd23b06992e64bd59f0750505a1249d480bba913ee68c1656bb9b94539db87411", - "layout": { - "solcVersion": "0.8.17", - "storage": [ - { - "label": "_initialized", - "offset": 0, - "slot": "0", - "type": "t_uint8", - "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", - "retypedFrom": "bool" - }, - { - "label": "_initializing", - "offset": 1, - "slot": "0", - "type": "t_bool", - "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" - }, - { - "label": "__gap", - "offset": 0, - "slot": "1", - "type": "t_array(t_uint256)50_storage", - "contract": "ContextUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" - }, - { - "label": "_owner", - "offset": 0, - "slot": "51", - "type": "t_address", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" - }, - { - "label": "__gap", - "offset": 0, - "slot": "52", - "type": "t_array(t_uint256)49_storage", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" - }, - { - "label": "_allowedSenders", - "offset": 0, - "slot": "101", - "type": "t_array(t_address)dyn_storage", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:23" - }, - { - "label": "certifierContract", - "offset": 0, - "slot": "102", - "type": "t_contract(ICertifier)2185", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:26" - }, - { - "label": "keyGenHistoryContract", - "offset": 0, - "slot": "103", - "type": "t_contract(IKeyGenHistory)2276", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:29" - }, - { - "label": "isSenderAllowed", - "offset": 0, - "slot": "104", - "type": "t_mapping(t_address,t_bool)", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:34" - }, - { - "label": "validatorSetContract", - "offset": 0, - "slot": "105", - "type": "t_contract(IValidatorSetHbbft)2685", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:37" - }, - { - "label": "minimumGasPrice", - "offset": 0, - "slot": "106", - "type": "t_uint256", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:41" - }, - { - "label": "blockGasLimit", - "offset": 0, - "slot": "107", - "type": "t_uint256", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:44" - }, - { - "label": "connectivityTracker", - "offset": 0, - "slot": "108", - "type": "t_contract(IConnectivityTrackerHbbft)2235", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:47" - }, - { - "label": "allowedParameterRange", - "offset": 0, - "slot": "109", - "type": "t_mapping(t_bytes4,t_struct(ParameterRange)733_storage)", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:62" - } - ], - "types": { - "t_address": { - "label": "address", - "numberOfBytes": "20" - }, - "t_array(t_address)dyn_storage": { - "label": "address[]", - "numberOfBytes": "32" - }, - "t_array(t_uint256)49_storage": { - "label": "uint256[49]", - "numberOfBytes": "1568" - }, - "t_array(t_uint256)50_storage": { - "label": "uint256[50]", - "numberOfBytes": "1600" - }, - "t_array(t_uint256)dyn_storage": { - "label": "uint256[]", - "numberOfBytes": "32" - }, - "t_bool": { - "label": "bool", - "numberOfBytes": "1" - }, - "t_bytes4": { - "label": "bytes4", - "numberOfBytes": "4" - }, - "t_contract(ICertifier)2185": { - "label": "contract ICertifier", - "numberOfBytes": "20" - }, - "t_contract(IConnectivityTrackerHbbft)2235": { - "label": "contract IConnectivityTrackerHbbft", - "numberOfBytes": "20" - }, - "t_contract(IKeyGenHistory)2276": { - "label": "contract IKeyGenHistory", - "numberOfBytes": "20" - }, - "t_contract(IValidatorSetHbbft)2685": { - "label": "contract IValidatorSetHbbft", - "numberOfBytes": "20" - }, - "t_mapping(t_address,t_bool)": { - "label": "mapping(address => bool)", - "numberOfBytes": "32" - }, - "t_mapping(t_bytes4,t_struct(ParameterRange)733_storage)": { - "label": "mapping(bytes4 => struct TxPermissionHbbft.ParameterRange)", - "numberOfBytes": "32" - }, - "t_struct(ParameterRange)733_storage": { - "label": "struct TxPermissionHbbft.ParameterRange", - "members": [ - { - "label": "getter", - "type": "t_bytes4", - "offset": 0, - "slot": "0" - }, - { - "label": "range", - "type": "t_array(t_uint256)dyn_storage", - "offset": 0, - "slot": "1" - } - ], - "numberOfBytes": "64" - }, - "t_uint256": { - "label": "uint256", - "numberOfBytes": "32" - }, - "t_uint8": { - "label": "uint8", - "numberOfBytes": "1" - } - } - } - }, - "de8214b53258524ce811d21da286245a9dc5ae3e0107b6df51f658e033aff88d": { - "address": "0x6B48E257d56F57961C19608991a0C02327C5C3Ba", - "txHash": "0x37029151faa5ea37600a369b8d7e1040b237045bb32fb8d720c6428e25c88e36", - "layout": { - "solcVersion": "0.8.17", - "storage": [ - { - "label": "_initialized", - "offset": 0, - "slot": "0", - "type": "t_uint8", - "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", - "retypedFrom": "bool" - }, - { - "label": "_initializing", - "offset": 1, - "slot": "0", - "type": "t_bool", - "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" - }, - { - "label": "__gap", - "offset": 0, - "slot": "1", - "type": "t_array(t_uint256)50_storage", - "contract": "ContextUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" - }, - { - "label": "_owner", - "offset": 0, - "slot": "51", - "type": "t_address", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" - }, - { - "label": "__gap", - "offset": 0, - "slot": "52", - "type": "t_array(t_uint256)49_storage", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" - }, - { - "label": "_allowedSenders", - "offset": 0, - "slot": "101", - "type": "t_array(t_address)dyn_storage", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:23" - }, - { - "label": "certifierContract", - "offset": 0, - "slot": "102", - "type": "t_contract(ICertifier)2185", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:26" - }, - { - "label": "keyGenHistoryContract", - "offset": 0, - "slot": "103", - "type": "t_contract(IKeyGenHistory)2276", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:29" - }, - { - "label": "isSenderAllowed", - "offset": 0, - "slot": "104", - "type": "t_mapping(t_address,t_bool)", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:34" - }, - { - "label": "validatorSetContract", - "offset": 0, - "slot": "105", - "type": "t_contract(IValidatorSetHbbft)2685", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:37" - }, - { - "label": "minimumGasPrice", - "offset": 0, - "slot": "106", - "type": "t_uint256", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:41" - }, - { - "label": "blockGasLimit", - "offset": 0, - "slot": "107", - "type": "t_uint256", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:44" - }, - { - "label": "connectivityTracker", - "offset": 0, - "slot": "108", - "type": "t_contract(IConnectivityTrackerHbbft)2235", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:47" - }, - { - "label": "allowedParameterRange", - "offset": 0, - "slot": "109", - "type": "t_mapping(t_bytes4,t_struct(ParameterRange)733_storage)", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:62" - } - ], - "types": { - "t_address": { - "label": "address", - "numberOfBytes": "20" - }, - "t_array(t_address)dyn_storage": { - "label": "address[]", - "numberOfBytes": "32" - }, - "t_array(t_uint256)49_storage": { - "label": "uint256[49]", - "numberOfBytes": "1568" - }, - "t_array(t_uint256)50_storage": { - "label": "uint256[50]", - "numberOfBytes": "1600" - }, - "t_array(t_uint256)dyn_storage": { - "label": "uint256[]", - "numberOfBytes": "32" - }, - "t_bool": { - "label": "bool", - "numberOfBytes": "1" - }, - "t_bytes4": { - "label": "bytes4", - "numberOfBytes": "4" - }, - "t_contract(ICertifier)2185": { - "label": "contract ICertifier", - "numberOfBytes": "20" - }, - "t_contract(IConnectivityTrackerHbbft)2235": { - "label": "contract IConnectivityTrackerHbbft", - "numberOfBytes": "20" - }, - "t_contract(IKeyGenHistory)2276": { - "label": "contract IKeyGenHistory", - "numberOfBytes": "20" - }, - "t_contract(IValidatorSetHbbft)2685": { - "label": "contract IValidatorSetHbbft", - "numberOfBytes": "20" - }, - "t_mapping(t_address,t_bool)": { - "label": "mapping(address => bool)", - "numberOfBytes": "32" - }, - "t_mapping(t_bytes4,t_struct(ParameterRange)733_storage)": { - "label": "mapping(bytes4 => struct TxPermissionHbbft.ParameterRange)", - "numberOfBytes": "32" - }, - "t_struct(ParameterRange)733_storage": { - "label": "struct TxPermissionHbbft.ParameterRange", - "members": [ - { - "label": "getter", - "type": "t_bytes4", - "offset": 0, - "slot": "0" - }, - { - "label": "range", - "type": "t_array(t_uint256)dyn_storage", - "offset": 0, - "slot": "1" - } - ], - "numberOfBytes": "64" - }, - "t_uint256": { - "label": "uint256", - "numberOfBytes": "32" - }, - "t_uint8": { - "label": "uint8", - "numberOfBytes": "1" - } - } - } - }, - "ab95067189e4bc3e324d38b3e3bd048e939b0faa75fe7ebfecfc08dbf212642a": { - "address": "0x38c1FAA41A8D7929bdc9Ab03e86E08261842943E", - "txHash": "0xc525ce82a16a0832a13729016a7ce94a048fcd0b7f2fbd7f9bed0f10a4b9a1b7", - "layout": { - "solcVersion": "0.8.17", - "storage": [ - { - "label": "_initialized", - "offset": 0, - "slot": "0", - "type": "t_uint8", - "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", - "retypedFrom": "bool" - }, - { - "label": "_initializing", - "offset": 1, - "slot": "0", - "type": "t_bool", - "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" - }, - { - "label": "__gap", - "offset": 0, - "slot": "1", - "type": "t_array(t_uint256)50_storage", - "contract": "ContextUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" - }, - { - "label": "_owner", - "offset": 0, - "slot": "51", - "type": "t_address", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" - }, - { - "label": "__gap", - "offset": 0, - "slot": "52", - "type": "t_array(t_uint256)49_storage", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" - }, - { - "label": "_allowedSenders", - "offset": 0, - "slot": "101", - "type": "t_array(t_address)dyn_storage", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:23" - }, - { - "label": "certifierContract", - "offset": 0, - "slot": "102", - "type": "t_contract(ICertifier)2223", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:26" - }, - { - "label": "keyGenHistoryContract", - "offset": 0, - "slot": "103", - "type": "t_contract(IKeyGenHistory)2314", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:29" - }, - { - "label": "isSenderAllowed", - "offset": 0, - "slot": "104", - "type": "t_mapping(t_address,t_bool)", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:34" - }, - { - "label": "validatorSetContract", - "offset": 0, - "slot": "105", - "type": "t_contract(IValidatorSetHbbft)2723", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:37" - }, - { - "label": "minimumGasPrice", - "offset": 0, - "slot": "106", - "type": "t_uint256", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:41" - }, - { - "label": "blockGasLimit", - "offset": 0, - "slot": "107", - "type": "t_uint256", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:44" - }, - { - "label": "connectivityTracker", - "offset": 0, - "slot": "108", - "type": "t_contract(IConnectivityTrackerHbbft)2273", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:47" - }, - { - "label": "allowedParameterRange", - "offset": 0, - "slot": "109", - "type": "t_mapping(t_bytes4,t_struct(ParameterRange)733_storage)", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:62" - } - ], - "types": { - "t_address": { - "label": "address", - "numberOfBytes": "20" - }, - "t_array(t_address)dyn_storage": { - "label": "address[]", - "numberOfBytes": "32" - }, - "t_array(t_uint256)49_storage": { - "label": "uint256[49]", - "numberOfBytes": "1568" - }, - "t_array(t_uint256)50_storage": { - "label": "uint256[50]", - "numberOfBytes": "1600" - }, - "t_array(t_uint256)dyn_storage": { - "label": "uint256[]", - "numberOfBytes": "32" - }, - "t_bool": { - "label": "bool", - "numberOfBytes": "1" - }, - "t_bytes4": { - "label": "bytes4", - "numberOfBytes": "4" - }, - "t_contract(ICertifier)2223": { - "label": "contract ICertifier", - "numberOfBytes": "20" - }, - "t_contract(IConnectivityTrackerHbbft)2273": { - "label": "contract IConnectivityTrackerHbbft", - "numberOfBytes": "20" - }, - "t_contract(IKeyGenHistory)2314": { - "label": "contract IKeyGenHistory", - "numberOfBytes": "20" - }, - "t_contract(IValidatorSetHbbft)2723": { - "label": "contract IValidatorSetHbbft", - "numberOfBytes": "20" - }, - "t_mapping(t_address,t_bool)": { - "label": "mapping(address => bool)", - "numberOfBytes": "32" - }, - "t_mapping(t_bytes4,t_struct(ParameterRange)733_storage)": { - "label": "mapping(bytes4 => struct TxPermissionHbbft.ParameterRange)", - "numberOfBytes": "32" - }, - "t_struct(ParameterRange)733_storage": { - "label": "struct TxPermissionHbbft.ParameterRange", - "members": [ - { - "label": "getter", - "type": "t_bytes4", - "offset": 0, - "slot": "0" - }, - { - "label": "range", - "type": "t_array(t_uint256)dyn_storage", - "offset": 0, - "slot": "1" - } - ], - "numberOfBytes": "64" - }, - "t_uint256": { - "label": "uint256", - "numberOfBytes": "32" - }, - "t_uint8": { - "label": "uint8", - "numberOfBytes": "1" - } - } - } - }, - "da6bcfa3869bfc28c84c9f48f2845583fe13ddc983566d7725b731179b167678": { - "address": "0x5d7425e9aDDaA4b6C27F62FbAEBB12656D6f985c", - "txHash": "0x7b36996cc51859ddcbb94600519acbd8e92c32735d058fb5eec7f65aded4e18a", - "layout": { - "solcVersion": "0.8.17", - "storage": [ - { - "label": "_initialized", - "offset": 0, - "slot": "0", - "type": "t_uint8", - "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", - "retypedFrom": "bool" - }, - { - "label": "_initializing", - "offset": 1, - "slot": "0", - "type": "t_bool", - "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" - }, - { - "label": "__gap", - "offset": 0, - "slot": "1", - "type": "t_array(t_uint256)50_storage", - "contract": "ContextUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" - }, - { - "label": "_owner", - "offset": 0, - "slot": "51", - "type": "t_address", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" - }, - { - "label": "__gap", - "offset": 0, - "slot": "52", - "type": "t_array(t_uint256)49_storage", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" - }, - { - "label": "_allowedSenders", - "offset": 0, - "slot": "101", - "type": "t_array(t_address)dyn_storage", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:23" - }, - { - "label": "certifierContract", - "offset": 0, - "slot": "102", - "type": "t_contract(ICertifier)2223", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:26" - }, - { - "label": "keyGenHistoryContract", - "offset": 0, - "slot": "103", - "type": "t_contract(IKeyGenHistory)2314", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:29" - }, - { - "label": "isSenderAllowed", - "offset": 0, - "slot": "104", - "type": "t_mapping(t_address,t_bool)", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:34" - }, - { - "label": "validatorSetContract", - "offset": 0, - "slot": "105", - "type": "t_contract(IValidatorSetHbbft)2723", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:37" - }, - { - "label": "minimumGasPrice", - "offset": 0, - "slot": "106", - "type": "t_uint256", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:41" - }, - { - "label": "blockGasLimit", - "offset": 0, - "slot": "107", - "type": "t_uint256", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:44" - }, - { - "label": "connectivityTracker", - "offset": 0, - "slot": "108", - "type": "t_contract(IConnectivityTrackerHbbft)2273", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:47" - }, - { - "label": "allowedParameterRange", - "offset": 0, - "slot": "109", - "type": "t_mapping(t_bytes4,t_struct(ParameterRange)733_storage)", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:62" - } - ], - "types": { - "t_address": { - "label": "address", - "numberOfBytes": "20" - }, - "t_array(t_address)dyn_storage": { - "label": "address[]", - "numberOfBytes": "32" - }, - "t_array(t_uint256)49_storage": { - "label": "uint256[49]", - "numberOfBytes": "1568" - }, - "t_array(t_uint256)50_storage": { - "label": "uint256[50]", - "numberOfBytes": "1600" - }, - "t_array(t_uint256)dyn_storage": { - "label": "uint256[]", - "numberOfBytes": "32" - }, - "t_bool": { - "label": "bool", - "numberOfBytes": "1" - }, - "t_bytes4": { - "label": "bytes4", - "numberOfBytes": "4" - }, - "t_contract(ICertifier)2223": { - "label": "contract ICertifier", - "numberOfBytes": "20" - }, - "t_contract(IConnectivityTrackerHbbft)2273": { - "label": "contract IConnectivityTrackerHbbft", - "numberOfBytes": "20" - }, - "t_contract(IKeyGenHistory)2314": { - "label": "contract IKeyGenHistory", - "numberOfBytes": "20" - }, - "t_contract(IValidatorSetHbbft)2723": { - "label": "contract IValidatorSetHbbft", - "numberOfBytes": "20" - }, - "t_mapping(t_address,t_bool)": { - "label": "mapping(address => bool)", - "numberOfBytes": "32" - }, - "t_mapping(t_bytes4,t_struct(ParameterRange)733_storage)": { - "label": "mapping(bytes4 => struct TxPermissionHbbft.ParameterRange)", - "numberOfBytes": "32" - }, - "t_struct(ParameterRange)733_storage": { - "label": "struct TxPermissionHbbft.ParameterRange", - "members": [ - { - "label": "getter", - "type": "t_bytes4", - "offset": 0, - "slot": "0" - }, - { - "label": "range", - "type": "t_array(t_uint256)dyn_storage", - "offset": 0, - "slot": "1" - } - ], - "numberOfBytes": "64" - }, - "t_uint256": { - "label": "uint256", - "numberOfBytes": "32" - }, - "t_uint8": { - "label": "uint8", - "numberOfBytes": "1" - } - } - } - }, - "ef3e467b3dfac108c04c5c5469d46fb6d1f7552e9ff256aa9195f54484fae6f0": { - "address": "0x76f45d132b1F2a460DF1A6D753e0d3b95756aE57", - "txHash": "0xef34faec2596f907757ba5702186c2113ddb81694c96d47a587bcf89675fab68", - "layout": { - "solcVersion": "0.8.17", - "storage": [ - { - "label": "_initialized", - "offset": 0, - "slot": "0", - "type": "t_uint8", - "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", - "retypedFrom": "bool" - }, - { - "label": "_initializing", - "offset": 1, - "slot": "0", - "type": "t_bool", - "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" - }, - { - "label": "__gap", - "offset": 0, - "slot": "1", - "type": "t_array(t_uint256)50_storage", - "contract": "ContextUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" - }, - { - "label": "_owner", - "offset": 0, - "slot": "51", - "type": "t_address", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" - }, - { - "label": "__gap", - "offset": 0, - "slot": "52", - "type": "t_array(t_uint256)49_storage", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" - }, - { - "label": "_allowedSenders", - "offset": 0, - "slot": "101", - "type": "t_array(t_address)dyn_storage", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:23" - }, - { - "label": "certifierContract", - "offset": 0, - "slot": "102", - "type": "t_contract(ICertifier)2223", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:26" - }, - { - "label": "keyGenHistoryContract", - "offset": 0, - "slot": "103", - "type": "t_contract(IKeyGenHistory)2314", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:29" - }, - { - "label": "isSenderAllowed", - "offset": 0, - "slot": "104", - "type": "t_mapping(t_address,t_bool)", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:34" - }, - { - "label": "validatorSetContract", - "offset": 0, - "slot": "105", - "type": "t_contract(IValidatorSetHbbft)2723", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:37" - }, - { - "label": "minimumGasPrice", - "offset": 0, - "slot": "106", - "type": "t_uint256", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:41" - }, - { - "label": "blockGasLimit", - "offset": 0, - "slot": "107", - "type": "t_uint256", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:44" - }, - { - "label": "connectivityTracker", - "offset": 0, - "slot": "108", - "type": "t_contract(IConnectivityTrackerHbbft)2273", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:47" - }, - { - "label": "allowedParameterRange", - "offset": 0, - "slot": "109", - "type": "t_mapping(t_bytes4,t_struct(ParameterRange)733_storage)", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:62" - } - ], - "types": { - "t_address": { - "label": "address", - "numberOfBytes": "20" - }, - "t_array(t_address)dyn_storage": { - "label": "address[]", - "numberOfBytes": "32" - }, - "t_array(t_uint256)49_storage": { - "label": "uint256[49]", - "numberOfBytes": "1568" - }, - "t_array(t_uint256)50_storage": { - "label": "uint256[50]", - "numberOfBytes": "1600" - }, - "t_array(t_uint256)dyn_storage": { - "label": "uint256[]", - "numberOfBytes": "32" - }, - "t_bool": { - "label": "bool", - "numberOfBytes": "1" - }, - "t_bytes4": { - "label": "bytes4", - "numberOfBytes": "4" - }, - "t_contract(ICertifier)2223": { - "label": "contract ICertifier", - "numberOfBytes": "20" - }, - "t_contract(IConnectivityTrackerHbbft)2273": { - "label": "contract IConnectivityTrackerHbbft", - "numberOfBytes": "20" - }, - "t_contract(IKeyGenHistory)2314": { - "label": "contract IKeyGenHistory", - "numberOfBytes": "20" - }, - "t_contract(IValidatorSetHbbft)2723": { - "label": "contract IValidatorSetHbbft", - "numberOfBytes": "20" - }, - "t_mapping(t_address,t_bool)": { - "label": "mapping(address => bool)", - "numberOfBytes": "32" - }, - "t_mapping(t_bytes4,t_struct(ParameterRange)733_storage)": { - "label": "mapping(bytes4 => struct TxPermissionHbbft.ParameterRange)", - "numberOfBytes": "32" - }, - "t_struct(ParameterRange)733_storage": { - "label": "struct TxPermissionHbbft.ParameterRange", - "members": [ - { - "label": "getter", - "type": "t_bytes4", - "offset": 0, - "slot": "0" - }, - { - "label": "range", - "type": "t_array(t_uint256)dyn_storage", - "offset": 0, - "slot": "1" - } - ], - "numberOfBytes": "64" - }, - "t_uint256": { - "label": "uint256", - "numberOfBytes": "32" - }, - "t_uint8": { - "label": "uint8", - "numberOfBytes": "1" - } - } - } - }, - "54214412b62a567b3451a3c5b8fb327c4aa0ced8adad8406fb65efd6fceb1542": { - "address": "0x7fc2c7c9789C1887edfcbf55a23f657b10361DeF", - "txHash": "0xbe97378067ac832ce108b345f194bb3d6509d1cc14e2e9a3f96b272df9c045b7", - "layout": { - "solcVersion": "0.8.17", - "storage": [ - { - "label": "_initialized", - "offset": 0, - "slot": "0", - "type": "t_uint8", - "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", - "retypedFrom": "bool" - }, - { - "label": "_initializing", - "offset": 1, - "slot": "0", - "type": "t_bool", - "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" - }, - { - "label": "__gap", - "offset": 0, - "slot": "1", - "type": "t_array(t_uint256)50_storage", - "contract": "ContextUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" - }, - { - "label": "_owner", - "offset": 0, - "slot": "51", - "type": "t_address", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" - }, - { - "label": "__gap", - "offset": 0, - "slot": "52", - "type": "t_array(t_uint256)49_storage", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" - }, - { - "label": "_allowedSenders", - "offset": 0, - "slot": "101", - "type": "t_array(t_address)dyn_storage", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:23" - }, - { - "label": "certifierContract", - "offset": 0, - "slot": "102", - "type": "t_contract(ICertifier)2223", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:26" - }, - { - "label": "keyGenHistoryContract", - "offset": 0, - "slot": "103", - "type": "t_contract(IKeyGenHistory)2314", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:29" - }, - { - "label": "isSenderAllowed", - "offset": 0, - "slot": "104", - "type": "t_mapping(t_address,t_bool)", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:34" - }, - { - "label": "validatorSetContract", - "offset": 0, - "slot": "105", - "type": "t_contract(IValidatorSetHbbft)2723", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:37" - }, - { - "label": "minimumGasPrice", - "offset": 0, - "slot": "106", - "type": "t_uint256", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:41" - }, - { - "label": "blockGasLimit", - "offset": 0, - "slot": "107", - "type": "t_uint256", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:44" - }, - { - "label": "connectivityTracker", - "offset": 0, - "slot": "108", - "type": "t_contract(IConnectivityTrackerHbbft)2273", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:47" - }, - { - "label": "allowedParameterRange", - "offset": 0, - "slot": "109", - "type": "t_mapping(t_bytes4,t_struct(ParameterRange)733_storage)", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:62" - } - ], - "types": { - "t_address": { - "label": "address", - "numberOfBytes": "20" - }, - "t_array(t_address)dyn_storage": { - "label": "address[]", - "numberOfBytes": "32" - }, - "t_array(t_uint256)49_storage": { - "label": "uint256[49]", - "numberOfBytes": "1568" - }, - "t_array(t_uint256)50_storage": { - "label": "uint256[50]", - "numberOfBytes": "1600" - }, - "t_array(t_uint256)dyn_storage": { - "label": "uint256[]", - "numberOfBytes": "32" - }, - "t_bool": { - "label": "bool", - "numberOfBytes": "1" - }, - "t_bytes4": { - "label": "bytes4", - "numberOfBytes": "4" - }, - "t_contract(ICertifier)2223": { - "label": "contract ICertifier", - "numberOfBytes": "20" - }, - "t_contract(IConnectivityTrackerHbbft)2273": { - "label": "contract IConnectivityTrackerHbbft", - "numberOfBytes": "20" - }, - "t_contract(IKeyGenHistory)2314": { - "label": "contract IKeyGenHistory", - "numberOfBytes": "20" - }, - "t_contract(IValidatorSetHbbft)2723": { - "label": "contract IValidatorSetHbbft", - "numberOfBytes": "20" - }, - "t_mapping(t_address,t_bool)": { - "label": "mapping(address => bool)", - "numberOfBytes": "32" - }, - "t_mapping(t_bytes4,t_struct(ParameterRange)733_storage)": { - "label": "mapping(bytes4 => struct TxPermissionHbbft.ParameterRange)", - "numberOfBytes": "32" - }, - "t_struct(ParameterRange)733_storage": { - "label": "struct TxPermissionHbbft.ParameterRange", - "members": [ - { - "label": "getter", - "type": "t_bytes4", - "offset": 0, - "slot": "0" - }, - { - "label": "range", - "type": "t_array(t_uint256)dyn_storage", - "offset": 0, - "slot": "1" - } - ], - "numberOfBytes": "64" - }, - "t_uint256": { - "label": "uint256", - "numberOfBytes": "32" - }, - "t_uint8": { - "label": "uint8", - "numberOfBytes": "1" - } - } - } - }, - "fff961b154d5e6c7e32011c839c5a13b56fe423755511bf9f13984b4b414f942": { - "address": "0x617c05F90f82FC2Ca85Fd5c5eaD91Dd92B31F5d1", - "txHash": "0xe2dfcf2d295f6744b5deb6fce1fb30e1756237a1a5c1e93d7d151e4c5698feb3", - "layout": { - "solcVersion": "0.8.17", - "storage": [ - { - "label": "_initialized", - "offset": 0, - "slot": "0", - "type": "t_uint8", - "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", - "retypedFrom": "bool" - }, - { - "label": "_initializing", - "offset": 1, - "slot": "0", - "type": "t_bool", - "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" - }, - { - "label": "__gap", - "offset": 0, - "slot": "1", - "type": "t_array(t_uint256)50_storage", - "contract": "ContextUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" - }, - { - "label": "_owner", - "offset": 0, - "slot": "51", - "type": "t_address", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" - }, - { - "label": "__gap", - "offset": 0, - "slot": "52", - "type": "t_array(t_uint256)49_storage", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" - }, - { - "label": "_allowedSenders", - "offset": 0, - "slot": "101", - "type": "t_array(t_address)dyn_storage", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:23" - }, - { - "label": "certifierContract", - "offset": 0, - "slot": "102", - "type": "t_contract(ICertifier)2223", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:26" - }, - { - "label": "keyGenHistoryContract", - "offset": 0, - "slot": "103", - "type": "t_contract(IKeyGenHistory)2314", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:29" - }, - { - "label": "isSenderAllowed", - "offset": 0, - "slot": "104", - "type": "t_mapping(t_address,t_bool)", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:34" - }, - { - "label": "validatorSetContract", - "offset": 0, - "slot": "105", - "type": "t_contract(IValidatorSetHbbft)2723", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:37" - }, - { - "label": "minimumGasPrice", - "offset": 0, - "slot": "106", - "type": "t_uint256", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:41" - }, - { - "label": "blockGasLimit", - "offset": 0, - "slot": "107", - "type": "t_uint256", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:44" - }, - { - "label": "connectivityTracker", - "offset": 0, - "slot": "108", - "type": "t_contract(IConnectivityTrackerHbbft)2273", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:47" - }, - { - "label": "allowedParameterRange", - "offset": 0, - "slot": "109", - "type": "t_mapping(t_bytes4,t_struct(ParameterRange)733_storage)", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:62" - } - ], - "types": { - "t_address": { - "label": "address", - "numberOfBytes": "20" - }, - "t_array(t_address)dyn_storage": { - "label": "address[]", - "numberOfBytes": "32" - }, - "t_array(t_uint256)49_storage": { - "label": "uint256[49]", - "numberOfBytes": "1568" - }, - "t_array(t_uint256)50_storage": { - "label": "uint256[50]", - "numberOfBytes": "1600" - }, - "t_array(t_uint256)dyn_storage": { - "label": "uint256[]", - "numberOfBytes": "32" - }, - "t_bool": { - "label": "bool", - "numberOfBytes": "1" - }, - "t_bytes4": { - "label": "bytes4", - "numberOfBytes": "4" - }, - "t_contract(ICertifier)2223": { - "label": "contract ICertifier", - "numberOfBytes": "20" - }, - "t_contract(IConnectivityTrackerHbbft)2273": { - "label": "contract IConnectivityTrackerHbbft", - "numberOfBytes": "20" - }, - "t_contract(IKeyGenHistory)2314": { - "label": "contract IKeyGenHistory", - "numberOfBytes": "20" - }, - "t_contract(IValidatorSetHbbft)2723": { - "label": "contract IValidatorSetHbbft", - "numberOfBytes": "20" - }, - "t_mapping(t_address,t_bool)": { - "label": "mapping(address => bool)", - "numberOfBytes": "32" - }, - "t_mapping(t_bytes4,t_struct(ParameterRange)733_storage)": { - "label": "mapping(bytes4 => struct TxPermissionHbbft.ParameterRange)", - "numberOfBytes": "32" - }, - "t_struct(ParameterRange)733_storage": { - "label": "struct TxPermissionHbbft.ParameterRange", - "members": [ - { - "label": "getter", - "type": "t_bytes4", - "offset": 0, - "slot": "0" - }, - { - "label": "range", - "type": "t_array(t_uint256)dyn_storage", - "offset": 0, - "slot": "1" - } - ], - "numberOfBytes": "64" - }, - "t_uint256": { - "label": "uint256", - "numberOfBytes": "32" - }, - "t_uint8": { - "label": "uint8", - "numberOfBytes": "1" - } - } - } - }, - "7e9ab50ab4ac75293c410028d69b2eb9662e17bad978ed031f983101fe38cb11": { - "address": "0x192F81DC544EE88e9FE5cD87cB6db481fECB9BBb", - "txHash": "0x5708656b8e053733573c8b90994d4280c41eb2e5891f2a839322eeb1ee30437e", - "layout": { - "solcVersion": "0.8.17", - "storage": [ - { - "label": "_initialized", - "offset": 0, - "slot": "0", - "type": "t_uint8", - "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", - "retypedFrom": "bool" - }, - { - "label": "_initializing", - "offset": 1, - "slot": "0", - "type": "t_bool", - "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" - }, - { - "label": "__gap", - "offset": 0, - "slot": "1", - "type": "t_array(t_uint256)50_storage", - "contract": "ContextUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" - }, - { - "label": "_owner", - "offset": 0, - "slot": "51", - "type": "t_address", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" - }, - { - "label": "__gap", - "offset": 0, - "slot": "52", - "type": "t_array(t_uint256)49_storage", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" - }, - { - "label": "allowedParameterRange", - "offset": 0, - "slot": "101", - "type": "t_mapping(t_bytes4,t_struct(ParameterRange)1966_storage)", - "contract": "ValueGuards", - "src": "contracts/ValueGuards.sol:39" - }, - { - "label": "_allowedSenders", - "offset": 0, - "slot": "102", - "type": "t_array(t_address)dyn_storage", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:24" - }, - { - "label": "certifierContract", - "offset": 0, - "slot": "103", - "type": "t_contract(ICertifier)2226", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:27" - }, - { - "label": "keyGenHistoryContract", - "offset": 0, - "slot": "104", - "type": "t_contract(IKeyGenHistory)2317", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:30" - }, - { - "label": "isSenderAllowed", - "offset": 0, - "slot": "105", - "type": "t_mapping(t_address,t_bool)", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:35" - }, - { - "label": "validatorSetContract", - "offset": 0, - "slot": "106", - "type": "t_contract(IValidatorSetHbbft)2726", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:38" - }, - { - "label": "minimumGasPrice", - "offset": 0, - "slot": "107", - "type": "t_uint256", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:42" - }, - { - "label": "blockGasLimit", - "offset": 0, - "slot": "108", - "type": "t_uint256", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:45" - }, - { - "label": "connectivityTracker", - "offset": 0, - "slot": "109", - "type": "t_contract(IConnectivityTrackerHbbft)2276", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:48" - } - ], - "types": { - "t_address": { - "label": "address", - "numberOfBytes": "20" - }, - "t_array(t_address)dyn_storage": { - "label": "address[]", - "numberOfBytes": "32" - }, - "t_array(t_uint256)49_storage": { - "label": "uint256[49]", - "numberOfBytes": "1568" - }, - "t_array(t_uint256)50_storage": { - "label": "uint256[50]", - "numberOfBytes": "1600" - }, - "t_array(t_uint256)dyn_storage": { - "label": "uint256[]", - "numberOfBytes": "32" - }, - "t_bool": { - "label": "bool", - "numberOfBytes": "1" - }, - "t_bytes4": { - "label": "bytes4", - "numberOfBytes": "4" - }, - "t_contract(ICertifier)2226": { - "label": "contract ICertifier", - "numberOfBytes": "20" - }, - "t_contract(IConnectivityTrackerHbbft)2276": { - "label": "contract IConnectivityTrackerHbbft", - "numberOfBytes": "20" - }, - "t_contract(IKeyGenHistory)2317": { - "label": "contract IKeyGenHistory", - "numberOfBytes": "20" - }, - "t_contract(IValidatorSetHbbft)2726": { - "label": "contract IValidatorSetHbbft", - "numberOfBytes": "20" - }, - "t_mapping(t_address,t_bool)": { - "label": "mapping(address => bool)", - "numberOfBytes": "32" - }, - "t_mapping(t_bytes4,t_struct(ParameterRange)1966_storage)": { - "label": "mapping(bytes4 => struct ValueGuards.ParameterRange)", - "numberOfBytes": "32" - }, - "t_struct(ParameterRange)1966_storage": { - "label": "struct ValueGuards.ParameterRange", - "members": [ - { - "label": "getter", - "type": "t_bytes4", - "offset": 0, - "slot": "0" - }, - { - "label": "range", - "type": "t_array(t_uint256)dyn_storage", - "offset": 0, - "slot": "1" - } - ], - "numberOfBytes": "64" - }, - "t_uint256": { - "label": "uint256", - "numberOfBytes": "32" - }, - "t_uint8": { - "label": "uint8", - "numberOfBytes": "1" - } - } - } - }, - "feb759fb1417f3475bcef606ff0300a5ff70fafc3ba0aa93cdf1a68c3800b438": { - "address": "0x68081EAbC44D892eC4177DBB186a9DA0AfaB8dDf", - "txHash": "0xd0b82d72b7efc0d4e296058a3aefec0c525d61bd571b4f5131221fb729f2a4b9", - "layout": { - "solcVersion": "0.8.17", - "storage": [ - { - "label": "_initialized", - "offset": 0, - "slot": "0", - "type": "t_uint8", - "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", - "retypedFrom": "bool" - }, - { - "label": "_initializing", - "offset": 1, - "slot": "0", - "type": "t_bool", - "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" - }, - { - "label": "__gap", - "offset": 0, - "slot": "1", - "type": "t_array(t_uint256)50_storage", - "contract": "ContextUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" - }, - { - "label": "_owner", - "offset": 0, - "slot": "51", - "type": "t_address", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" - }, - { - "label": "__gap", - "offset": 0, - "slot": "52", - "type": "t_array(t_uint256)49_storage", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" - }, - { - "label": "allowedParameterRange", - "offset": 0, - "slot": "101", - "type": "t_mapping(t_bytes4,t_struct(ParameterRange)1988_storage)", - "contract": "ValueGuards", - "src": "contracts/ValueGuards.sol:39" - }, - { - "label": "_allowedSenders", - "offset": 0, - "slot": "102", - "type": "t_array(t_address)dyn_storage", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:24" - }, - { - "label": "certifierContract", - "offset": 0, - "slot": "103", - "type": "t_contract(ICertifier)2248", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:27" - }, - { - "label": "keyGenHistoryContract", - "offset": 0, - "slot": "104", - "type": "t_contract(IKeyGenHistory)2339", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:30" - }, - { - "label": "isSenderAllowed", - "offset": 0, - "slot": "105", - "type": "t_mapping(t_address,t_bool)", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:35" - }, - { - "label": "validatorSetContract", - "offset": 0, - "slot": "106", - "type": "t_contract(IValidatorSetHbbft)2748", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:38" - }, - { - "label": "minimumGasPrice", - "offset": 0, - "slot": "107", - "type": "t_uint256", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:42" - }, - { - "label": "blockGasLimit", - "offset": 0, - "slot": "108", - "type": "t_uint256", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:45" - }, - { - "label": "connectivityTracker", - "offset": 0, - "slot": "109", - "type": "t_contract(IConnectivityTrackerHbbft)2298", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:48" - } - ], - "types": { - "t_address": { - "label": "address", - "numberOfBytes": "20" - }, - "t_array(t_address)dyn_storage": { - "label": "address[]", - "numberOfBytes": "32" - }, - "t_array(t_uint256)49_storage": { - "label": "uint256[49]", - "numberOfBytes": "1568" - }, - "t_array(t_uint256)50_storage": { - "label": "uint256[50]", - "numberOfBytes": "1600" - }, - "t_array(t_uint256)dyn_storage": { - "label": "uint256[]", - "numberOfBytes": "32" - }, - "t_bool": { - "label": "bool", - "numberOfBytes": "1" - }, - "t_bytes4": { - "label": "bytes4", - "numberOfBytes": "4" - }, - "t_contract(ICertifier)2248": { - "label": "contract ICertifier", - "numberOfBytes": "20" - }, - "t_contract(IConnectivityTrackerHbbft)2298": { - "label": "contract IConnectivityTrackerHbbft", - "numberOfBytes": "20" - }, - "t_contract(IKeyGenHistory)2339": { - "label": "contract IKeyGenHistory", - "numberOfBytes": "20" - }, - "t_contract(IValidatorSetHbbft)2748": { - "label": "contract IValidatorSetHbbft", - "numberOfBytes": "20" - }, - "t_mapping(t_address,t_bool)": { - "label": "mapping(address => bool)", - "numberOfBytes": "32" - }, - "t_mapping(t_bytes4,t_struct(ParameterRange)1988_storage)": { - "label": "mapping(bytes4 => struct ValueGuards.ParameterRange)", - "numberOfBytes": "32" - }, - "t_struct(ParameterRange)1988_storage": { - "label": "struct ValueGuards.ParameterRange", - "members": [ - { - "label": "getter", - "type": "t_bytes4", - "offset": 0, - "slot": "0" - }, - { - "label": "range", - "type": "t_array(t_uint256)dyn_storage", - "offset": 0, - "slot": "1" - } - ], - "numberOfBytes": "64" - }, - "t_uint256": { - "label": "uint256", - "numberOfBytes": "32" - }, - "t_uint8": { - "label": "uint8", - "numberOfBytes": "1" - } - } - } - }, - "8f70a3753cde8117160917a184b1ced9b7d93cc01e38b75257a3fc830588df95": { - "address": "0x2b9487e02E0bC62322D71882f70159E83209Ca3a", - "txHash": "0xcb8fd69ce9dbf5d2fc9ce6e62411af858cbca35c53269e825ec914476b2e0c73", - "layout": { - "solcVersion": "0.8.17", - "storage": [ - { - "label": "_initialized", - "offset": 0, - "slot": "0", - "type": "t_uint8", - "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", - "retypedFrom": "bool" - }, - { - "label": "_initializing", - "offset": 1, - "slot": "0", - "type": "t_bool", - "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" - }, - { - "label": "__gap", - "offset": 0, - "slot": "1", - "type": "t_array(t_uint256)50_storage", - "contract": "ContextUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" - }, - { - "label": "_owner", - "offset": 0, - "slot": "51", - "type": "t_address", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" - }, - { - "label": "__gap", - "offset": 0, - "slot": "52", - "type": "t_array(t_uint256)49_storage", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" - }, - { - "label": "allowedParameterRange", - "offset": 0, - "slot": "101", - "type": "t_mapping(t_bytes4,t_struct(ParameterRange)2003_storage)", - "contract": "ValueGuards", - "src": "contracts/ValueGuards.sol:39" - }, - { - "label": "_allowedSenders", - "offset": 0, - "slot": "102", - "type": "t_array(t_address)dyn_storage", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:24" - }, - { - "label": "certifierContract", - "offset": 0, - "slot": "103", - "type": "t_contract(ICertifier)2263", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:27" - }, - { - "label": "keyGenHistoryContract", - "offset": 0, - "slot": "104", - "type": "t_contract(IKeyGenHistory)2354", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:30" - }, - { - "label": "isSenderAllowed", - "offset": 0, - "slot": "105", - "type": "t_mapping(t_address,t_bool)", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:35" - }, - { - "label": "validatorSetContract", - "offset": 0, - "slot": "106", - "type": "t_contract(IValidatorSetHbbft)2763", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:38" - }, - { - "label": "minimumGasPrice", - "offset": 0, - "slot": "107", - "type": "t_uint256", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:42" - }, - { - "label": "blockGasLimit", - "offset": 0, - "slot": "108", - "type": "t_uint256", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:45" - }, - { - "label": "connectivityTracker", - "offset": 0, - "slot": "109", - "type": "t_contract(IConnectivityTrackerHbbft)2313", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:48" - } - ], - "types": { - "t_address": { - "label": "address", - "numberOfBytes": "20" - }, - "t_array(t_address)dyn_storage": { - "label": "address[]", - "numberOfBytes": "32" - }, - "t_array(t_uint256)49_storage": { - "label": "uint256[49]", - "numberOfBytes": "1568" - }, - "t_array(t_uint256)50_storage": { - "label": "uint256[50]", - "numberOfBytes": "1600" - }, - "t_array(t_uint256)dyn_storage": { - "label": "uint256[]", - "numberOfBytes": "32" - }, - "t_bool": { - "label": "bool", - "numberOfBytes": "1" - }, - "t_bytes4": { - "label": "bytes4", - "numberOfBytes": "4" - }, - "t_contract(ICertifier)2263": { - "label": "contract ICertifier", - "numberOfBytes": "20" - }, - "t_contract(IConnectivityTrackerHbbft)2313": { - "label": "contract IConnectivityTrackerHbbft", - "numberOfBytes": "20" - }, - "t_contract(IKeyGenHistory)2354": { - "label": "contract IKeyGenHistory", - "numberOfBytes": "20" - }, - "t_contract(IValidatorSetHbbft)2763": { - "label": "contract IValidatorSetHbbft", - "numberOfBytes": "20" - }, - "t_mapping(t_address,t_bool)": { - "label": "mapping(address => bool)", - "numberOfBytes": "32" - }, - "t_mapping(t_bytes4,t_struct(ParameterRange)2003_storage)": { - "label": "mapping(bytes4 => struct ValueGuards.ParameterRange)", - "numberOfBytes": "32" - }, - "t_struct(ParameterRange)2003_storage": { - "label": "struct ValueGuards.ParameterRange", - "members": [ - { - "label": "getter", - "type": "t_bytes4", - "offset": 0, - "slot": "0" - }, - { - "label": "range", - "type": "t_array(t_uint256)dyn_storage", - "offset": 0, - "slot": "1" - } - ], - "numberOfBytes": "64" - }, - "t_uint256": { - "label": "uint256", - "numberOfBytes": "32" - }, - "t_uint8": { - "label": "uint8", - "numberOfBytes": "1" - } - } - } - }, - "65e96f892c2a0f156339ced52843cd0dbf4181f4c0cd4c0e531f67abb00f29f8": { - "address": "0xBD2dCF988abE01C0B7bFc61D58EFc33fEf08DbfD", - "txHash": "0x4eec9af186719d851313d81715a70c1fd164e9622c752466ebb177615327bb31", - "layout": { - "solcVersion": "0.8.17", - "storage": [ - { - "label": "_initialized", - "offset": 0, - "slot": "0", - "type": "t_uint8", - "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", - "retypedFrom": "bool" - }, - { - "label": "_initializing", - "offset": 1, - "slot": "0", - "type": "t_bool", - "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" - }, - { - "label": "__gap", - "offset": 0, - "slot": "1", - "type": "t_array(t_uint256)50_storage", - "contract": "ContextUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" - }, - { - "label": "_owner", - "offset": 0, - "slot": "51", - "type": "t_address", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" - }, - { - "label": "__gap", - "offset": 0, - "slot": "52", - "type": "t_array(t_uint256)49_storage", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" - }, - { - "label": "_epochsPoolGotRewardFor", - "offset": 0, - "slot": "101", - "type": "t_mapping(t_address,t_array(t_uint256)dyn_storage)", - "contract": "BlockRewardHbbftBase", - "src": "contracts/base/BlockRewardHbbftBase.sol:24" - }, - { - "label": "epochPoolNativeReward", - "offset": 0, - "slot": "102", - "type": "t_mapping(t_uint256,t_mapping(t_address,t_uint256))", - "contract": "BlockRewardHbbftBase", - "src": "contracts/base/BlockRewardHbbftBase.sol:28" - }, - { - "label": "nativeRewardUndistributed", - "offset": 0, - "slot": "103", - "type": "t_uint256", - "contract": "BlockRewardHbbftBase", - "src": "contracts/base/BlockRewardHbbftBase.sol:32" - }, - { - "label": "snapshotPoolTotalStakeAmount", - "offset": 0, - "slot": "104", - "type": "t_mapping(t_uint256,t_mapping(t_address,t_uint256))", - "contract": "BlockRewardHbbftBase", - "src": "contracts/base/BlockRewardHbbftBase.sol:36" - }, - { - "label": "snapshotPoolValidatorStakeAmount", - "offset": 0, - "slot": "105", - "type": "t_mapping(t_uint256,t_mapping(t_address,t_uint256))", - "contract": "BlockRewardHbbftBase", - "src": "contracts/base/BlockRewardHbbftBase.sol:41" - }, - { - "label": "validatorMinRewardPercent", - "offset": 0, - "slot": "106", - "type": "t_mapping(t_uint256,t_uint256)", - "contract": "BlockRewardHbbftBase", - "src": "contracts/base/BlockRewardHbbftBase.sol:49" - }, - { - "label": "deltaPot", - "offset": 0, - "slot": "107", - "type": "t_uint256", - "contract": "BlockRewardHbbftBase", - "src": "contracts/base/BlockRewardHbbftBase.sol:52" - }, - { - "label": "deltaPotPayoutFraction", - "offset": 0, - "slot": "108", - "type": "t_uint256", - "contract": "BlockRewardHbbftBase", - "src": "contracts/base/BlockRewardHbbftBase.sol:56" - }, - { - "label": "reinsertPot", - "offset": 0, - "slot": "109", - "type": "t_uint256", - "contract": "BlockRewardHbbftBase", - "src": "contracts/base/BlockRewardHbbftBase.sol:61" - }, - { - "label": "reinsertPotPayoutFraction", - "offset": 0, - "slot": "110", - "type": "t_uint256", - "contract": "BlockRewardHbbftBase", - "src": "contracts/base/BlockRewardHbbftBase.sol:65" - }, - { - "label": "validatorSetContract", - "offset": 0, - "slot": "111", - "type": "t_contract(IValidatorSetHbbft)8481", - "contract": "BlockRewardHbbftBase", - "src": "contracts/base/BlockRewardHbbftBase.sol:68" - }, - { - "label": "governancePotAddress", - "offset": 0, - "slot": "112", - "type": "t_address_payable", - "contract": "BlockRewardHbbftBase", - "src": "contracts/base/BlockRewardHbbftBase.sol:71" - }, - { - "label": "governancePotShareNominator", - "offset": 0, - "slot": "113", - "type": "t_uint256", - "contract": "BlockRewardHbbftBase", - "src": "contracts/base/BlockRewardHbbftBase.sol:75" - }, - { - "label": "governancePotShareDenominator", - "offset": 0, - "slot": "114", - "type": "t_uint256", - "contract": "BlockRewardHbbftBase", - "src": "contracts/base/BlockRewardHbbftBase.sol:79" - }, - { - "label": "connectivityTracker", - "offset": 0, - "slot": "115", - "type": "t_address", - "contract": "BlockRewardHbbftBase", - "src": "contracts/base/BlockRewardHbbftBase.sol:82" - }, - { - "label": "earlyEpochEnd", - "offset": 20, - "slot": "115", - "type": "t_bool", - "contract": "BlockRewardHbbftBase", - "src": "contracts/base/BlockRewardHbbftBase.sol:85" - }, - { - "label": "__gap", - "offset": 0, - "slot": "116", - "type": "t_array(t_uint256)49_storage", - "contract": "BlockRewardHbbftBase", - "src": "contracts/base/BlockRewardHbbftBase.sol:708" - }, - { - "label": "allowedParameterRange", - "offset": 0, - "slot": "165", - "type": "t_mapping(t_bytes4,t_struct(ParameterRange)2737_storage)", - "contract": "ValueGuards", - "src": "contracts/ValueGuards.sol:39" - }, - { - "label": "_systemAddress", - "offset": 0, - "slot": "166", - "type": "t_address", - "contract": "BlockRewardHbbftMock", - "src": "contracts/mockContracts/BlockRewardHbbftMock.sol:6" - } - ], - "types": { - "t_address": { - "label": "address", - "numberOfBytes": "20" - }, - "t_address_payable": { - "label": "address payable", - "numberOfBytes": "20" - }, - "t_array(t_uint256)49_storage": { - "label": "uint256[49]", - "numberOfBytes": "1568" - }, - "t_array(t_uint256)50_storage": { - "label": "uint256[50]", - "numberOfBytes": "1600" - }, - "t_array(t_uint256)dyn_storage": { - "label": "uint256[]", - "numberOfBytes": "32" - }, - "t_bool": { - "label": "bool", - "numberOfBytes": "1" - }, - "t_bytes4": { - "label": "bytes4", - "numberOfBytes": "4" - }, - "t_contract(IValidatorSetHbbft)8481": { - "label": "contract IValidatorSetHbbft", - "numberOfBytes": "20" - }, - "t_mapping(t_address,t_array(t_uint256)dyn_storage)": { - "label": "mapping(address => uint256[])", - "numberOfBytes": "32" - }, - "t_mapping(t_address,t_uint256)": { - "label": "mapping(address => uint256)", - "numberOfBytes": "32" - }, - "t_mapping(t_bytes4,t_struct(ParameterRange)2737_storage)": { - "label": "mapping(bytes4 => struct ValueGuards.ParameterRange)", - "numberOfBytes": "32" - }, - "t_mapping(t_uint256,t_mapping(t_address,t_uint256))": { - "label": "mapping(uint256 => mapping(address => uint256))", - "numberOfBytes": "32" - }, - "t_mapping(t_uint256,t_uint256)": { - "label": "mapping(uint256 => uint256)", - "numberOfBytes": "32" - }, - "t_struct(ParameterRange)2737_storage": { - "label": "struct ValueGuards.ParameterRange", - "members": [ - { - "label": "getter", - "type": "t_bytes4", - "offset": 0, - "slot": "0" - }, - { - "label": "range", - "type": "t_array(t_uint256)dyn_storage", - "offset": 0, - "slot": "1" - } - ], - "numberOfBytes": "64" - }, - "t_uint256": { - "label": "uint256", - "numberOfBytes": "32" - }, - "t_uint8": { - "label": "uint8", - "numberOfBytes": "1" - } - } - } - }, - "90f01f6a5e36dcd105f3a7eb01d2d882a820ef9c08873c2da50698007e027280": { - "address": "0xA994B9B8c30E56e9fC9Bc17fC20EEe619ae93022", - "txHash": "0xb054b24a1c36bfd7824ee5ad7e25e755b71d65b95499aa54061d8378c815a4f5", - "layout": { - "solcVersion": "0.8.17", - "storage": [ - { - "label": "_initialized", - "offset": 0, - "slot": "0", - "type": "t_uint8", - "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", - "retypedFrom": "bool" - }, - { - "label": "_initializing", - "offset": 1, - "slot": "0", - "type": "t_bool", - "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" - }, - { - "label": "__gap", - "offset": 0, - "slot": "1", - "type": "t_array(t_uint256)50_storage", - "contract": "ContextUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" - }, - { - "label": "_owner", - "offset": 0, - "slot": "51", - "type": "t_address", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" - }, - { - "label": "__gap", - "offset": 0, - "slot": "52", - "type": "t_array(t_uint256)49_storage", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" - }, - { - "label": "_pools", - "offset": 0, - "slot": "101", - "type": "t_array(t_address)dyn_storage", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:17" - }, - { - "label": "_poolsInactive", - "offset": 0, - "slot": "102", - "type": "t_array(t_address)dyn_storage", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:18" - }, - { - "label": "_poolsToBeElected", - "offset": 0, - "slot": "103", - "type": "t_array(t_address)dyn_storage", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:19" - }, - { - "label": "_poolsToBeRemoved", - "offset": 0, - "slot": "104", - "type": "t_array(t_address)dyn_storage", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:20" - }, - { - "label": "_poolsLikelihood", - "offset": 0, - "slot": "105", - "type": "t_array(t_uint256)dyn_storage", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:21" - }, - { - "label": "_poolsLikelihoodSum", - "offset": 0, - "slot": "106", - "type": "t_uint256", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:22" - }, - { - "label": "_poolDelegators", - "offset": 0, - "slot": "107", - "type": "t_mapping(t_address,t_array(t_address)dyn_storage)", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:23" - }, - { - "label": "_poolDelegatorsInactive", - "offset": 0, - "slot": "108", - "type": "t_mapping(t_address,t_array(t_address)dyn_storage)", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:24" - }, - { - "label": "_stakeAmountByEpoch", - "offset": 0, - "slot": "109", - "type": "t_mapping(t_address,t_mapping(t_address,t_mapping(t_uint256,t_uint256)))", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:25" - }, - { - "label": "candidateMinStake", - "offset": 0, - "slot": "110", - "type": "t_uint256", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:29" - }, - { - "label": "delegatorMinStake", - "offset": 0, - "slot": "111", - "type": "t_uint256", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:32" - }, - { - "label": "delegatorStakeSnapshot", - "offset": 0, - "slot": "112", - "type": "t_mapping(t_address,t_mapping(t_address,t_mapping(t_uint256,t_uint256)))", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:38" - }, - { - "label": "orderedWithdrawAmount", - "offset": 0, - "slot": "113", - "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:44" - }, - { - "label": "orderedWithdrawAmountTotal", - "offset": 0, - "slot": "114", - "type": "t_mapping(t_address,t_uint256)", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:49" - }, - { - "label": "orderWithdrawEpoch", - "offset": 0, - "slot": "115", - "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:55" - }, - { - "label": "poolDelegatorIndex", - "offset": 0, - "slot": "116", - "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:62" - }, - { - "label": "poolDelegatorInactiveIndex", - "offset": 0, - "slot": "117", - "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:69" - }, - { - "label": "poolInactiveIndex", - "offset": 0, - "slot": "118", - "type": "t_mapping(t_address,t_uint256)", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:74" - }, - { - "label": "poolIndex", - "offset": 0, - "slot": "119", - "type": "t_mapping(t_address,t_uint256)", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:80" - }, - { - "label": "poolToBeElectedIndex", - "offset": 0, - "slot": "120", - "type": "t_mapping(t_address,t_uint256)", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:87" - }, - { - "label": "poolToBeRemovedIndex", - "offset": 0, - "slot": "121", - "type": "t_mapping(t_address,t_uint256)", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:94" - }, - { - "label": "rewardWasTaken", - "offset": 0, - "slot": "122", - "type": "t_mapping(t_address,t_mapping(t_address,t_mapping(t_uint256,t_bool)))", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:100" - }, - { - "label": "stakeAmount", - "offset": 0, - "slot": "123", - "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:106" - }, - { - "label": "stakeFirstEpoch", - "offset": 0, - "slot": "124", - "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:112" - }, - { - "label": "stakeLastEpoch", - "offset": 0, - "slot": "125", - "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:118" - }, - { - "label": "stakingWithdrawDisallowPeriod", - "offset": 0, - "slot": "126", - "type": "t_uint256", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:122" - }, - { - "label": "stakingEpoch", - "offset": 0, - "slot": "127", - "type": "t_uint256", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:125" - }, - { - "label": "stakingFixedEpochDuration", - "offset": 0, - "slot": "128", - "type": "t_uint256", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:129" - }, - { - "label": "stakingTransitionTimeframeLength", - "offset": 0, - "slot": "129", - "type": "t_uint256", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:132" - }, - { - "label": "stakingEpochStartTime", - "offset": 0, - "slot": "130", - "type": "t_uint256", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:136" - }, - { - "label": "stakingEpochStartBlock", - "offset": 0, - "slot": "131", - "type": "t_uint256", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:143" - }, - { - "label": "currentKeyGenExtraTimeWindow", - "offset": 0, - "slot": "132", - "type": "t_uint256", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:149" - }, - { - "label": "stakeAmountTotal", - "offset": 0, - "slot": "133", - "type": "t_mapping(t_address,t_uint256)", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:154" - }, - { - "label": "validatorSetContract", - "offset": 0, - "slot": "134", - "type": "t_contract(IValidatorSetHbbft)8481", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:157" - }, - { - "label": "poolInfo", - "offset": 0, - "slot": "135", - "type": "t_mapping(t_address,t_struct(PoolInfo)4627_storage)", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:165" - }, - { - "label": "maxStakeAmount", - "offset": 0, - "slot": "136", - "type": "t_uint256", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:169" - }, - { - "label": "abandonedAndRemoved", - "offset": 0, - "slot": "137", - "type": "t_mapping(t_address,t_bool)", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:171" - }, - { - "label": "__gap", - "offset": 0, - "slot": "138", - "type": "t_array(t_uint256)50_storage", - "contract": "StakingHbbftBase", - "src": "contracts/base/StakingHbbftBase.sol:1692" - }, - { - "label": "allowedParameterRange", - "offset": 0, - "slot": "188", - "type": "t_mapping(t_bytes4,t_struct(ParameterRange)2737_storage)", - "contract": "ValueGuards", - "src": "contracts/ValueGuards.sol:39" - }, - { - "label": "validatorSetContractMock", - "offset": 0, - "slot": "189", - "type": "t_contract(IValidatorSetHbbft)8481", - "contract": "StakingHbbftMock", - "src": "contracts/mockContracts/StakingHbbftMock.sol:6" - } - ], - "types": { - "t_address": { - "label": "address", - "numberOfBytes": "20" - }, - "t_array(t_address)dyn_storage": { - "label": "address[]", - "numberOfBytes": "32" - }, - "t_array(t_uint256)49_storage": { - "label": "uint256[49]", - "numberOfBytes": "1568" - }, - "t_array(t_uint256)50_storage": { - "label": "uint256[50]", - "numberOfBytes": "1600" - }, - "t_array(t_uint256)dyn_storage": { - "label": "uint256[]", - "numberOfBytes": "32" - }, - "t_bool": { - "label": "bool", - "numberOfBytes": "1" - }, - "t_bytes16": { - "label": "bytes16", - "numberOfBytes": "16" - }, - "t_bytes2": { - "label": "bytes2", - "numberOfBytes": "2" - }, - "t_bytes4": { - "label": "bytes4", - "numberOfBytes": "4" - }, - "t_bytes_storage": { - "label": "bytes", - "numberOfBytes": "32" - }, - "t_contract(IValidatorSetHbbft)8481": { - "label": "contract IValidatorSetHbbft", - "numberOfBytes": "20" - }, - "t_mapping(t_address,t_array(t_address)dyn_storage)": { - "label": "mapping(address => address[])", - "numberOfBytes": "32" - }, - "t_mapping(t_address,t_bool)": { - "label": "mapping(address => bool)", - "numberOfBytes": "32" - }, - "t_mapping(t_address,t_mapping(t_address,t_mapping(t_uint256,t_bool)))": { - "label": "mapping(address => mapping(address => mapping(uint256 => bool)))", - "numberOfBytes": "32" - }, - "t_mapping(t_address,t_mapping(t_address,t_mapping(t_uint256,t_uint256)))": { - "label": "mapping(address => mapping(address => mapping(uint256 => uint256)))", - "numberOfBytes": "32" - }, - "t_mapping(t_address,t_mapping(t_address,t_uint256))": { - "label": "mapping(address => mapping(address => uint256))", - "numberOfBytes": "32" - }, - "t_mapping(t_address,t_mapping(t_uint256,t_bool))": { - "label": "mapping(address => mapping(uint256 => bool))", - "numberOfBytes": "32" - }, - "t_mapping(t_address,t_mapping(t_uint256,t_uint256))": { - "label": "mapping(address => mapping(uint256 => uint256))", - "numberOfBytes": "32" - }, - "t_mapping(t_address,t_struct(PoolInfo)4627_storage)": { - "label": "mapping(address => struct StakingHbbftBase.PoolInfo)", - "numberOfBytes": "32" - }, - "t_mapping(t_address,t_uint256)": { - "label": "mapping(address => uint256)", - "numberOfBytes": "32" - }, - "t_mapping(t_bytes4,t_struct(ParameterRange)2737_storage)": { - "label": "mapping(bytes4 => struct ValueGuards.ParameterRange)", - "numberOfBytes": "32" - }, - "t_mapping(t_uint256,t_bool)": { - "label": "mapping(uint256 => bool)", - "numberOfBytes": "32" - }, - "t_mapping(t_uint256,t_uint256)": { - "label": "mapping(uint256 => uint256)", - "numberOfBytes": "32" - }, - "t_struct(ParameterRange)2737_storage": { - "label": "struct ValueGuards.ParameterRange", - "members": [ - { - "label": "getter", - "type": "t_bytes4", - "offset": 0, - "slot": "0" - }, - { - "label": "range", - "type": "t_array(t_uint256)dyn_storage", - "offset": 0, - "slot": "1" - } - ], - "numberOfBytes": "64" - }, - "t_struct(PoolInfo)4627_storage": { - "label": "struct StakingHbbftBase.PoolInfo", - "members": [ - { - "label": "publicKey", - "type": "t_bytes_storage", - "offset": 0, - "slot": "0" - }, - { - "label": "internetAddress", - "type": "t_bytes16", - "offset": 0, - "slot": "1" - }, - { - "label": "port", - "type": "t_bytes2", - "offset": 16, - "slot": "1" - } - ], - "numberOfBytes": "64" - }, - "t_uint256": { - "label": "uint256", - "numberOfBytes": "32" - }, - "t_uint8": { - "label": "uint8", - "numberOfBytes": "1" - } - } - } - }, - "fb53fab9e4a2ec0af56d84574da31bedcc8e1539a2c155f573d24ad2f01d47bc": { - "address": "0x88B015f06d1314f00248Ca29BC9e12982CEF26ef", - "txHash": "0x08fdb52d2d6d1113042fd4f87af302c08efae333229e17863e7fd99579423a91", - "layout": { - "solcVersion": "0.8.17", - "storage": [ - { - "label": "_initialized", - "offset": 0, - "slot": "0", - "type": "t_uint8", - "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", - "retypedFrom": "bool" - }, - { - "label": "_initializing", - "offset": 1, - "slot": "0", - "type": "t_bool", - "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" - }, - { - "label": "__gap", - "offset": 0, - "slot": "1", - "type": "t_array(t_uint256)50_storage", - "contract": "ContextUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" - }, - { - "label": "_owner", - "offset": 0, - "slot": "51", - "type": "t_address", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" - }, - { - "label": "__gap", - "offset": 0, - "slot": "52", - "type": "t_array(t_uint256)49_storage", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" - }, - { - "label": "allowedParameterRange", - "offset": 0, - "slot": "101", - "type": "t_mapping(t_bytes4,t_struct(ParameterRange)2737_storage)", - "contract": "ValueGuards", - "src": "contracts/ValueGuards.sol:39" - }, - { - "label": "_allowedSenders", - "offset": 0, - "slot": "102", - "type": "t_array(t_address)dyn_storage", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:24" - }, - { - "label": "certifierContract", - "offset": 0, - "slot": "103", - "type": "t_contract(ICertifier)7936", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:27" - }, - { - "label": "keyGenHistoryContract", - "offset": 0, - "slot": "104", - "type": "t_contract(IKeyGenHistory)8027", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:30" - }, - { - "label": "isSenderAllowed", - "offset": 0, - "slot": "105", - "type": "t_mapping(t_address,t_bool)", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:35" - }, - { - "label": "validatorSetContract", - "offset": 0, - "slot": "106", - "type": "t_contract(IValidatorSetHbbft)8481", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:38" - }, - { - "label": "minimumGasPrice", - "offset": 0, - "slot": "107", - "type": "t_uint256", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:42" - }, - { - "label": "blockGasLimit", - "offset": 0, - "slot": "108", - "type": "t_uint256", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:45" - }, - { - "label": "connectivityTracker", - "offset": 0, - "slot": "109", - "type": "t_contract(IConnectivityTrackerHbbft)7986", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:48" - } - ], - "types": { - "t_address": { - "label": "address", - "numberOfBytes": "20" - }, - "t_array(t_address)dyn_storage": { - "label": "address[]", - "numberOfBytes": "32" - }, - "t_array(t_uint256)49_storage": { - "label": "uint256[49]", - "numberOfBytes": "1568" - }, - "t_array(t_uint256)50_storage": { - "label": "uint256[50]", - "numberOfBytes": "1600" - }, - "t_array(t_uint256)dyn_storage": { - "label": "uint256[]", - "numberOfBytes": "32" - }, - "t_bool": { - "label": "bool", - "numberOfBytes": "1" - }, - "t_bytes4": { - "label": "bytes4", - "numberOfBytes": "4" - }, - "t_contract(ICertifier)7936": { - "label": "contract ICertifier", - "numberOfBytes": "20" - }, - "t_contract(IConnectivityTrackerHbbft)7986": { - "label": "contract IConnectivityTrackerHbbft", - "numberOfBytes": "20" - }, - "t_contract(IKeyGenHistory)8027": { - "label": "contract IKeyGenHistory", - "numberOfBytes": "20" - }, - "t_contract(IValidatorSetHbbft)8481": { - "label": "contract IValidatorSetHbbft", - "numberOfBytes": "20" - }, - "t_mapping(t_address,t_bool)": { - "label": "mapping(address => bool)", - "numberOfBytes": "32" - }, - "t_mapping(t_bytes4,t_struct(ParameterRange)2737_storage)": { - "label": "mapping(bytes4 => struct ValueGuards.ParameterRange)", - "numberOfBytes": "32" - }, - "t_struct(ParameterRange)2737_storage": { - "label": "struct ValueGuards.ParameterRange", - "members": [ - { - "label": "getter", - "type": "t_bytes4", - "offset": 0, - "slot": "0" - }, - { - "label": "range", - "type": "t_array(t_uint256)dyn_storage", - "offset": 0, - "slot": "1" - } - ], - "numberOfBytes": "64" - }, - "t_uint256": { - "label": "uint256", - "numberOfBytes": "32" - }, - "t_uint8": { - "label": "uint8", - "numberOfBytes": "1" - } - } - } - }, - "8960dc0a864834a45c5dc31aedcbf832ff6245e18f3b21b496de4cf9af4d85a0": { - "address": "0x7b0b96C1b27e774E7EE7DAC9F3489EAfFa3bE93b", - "txHash": "0x02185ac321ed259b4e3a1a789b73a67a5fcddb33938d65360e6dee26f72cdf51", - "layout": { - "solcVersion": "0.8.17", - "storage": [ - { - "label": "_initialized", - "offset": 0, - "slot": "0", - "type": "t_uint8", - "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:63", - "retypedFrom": "bool" - }, - { - "label": "_initializing", - "offset": 1, - "slot": "0", - "type": "t_bool", - "contract": "Initializable", - "src": "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol:68" - }, - { - "label": "__gap", - "offset": 0, - "slot": "1", - "type": "t_array(t_uint256)50_storage", - "contract": "ContextUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol:36" - }, - { - "label": "_owner", - "offset": 0, - "slot": "51", - "type": "t_address", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:22" - }, - { - "label": "__gap", - "offset": 0, - "slot": "52", - "type": "t_array(t_uint256)49_storage", - "contract": "OwnableUpgradeable", - "src": "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol:94" - }, - { - "label": "allowedParameterRange", - "offset": 0, - "slot": "101", - "type": "t_mapping(t_bytes4,t_struct(ParameterRange)2737_storage)", - "contract": "ValueGuards", - "src": "contracts/ValueGuards.sol:39" - }, - { - "label": "_allowedSenders", - "offset": 0, - "slot": "102", - "type": "t_array(t_address)dyn_storage", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:24" - }, - { - "label": "certifierContract", - "offset": 0, - "slot": "103", - "type": "t_contract(ICertifier)7936", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:27" - }, - { - "label": "keyGenHistoryContract", - "offset": 0, - "slot": "104", - "type": "t_contract(IKeyGenHistory)8027", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:30" - }, - { - "label": "isSenderAllowed", - "offset": 0, - "slot": "105", - "type": "t_mapping(t_address,t_bool)", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:35" - }, - { - "label": "validatorSetContract", - "offset": 0, - "slot": "106", - "type": "t_contract(IValidatorSetHbbft)8481", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:38" - }, - { - "label": "minimumGasPrice", - "offset": 0, - "slot": "107", - "type": "t_uint256", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:42" - }, - { - "label": "blockGasLimit", - "offset": 0, - "slot": "108", - "type": "t_uint256", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:45" - }, - { - "label": "connectivityTracker", - "offset": 0, - "slot": "109", - "type": "t_contract(IConnectivityTrackerHbbft)7986", - "contract": "TxPermissionHbbft", - "src": "contracts/TxPermissionHbbft.sol:48" - } - ], - "types": { - "t_address": { - "label": "address", - "numberOfBytes": "20" - }, - "t_array(t_address)dyn_storage": { - "label": "address[]", - "numberOfBytes": "32" - }, - "t_array(t_uint256)49_storage": { - "label": "uint256[49]", - "numberOfBytes": "1568" - }, - "t_array(t_uint256)50_storage": { - "label": "uint256[50]", - "numberOfBytes": "1600" - }, - "t_array(t_uint256)dyn_storage": { - "label": "uint256[]", - "numberOfBytes": "32" - }, - "t_bool": { - "label": "bool", - "numberOfBytes": "1" - }, - "t_bytes4": { - "label": "bytes4", - "numberOfBytes": "4" - }, - "t_contract(ICertifier)7936": { - "label": "contract ICertifier", - "numberOfBytes": "20" - }, - "t_contract(IConnectivityTrackerHbbft)7986": { - "label": "contract IConnectivityTrackerHbbft", - "numberOfBytes": "20" - }, - "t_contract(IKeyGenHistory)8027": { - "label": "contract IKeyGenHistory", - "numberOfBytes": "20" - }, - "t_contract(IValidatorSetHbbft)8481": { - "label": "contract IValidatorSetHbbft", - "numberOfBytes": "20" - }, - "t_mapping(t_address,t_bool)": { - "label": "mapping(address => bool)", - "numberOfBytes": "32" - }, - "t_mapping(t_bytes4,t_struct(ParameterRange)2737_storage)": { - "label": "mapping(bytes4 => struct ValueGuards.ParameterRange)", - "numberOfBytes": "32" - }, - "t_struct(ParameterRange)2737_storage": { - "label": "struct ValueGuards.ParameterRange", - "members": [ - { - "label": "getter", - "type": "t_bytes4", - "offset": 0, - "slot": "0" - }, - { - "label": "range", - "type": "t_array(t_uint256)dyn_storage", - "offset": 0, - "slot": "1" - } - ], - "numberOfBytes": "64" - }, - "t_uint256": { - "label": "uint256", - "numberOfBytes": "32" - }, - "t_uint8": { - "label": "uint8", - "numberOfBytes": "1" - } - } - } - } - } -} diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 00000000..a6901749 --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,26 @@ +{ + "overrides": [ + { + "files": "*.sol", + "options": { + "tabWidth": 4, + "printWidth": 120, + "bracketSpacing": true + } + }, + { + "files": "*.js", + "options": { + "tabWidth": 2, + "printWidth": 100 + } + }, + { + "files": "*.ts", + "options": { + "tabWidth": 2, + "printWidth": 120 + } + } + ] +} diff --git a/contracts/BlockRewardHbbft.sol b/contracts/BlockRewardHbbft.sol index af1529cb..4824ac2c 100644 --- a/contracts/BlockRewardHbbft.sol +++ b/contracts/BlockRewardHbbft.sol @@ -1,21 +1,239 @@ pragma solidity =0.8.17; +<<<<<<< HEAD import "./base/BlockRewardHbbftBase.sol"; import { ValueGuards } from "./ValueGuards.sol"; import "./interfaces/IBlockRewardHbbftCoins.sol"; contract BlockRewardHbbft is BlockRewardHbbftBase, IBlockRewardHbbftCoins, ValueGuards { +======= +import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; +import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; +import { ReentrancyGuardUpgradeable } from "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol"; + +import { IBlockRewardHbbft } from "./interfaces/IBlockRewardHbbft.sol"; +import { IStakingHbbft } from "./interfaces/IStakingHbbft.sol"; +import { IValidatorSetHbbft } from "./interfaces/IValidatorSetHbbft.sol"; +import { TransferUtils } from "./utils/TransferUtils.sol"; + +/// @dev Generates and distributes rewards according to the logic and formulas described in the POSDAO white paper. +contract BlockRewardHbbft is Initializable, OwnableUpgradeable, ReentrancyGuardUpgradeable, IBlockRewardHbbft { + struct PotsShares { + uint256 deltaPotAmount; + uint256 reinsertPotAmount; + uint256 governancePotAmount; + uint256 totalRewards; + } + + // =============================================== Storage ======================================================== + mapping(address => uint256[]) internal _epochsPoolGotRewardFor; + + /// @dev The reward amount to be distributed in native coins among participants (the validator and their + /// delegators) of the specified pool (mining address) for the specified staking epoch. + mapping(uint256 => mapping(address => uint256)) public epochPoolNativeReward; + + /// @dev The total reward amount in native coins which is not yet distributed among pools. + uint256 public nativeRewardUndistributed; + + /// @dev The validator's min reward percent which was actual at the specified staking epoch. + /// This percent is taken from the VALIDATOR_MIN_REWARD_PERCENT constant and saved for every staking epoch + /// by the `reward` function. + /// This is needed to have an ability to change validator's min reward percent in the VALIDATOR_MIN_REWARD_PERCENT + /// constant by upgrading the contract. + mapping(uint256 => uint256) public validatorMinRewardPercent; + + /// @dev the Delta Pool holds all coins that never got emitted, since the maximum supply is 4,380,000 + uint256 public deltaPot; + + /// @dev each epoch reward, one Fraction of the delta pool gets payed out. + /// the number is the divisor of the fraction. 60 means 1/60 of the delta pool gets payed out. + uint256 public deltaPotPayoutFraction; + + /// @dev the reinsertPot holds all coins that are designed for getting reinserted into the coin circulation. + uint256 public reinsertPot; + + /// @dev each epoch reward, one Fraction of the reinsert pool gets payed out. + /// the number is the divisor of the fraction. 60 means 1/60 of the reinsert pool gets payed out. + uint256 public reinsertPotPayoutFraction; + + /// @dev The address of the `ValidatorSet` contract. + IValidatorSetHbbft public validatorSetContract; + + /// @dev parts of the epoch reward get forwarded to a governance fund. + address payable public governancePotAddress; + + /// @dev nominator of the epoch reward that get's forwarded to the + /// `governancePotAddress`. See also `governancePotShareDenominator` + uint256 public governancePotShareNominator; + + /// @dev denominator of the epoch reward that get's forwarded to the + /// `governancePotAddress`. See also `governancePotShareNominator` + uint256 public governancePotShareDenominator; + + /// @dev the address of the `ConnectivityTrackerHbbft` contract. + address public connectivityTracker; + + /// @dev flag indicating whether it is needed to end current epoch earlier. + bool public earlyEpochEnd; + + uint256 public constant VALIDATOR_MIN_REWARD_PERCENT = 30; // 30% + uint256 public constant REWARD_PERCENT_MULTIPLIER = 1000000; + + // ================================================ Events ======================================================== + + /// @dev Emitted by the `reward` function. + /// @param rewards The amount minted and distributed among the validators. + event CoinsRewarded(uint256 rewards); + + /// @dev Emitted by the `setConnectivityTracker` function. + /// @param _connectivityTracker New ConnectivityTracker contract address. + event SetConnectivityTracker(address _connectivityTracker); + + /// @dev Emitted by the `setdeltaPotPayoutFraction` function. + /// @param _fraction New delta pot payout fraction value. + event SetDeltaPotPayoutFraction(uint256 _fraction); + + /// @dev Emitted by the `setReinsertPotPayoutFraction` function. + /// @param _fraction New reinsert pot payout fraction value. + event SetReinsertPotPayoutFraction(uint256 _fraction); + + // ============================================== Modifiers ======================================================= + + /// @dev Ensures the caller is the SYSTEM_ADDRESS. See https://wiki.parity.io/Block-Reward-Contract.html + modifier onlySystem() virtual { + require(msg.sender == 0xffffFFFfFFffffffffffffffFfFFFfffFFFfFFfE); + _; + } + + /// @dev Ensures the caller is the ConnectivityTracker contract address. + modifier onlyConnectivityTracker() { + require(msg.sender == connectivityTracker); + _; + } + + /// @custom:oz-upgrades-unsafe-allow constructor + constructor() { + // Prevents initialization of implementation contract + _disableInitializers(); + } + +>>>>>>> dmd/dev // =============================================== Setters ======================================================== - /// @dev Called by the `StakingHbbft.claimReward` function to transfer native coins - /// from the balance of the `BlockRewardHbbft` contract to the specified address as a reward. - /// @param _nativeCoins The amount of native coins to transfer as a reward. - /// @param _to The target address to transfer the amounts to. - function transferReward(uint256 _nativeCoins, address payable _to) - external - onlyStakingContract - { - _transferNativeReward(_nativeCoins, _to); + /// @dev Receive function. Prevents direct sending native coins to this contract. + receive() external payable { + reinsertPot += msg.value; + } + + /// @dev Initializes the contract at network startup. + /// Can only be called by the constructor of the `InitializerHbbft` contract or owner. + /// @param _contractOwner The address of the contract owner + /// @param _validatorSet The address of the `ValidatorSetHbbft` contract. + function initialize( + address _contractOwner, + address _validatorSet, + address _connectivityTracker + ) external initializer { + require(_contractOwner != address(0), "Owner address must not be 0"); + require(_validatorSet != address(0), "ValidatorSet must not be 0"); + require(_connectivityTracker != address(0), "ConnectivityTracker must not be 0"); + + __Ownable_init(); + __ReentrancyGuard_init(); + _transferOwnership(_contractOwner); + + validatorSetContract = IValidatorSetHbbft(_validatorSet); + connectivityTracker = _connectivityTracker; + + validatorMinRewardPercent[0] = VALIDATOR_MIN_REWARD_PERCENT; + + deltaPotPayoutFraction = 6000; + reinsertPotPayoutFraction = 6000; + governancePotAddress = payable(0xDA0da0da0Da0Da0Da0DA00DA0da0da0DA0DA0dA0); + governancePotShareNominator = 1; + governancePotShareDenominator = 10; + } + + /// @dev adds the transfered value to the delta pot. + /// everyone is allowed to pile up the delta pot. + /// however, circulating coins should be added to the reinsert pot, + /// since the reinsert pot is designed for circulating coins. + function addToDeltaPot() external payable { + deltaPot += msg.value; + } + + /// @dev adds the transfered value to the reinsert pot. + /// everyone is allowed to pile up the resinsert pot, + /// the reinsert pot reinserts coins back into the payout cycle. + /// this is used by smart contracts of the ecosystem, + /// DAO decisions to fund the reinsert pot from the DAO Pool + /// and manual by hand. + /// There is no permission check, + /// everyone is welcomed to pile up the reinsert pot. + function addToReinsertPot() external payable { + reinsertPot += msg.value; + } + + /// @dev set the delta pot payout fraction. + /// every epoch, + /// a fraction of the delta pot is payed out. + /// Only theOwner, the DAO is allowed to set the delta pot payout fraction. + function setdeltaPotPayoutFraction(uint256 _value) external onlyOwner { + require(_value != 0, "Payout fraction must not be 0"); + deltaPotPayoutFraction = _value; + + emit SetDeltaPotPayoutFraction(_value); + } + + /// @dev set the reinsert pot payout fraction. + /// every epoch, + /// a fraction of the reinsert pot is payed out. + /// (same logic than in the reinsert pot.) + /// Only theOwner, the DAO is allowed to set the reinsert pot payout fraction. + function setReinsertPotPayoutFraction(uint256 _value) external onlyOwner { + require(_value != 0, "Payout fraction must not be 0"); + reinsertPotPayoutFraction = _value; + + emit SetReinsertPotPayoutFraction(_value); + } + + function setConnectivityTracker(address _connectivityTracker) external onlyOwner { + require(_connectivityTracker != address(0), "ConnectivityTracker must not be 0"); + connectivityTracker = _connectivityTracker; + + emit SetConnectivityTracker(_connectivityTracker); + } + + /// @dev Notify block reward contract, that current epoch must be closed earlier. + /// + /// https://github.com/DMDcoin/diamond-contracts-core/issues/92 + function notifyEarlyEpochEnd() external onlyConnectivityTracker { + earlyEpochEnd = true; + } + + /// @dev Called by the engine when producing and closing a block, + /// see https://wiki.parity.io/Block-Reward-Contract.html. + /// This function performs all of the automatic operations needed for accumulating block producing statistics, + /// starting a new staking epoch, snapshotting staking amounts for the upcoming staking epoch, + /// and rewards distributing at the end of a staking epoch. + /// @param _isEpochEndBlock Indicates if this is the last block of the current epoch i.e. + /// just before the pending validators are finalized. + function reward(bool _isEpochEndBlock) external onlySystem nonReentrant returns (uint256 rewardsNative) { + // slither-disable-start reentrancy-eth + IStakingHbbft stakingContract = IStakingHbbft(validatorSetContract.getStakingContract()); + + // If this is the last block of the epoch i.e. master key has been generated. + if (_isEpochEndBlock || earlyEpochEnd) { + rewardsNative = _closeEpoch(stakingContract); + + earlyEpochEnd = false; + + emit CoinsRewarded(rewardsNative); + } else { + _closeBlock(stakingContract); + } + + // slither-disable-end reentrancy-eth } /** @@ -58,57 +276,238 @@ contract BlockRewardHbbft is BlockRewardHbbftBase, IBlockRewardHbbftCoins, Value } // =============================================== Getters ======================================================== + function getGovernanceAddress() external view returns (address) { + return governancePotAddress; + } - /// @dev Returns the reward amount in native coins for - /// some delegator with the specified stake amount placed into the specified - /// pool before the specified staking epoch. Used by the `StakingHbbft.claimReward` function. - /// @param _delegatorStake The stake amount placed by some delegator into the `_poolMiningAddress` pool. - /// @param _stakingEpoch The serial number of staking epoch. - /// @param _poolMiningAddress The pool mining address. - /// @return nativeReward `uint256 nativeReward` - the reward amount in native coins. - function getDelegatorReward( - uint256 _delegatorStake, - uint256 _stakingEpoch, - address _poolMiningAddress - ) external view returns (uint256 nativeReward) { - uint256 validatorStake = snapshotPoolValidatorStakeAmount[ - _stakingEpoch - ][_poolMiningAddress]; - uint256 totalStake = snapshotPoolTotalStakeAmount[_stakingEpoch][ - _poolMiningAddress - ]; - - nativeReward = delegatorShare( - _stakingEpoch, - _delegatorStake, - validatorStake, - totalStake, - epochPoolNativeReward[_stakingEpoch][_poolMiningAddress] - ); + /// @dev Returns an array of epoch numbers for which the specified pool (mining address) + /// got a non-zero reward. + function epochsPoolGotRewardFor(address _miningAddress) external view returns (uint256[] memory) { + return _epochsPoolGotRewardFor[_miningAddress]; + } + + ///@dev Calculates and returns the percentage of the current epoch. + /// 100% MAX + function epochPercentage() public view returns (uint256) { + IStakingHbbft stakingContract = IStakingHbbft(validatorSetContract.getStakingContract()); + uint256 expectedEpochDuration = stakingContract.stakingFixedEpochEndTime() - + stakingContract.stakingEpochStartTime(); + return + block.timestamp > stakingContract.stakingFixedEpochEndTime() + ? 100 + : ((block.timestamp - stakingContract.stakingEpochStartTime()) * 100) / expectedEpochDuration; } - /// @dev Returns the reward amount in native coins for - /// the specified validator and for the specified staking epoch. - /// Used by the `StakingHbbft.claimReward` function. - /// @param _stakingEpoch The serial number of staking epoch. - /// @param _poolMiningAddress The pool mining address. - /// @return nativeReward `uint256 nativeReward` - the reward amount in native coins. - function getValidatorReward( - uint256 _stakingEpoch, - address _poolMiningAddress - ) external view returns (uint256 nativeReward) { - uint256 validatorStake = snapshotPoolValidatorStakeAmount[ - _stakingEpoch - ][_poolMiningAddress]; - uint256 totalStake = snapshotPoolTotalStakeAmount[_stakingEpoch][ - _poolMiningAddress - ]; - - nativeReward = validatorShare( + // ============================================== Private ======================================================== + + /// @dev Distributes rewards among pools at the latest block of a staking epoch. + /// This function is called by the `reward` function. + /// @param _stakingEpoch The number of the current staking epoch. + /// @return Returns the reward amount in native coins needed to be minted + /// and accrued to the balance of this contract. + function _distributeRewards(uint256 _stakingEpoch, IStakingHbbft stakingContract) private returns (uint256) { + // slither-disable-start reentrancy-eth + address[] memory validators = validatorSetContract.getValidators(); + + uint256 numValidators = validators.length; + require(numValidators != 0, "Empty Validator list"); + + PotsShares memory shares = _getPotsShares(numValidators); + + deltaPot -= shares.deltaPotAmount; + reinsertPot -= shares.reinsertPotAmount; + + if (shares.totalRewards == 0) { + return 0; + } + + TransferUtils.transferNative(governancePotAddress, shares.governancePotAmount); + + uint256 distributedAmount = shares.governancePotAmount; + uint256 rewardToDistribute = shares.totalRewards - distributedAmount; + + (uint256 numRewardedValidators, bool[] memory isRewardedValidator) = _markRewardedValidators( + stakingContract, _stakingEpoch, - validatorStake, - totalStake, - epochPoolNativeReward[_stakingEpoch][_poolMiningAddress] + validators ); + + // No rewards distributed in this epoch + if (numRewardedValidators == 0) { + return 0; + } + + // Share the reward equally among the validators. + uint256 poolReward = rewardToDistribute / numRewardedValidators; + uint256 minValidatorRewardPercent = validatorMinRewardPercent[_stakingEpoch]; + + if (poolReward != 0) { + for (uint256 i = 0; i < numValidators; ++i) { + if (!isRewardedValidator[i]) { + continue; + } + + address miningAddress = validators[i]; + address poolStakingAddress = validatorSetContract.stakingByMiningAddress(miningAddress); + + _savePoolRewardStats(_stakingEpoch, miningAddress, poolReward); + + stakingContract.restake{ value: poolReward }(poolStakingAddress, minValidatorRewardPercent); + + distributedAmount += poolReward; + } + } + + nativeRewardUndistributed = shares.totalRewards - distributedAmount; + + // slither-disable-end reentrancy-eth + + return distributedAmount; + } + + /// @dev Makes snapshots of total amount staked into the specified pool + /// before the specified staking epoch. Used by the `reward` function. + /// @param stakingContract The address of the `StakingHbbft` contract. + /// @param stakingEpoch The number of upcoming staking epoch. + /// @param miningAddresses The mining address of the pool. + function _snapshotPoolStakeAmounts( + IStakingHbbft stakingContract, + uint256 stakingEpoch, + address[] memory miningAddresses + ) private { + for (uint256 i = 0; i < miningAddresses.length; ++i) { + address stakingAddress = validatorSetContract.stakingByMiningAddress(miningAddresses[i]); + + stakingContract.snapshotPoolStakeAmounts(stakingEpoch, stakingAddress); + } + } + + function _savePoolRewardStats(uint256 stakingEpoch, address miningAddress, uint256 poolReward) private { + _epochsPoolGotRewardFor[miningAddress].push(stakingEpoch); + epochPoolNativeReward[stakingEpoch][miningAddress] = poolReward; + } + + function _closeEpoch(IStakingHbbft stakingContract) private returns (uint256) { + uint256 stakingEpoch = stakingContract.stakingEpoch(); + + uint256 nativeTotalRewardAmount = 0; + // Distribute rewards among validator pools + if (stakingEpoch != 0) { + nativeTotalRewardAmount = _distributeRewards(stakingEpoch, stakingContract); + } + + // Snapshot total amounts staked into the pools + uint256 nextStakingEpoch = stakingEpoch + 1; + address[] memory miningAddresses; + + // We need to remember the total staked amounts for the pending addresses + // for when these pending addresses are finalized by `ValidatorSetHbbft.finalizeChange()`. + miningAddresses = validatorSetContract.getPendingValidators(); + _snapshotPoolStakeAmounts(stakingContract, nextStakingEpoch, miningAddresses); + + // We need to remember the total staked amounts for the current validators + // for the possible case when these validators continue to be validators + // throughout the upcoming staking epoch (if the new validator set is not finalized + // for some reason) + miningAddresses = validatorSetContract.getValidators(); + _snapshotPoolStakeAmounts(stakingContract, nextStakingEpoch, miningAddresses); + + // Remember validator's min reward percent for the upcoming staking epoch + validatorMinRewardPercent[nextStakingEpoch] = VALIDATOR_MIN_REWARD_PERCENT; + + // the rewards got distributed, + // we now can finalize the epoch and start with a new one. + validatorSetContract.finalizeChange(); + + return nativeTotalRewardAmount; + } + + function _closeBlock(IStakingHbbft stakingContract) private { + uint256 phaseTransitionTime = stakingContract.startTimeOfNextPhaseTransition(); + + address[] memory miningAddresses = validatorSetContract.getValidators(); + + // TODO: Problem occurs here if there are not regular blocks: + // https://github.com/DMDcoin/hbbft-posdao-contracts/issues/96 + + //we are in a transition to phase 2 if the time for it arrived, + // and we do not have pendingValidators yet. + bool isPhaseTransition = block.timestamp >= phaseTransitionTime; + bool toBeUpscaled = false; + if (miningAddresses.length * 3 <= (validatorSetContract.maxValidators() * 2)) { + uint256 amountToBeElected = stakingContract.getPoolsToBeElected().length; + if ( + (amountToBeElected > 0) && + validatorSetContract.getValidatorCountSweetSpot(amountToBeElected) > miningAddresses.length + ) { + toBeUpscaled = true; + } + } + + if ((isPhaseTransition || toBeUpscaled) && validatorSetContract.getPendingValidators().length == 0) { + // Choose new validators + validatorSetContract.newValidatorSet(); + } else if (block.timestamp >= stakingContract.stakingFixedEpochEndTime()) { + validatorSetContract.handleFailedKeyGeneration(); + } + } + + function _markRewardedValidators( + IStakingHbbft stakingContract, + uint256 stakingEpoch, + address[] memory validators + ) private view returns (uint256, bool[] memory) { + // Indicates whether the validator is entitled to share the rewartds or not. + bool[] memory isRewardedValidator = new bool[](validators.length); + + // Number of validators that are being rewarded. + uint256 numRewardedValidators = 0; + + for (uint256 i = 0; i < validators.length; ++i) { + if (validatorSetContract.isValidatorBanned(validators[i])) { + continue; + } + + uint256 validatorStakeAmount = stakingContract.getPoolValidatorStakeAmount( + stakingEpoch, + validatorSetContract.stakingByMiningAddress(validators[i]) + ); + + if (validatorStakeAmount == 0) { + continue; + } + + isRewardedValidator[i] = true; + ++numRewardedValidators; + } + + return (numRewardedValidators, isRewardedValidator); + } + + function _getPotsShares(uint256 numValidators) internal view returns (PotsShares memory) { + uint256 maxValidators = validatorSetContract.maxValidators(); + uint256 epochPercent = epochPercentage(); + + PotsShares memory shares = PotsShares(0, 0, 0, 0); + + shares.deltaPotAmount = + (deltaPot * numValidators * epochPercent) / + deltaPotPayoutFraction / + maxValidators / + 100; + + shares.reinsertPotAmount = + (reinsertPot * numValidators * epochPercent) / + reinsertPotPayoutFraction / + maxValidators / + 100; + + shares.totalRewards = nativeRewardUndistributed + shares.deltaPotAmount + shares.reinsertPotAmount; + + shares.governancePotAmount = + (shares.totalRewards * governancePotShareNominator) / + governancePotShareDenominator; + + return shares; } } diff --git a/contracts/StakingHbbft.sol b/contracts/StakingHbbft.sol index 7a53144b..235d0ed8 100644 --- a/contracts/StakingHbbft.sol +++ b/contracts/StakingHbbft.sol @@ -4,28 +4,33 @@ pragma solidity =0.8.17; import "./base/StakingHbbftBase.sol"; import { ValueGuards } from "./ValueGuards.sol"; import "./interfaces/IBlockRewardHbbftCoins.sol"; +import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; +import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; -contract Sacrifice2 { - constructor(address payable _recipient) payable { - selfdestruct(_recipient); - } -} +import { + EnumerableSetUpgradeable +} from "@openzeppelin/contracts-upgradeable/utils/structs/EnumerableSetUpgradeable.sol"; + +import { IBlockRewardHbbft } from "./interfaces/IBlockRewardHbbft.sol"; +import { IStakingHbbft } from "./interfaces/IStakingHbbft.sol"; +import { IValidatorSetHbbft } from "./interfaces/IValidatorSetHbbft.sol"; +import { TransferUtils } from "./utils/TransferUtils.sol"; /// @dev Implements staking and withdrawal logic. contract StakingHbbft is StakingHbbftBase, ValueGuards { // ================================================ Events ======================================================== - /// @dev Emitted by the `claimReward` function to signal the staker withdrew the specified - /// amount of native coins from the specified pool for the specified staking epoch. - /// @param fromPoolStakingAddress The pool from which the `staker` withdrew the amount. - /// @param staker The address of the staker that withdrew the amount. - /// @param stakingEpoch The serial number of the staking epoch for which the claim was made. - /// @param nativeCoinsAmount The withdrawal amount of native coins. - event ClaimedReward( + /// @dev Emitted by the `claimOrderedWithdraw` function to signal the staker withdrew the specified + /// amount of requested coins from the specified pool during the specified staking epoch. + /// @param fromPoolStakingAddress The pool from which the `staker` withdrew the `amount`. + /// @param staker The address of the staker that withdrew the `amount`. + /// @param stakingEpoch The serial number of the staking epoch during which the claim was made. + /// @param amount The withdrawal amount. + event ClaimedOrderedWithdrawal( address indexed fromPoolStakingAddress, address indexed staker, uint256 indexed stakingEpoch, - uint256 nativeCoinsAmount + uint256 amount ); /** @@ -36,97 +41,528 @@ contract StakingHbbft is StakingHbbftBase, ValueGuards { // =============================================== Setters ======================================================== - /// @dev Withdraws a reward from the specified pool for the specified staking epochs - /// to the staker address (msg.sender). - /// @param _stakingEpochs The list of staking epochs in ascending order. - /// If the list is empty, it is taken with `BlockRewardHbbft.epochsPoolGotRewardFor` getter. - /// @param _poolStakingAddress The staking address of the pool from which the reward needs to be withdrawn. - function claimReward( - uint256[] memory _stakingEpochs, - address _poolStakingAddress - ) public gasPriceIsValid { - address payable staker = payable(msg.sender); - uint256 firstEpoch = 0; - uint256 lastEpoch = 0; + /// @custom:oz-upgrades-unsafe-allow constructor + constructor() { + // Prevents initialization of implementation contract + _disableInitializers(); + } - if (_poolStakingAddress != staker) { - // this is a delegator - firstEpoch = stakeFirstEpoch[_poolStakingAddress][staker]; - require(firstEpoch != 0, "Claim: first epoch can't be 0"); - lastEpoch = stakeLastEpoch[_poolStakingAddress][staker]; - } + /// @dev Fallback function. Prevents direct sending native coins to this contract. + receive() external payable { + revert("Not payable"); + } + + /// @dev Initializes the network parameters. + /// Can only be called by the constructor of the `InitializerHbbft` contract or owner. + /// @param _contractOwner The address of the contract owner + /// @param stakingParams stores other parameters due to stack too deep issue + /// _validatorSetContract The address of the `ValidatorSetHbbft` contract. + /// _initialStakingAddresses The array of initial validators' staking addresses. + /// _delegatorMinStake The minimum allowed amount of delegator stake in Wei. + /// _candidateMinStake The minimum allowed amount of candidate/validator stake in Wei. + /// _stakingFixedEpochDuration The fixed duration of each epoch before keyGen starts. + /// _stakingTransitionTimeframeLength Length of the timeframe in seconds for the transition + /// to the new validator set. + /// _stakingWithdrawDisallowPeriod The duration period at the end of a staking epoch + /// during which participants cannot stake/withdraw/order/claim their staking coins + function initialize( + address _contractOwner, + StakingParams calldata stakingParams, + bytes32[] calldata _publicKeys, + bytes16[] calldata _internetAddresses + ) external initializer { + require(_contractOwner != address(0), "Owner address cannot be 0"); + + require(stakingParams._stakingFixedEpochDuration != 0, "FixedEpochDuration is 0"); + require( + stakingParams._stakingFixedEpochDuration > stakingParams._stakingWithdrawDisallowPeriod, + "FixedEpochDuration must be longer than withdrawDisallowPeriod" + ); + require(stakingParams._stakingWithdrawDisallowPeriod != 0, "WithdrawDisallowPeriod is 0"); + require(stakingParams._stakingTransitionTimeframeLength != 0, "The transition timeframe must be longer than 0"); + require( + stakingParams._stakingTransitionTimeframeLength < stakingParams._stakingFixedEpochDuration, + "The transition timeframe must be shorter then the epoch duration" + ); + + __Ownable_init(); + _transferOwnership(_contractOwner); + + _initialize( + stakingParams._validatorSetContract, + stakingParams._initialStakingAddresses, + stakingParams._delegatorMinStake, + stakingParams._candidateMinStake, + stakingParams._maxStake, + _publicKeys, + _internetAddresses + ); + + stakingFixedEpochDuration = stakingParams._stakingFixedEpochDuration; + stakingWithdrawDisallowPeriod = stakingParams._stakingWithdrawDisallowPeriod; + //note: this might be still 0 when created in the genesis block. + stakingEpochStartTime = block.timestamp; + stakingTransitionTimeframeLength = stakingParams._stakingTransitionTimeframeLength; + } + + function setStakingTransitionTimeframeLength(uint256 _value) external onlyOwner { + require(_value > 10, "The transition timeframe must be longer than 10"); + require(_value < stakingFixedEpochDuration, "The transition timeframe must be smaller than the epoch duration"); + + stakingTransitionTimeframeLength = _value; + } - IBlockRewardHbbftCoins blockRewardContract = IBlockRewardHbbftCoins( - validatorSetContract.blockRewardContract() + function setStakingFixedEpochDuration(uint256 _value) external onlyOwner { + require( + _value > stakingTransitionTimeframeLength, + "The fixed epoch duration timeframe must be greater than the transition timeframe length" ); - address miningAddress = validatorSetContract.miningByStakingAddress( - _poolStakingAddress + stakingFixedEpochDuration = _value; + } + + /// @dev Sets (updates) the limit of the minimum candidate stake (CANDIDATE_MIN_STAKE). + /// Can only be called by the `owner`. + /// @param _minStake The value of a new limit in Wei. + function setCandidateMinStake(uint256 _minStake) external onlyOwner { + candidateMinStake = _minStake; + } + + /// @dev Sets (updates) the limit of the minimum delegator stake (DELEGATOR_MIN_STAKE). + /// Can only be called by the `owner`. + /// @param _minStake The value of a new limit in Wei. + function setDelegatorMinStake(uint256 _minStake) external onlyOwner { + delegatorMinStake = _minStake; + } + + /// @dev Sets the timetamp of the current epoch's last block as the start time of the upcoming staking epoch. + /// Called by the `ValidatorSetHbbft.newValidatorSet` function at the last block of a staking epoch. + /// @param _timestamp The starting time of the very first block in the upcoming staking epoch. + function setStakingEpochStartTime(uint256 _timestamp) external onlyValidatorSetContract { + stakingEpochStartTime = _timestamp; + stakingEpochStartBlock = block.number; + } + + /// @dev set's the validators ip address. + /// this function can only be called by the validator Set contract. + /// @param _validatorAddress address if the validator. (mining address) + /// @param _ip IPV4 address of a running Node Software or Proxy. + function setValidatorInternetAddress( + address _validatorAddress, + bytes16 _ip, + bytes2 _port + ) external onlyValidatorSetContract { + poolInfo[_validatorAddress].internetAddress = _ip; + poolInfo[_validatorAddress].port = _port; + } + + /// @dev Increments the serial number of the current staking epoch. + /// Called by the `ValidatorSetHbbft.newValidatorSet` at the last block of the finished staking epoch. + function incrementStakingEpoch() external onlyValidatorSetContract { + stakingEpoch++; + currentKeyGenExtraTimeWindow = 0; + } + + /// @dev Notifies hbbft staking contract that the + /// key generation has failed, and a new round + /// of keygeneration starts. + function notifyKeyGenFailed() public onlyValidatorSetContract { + // we allow a extra time window for the current key generation + // equal in the size of the usual transition timeframe. + currentKeyGenExtraTimeWindow += stakingTransitionTimeframeLength; + } + + /// @dev Notifies hbbft staking contract about a detected + /// network offline time. + /// if there is no handling for this, + /// validators got chosen outside the transition timewindow + /// and get banned immediatly, since they never got their chance + /// to write their keys. + /// more about: https://github.com/DMDcoin/hbbft-posdao-contracts/issues/96 + function notifyNetworkOfftimeDetected(uint256 detectedOfflineTime) public onlyValidatorSetContract { + currentKeyGenExtraTimeWindow = + currentKeyGenExtraTimeWindow + + detectedOfflineTime + + stakingTransitionTimeframeLength; + } + + /// @dev Notifies hbbft staking contract that a validator + /// asociated with the given `_stakingAddress` became + /// available again and can be put on to the list + /// of available nodes again. + function notifyAvailability(address _stakingAddress) public onlyValidatorSetContract { + if (stakeAmount[_stakingAddress][_stakingAddress] >= candidateMinStake) { + _addPoolActive(_stakingAddress, true); + _setLikelihood(_stakingAddress); + } + } + + /// @dev Adds a new candidate's pool to the list of active pools (see the `getPools` getter) and + /// moves the specified amount of staking coins from the candidate's staking address + /// to the candidate's pool. A participant calls this function using their staking address when + /// they want to create a pool. This is a wrapper for the `stake` function. + /// @param _miningAddress The mining address of the candidate. The mining address is bound to the staking address + /// (msg.sender). This address cannot be equal to `msg.sender`. + function addPool(address _miningAddress, bytes calldata _publicKey, bytes16 _ip) external payable gasPriceIsValid { + address stakingAddress = msg.sender; + uint256 amount = msg.value; + validatorSetContract.setStakingAddress(_miningAddress, stakingAddress); + // The staking address and the staker are the same. + _stake(stakingAddress, stakingAddress, amount); + poolInfo[stakingAddress].publicKey = _publicKey; + poolInfo[stakingAddress].internetAddress = _ip; + + emit PlacedStake(stakingAddress, stakingAddress, stakingEpoch, amount); + } + + /// @dev Removes the candidate's or validator's pool from the `pools` array (a list of active pools which + /// can be retrieved by the `getPools` getter). When a candidate or validator wants to remove their pool, + /// they should call this function from their staking address. + function removeMyPool() external gasPriceIsValid { + address stakingAddress = msg.sender; + address miningAddress = validatorSetContract.miningByStakingAddress(stakingAddress); + // initial validator cannot remove their pool during the initial staking epoch + require( + stakingEpoch > 0 || !validatorSetContract.isValidator(miningAddress), + "Can't remove pool during 1st staking epoch" ); - uint256 rewardSum = 0; - uint256 delegatorStake = 0; + _removePool(stakingAddress); + } + + /// @dev set's the pool info for a specific ethereum address. + /// @param _publicKey public key of the (future) signing address. + /// @param _ip (optional) IPV4 address of a running Node Software or Proxy. + /// @param _port (optional) port of IPv4 address of a running Node Software or Proxy. + /// Stores the supplied data for a staking (pool) address. + /// This function is external available without security checks, + /// since no array operations are used in the implementation, + /// this allows the flexibility to set the pool information before + /// adding the stake to the pool. + function setPoolInfo(bytes calldata _publicKey, bytes16 _ip, bytes2 _port) external { + poolInfo[msg.sender].publicKey = _publicKey; + poolInfo[msg.sender].internetAddress = _ip; + poolInfo[msg.sender].port = _port; + } + + /// @dev Removes a specified pool from the `pools` array (a list of active pools which can be retrieved by the + /// `getPools` getter). Called by the `ValidatorSetHbbft._removeMaliciousValidator` internal function, + /// and the `ValidatorSetHbbft.handleFailedKeyGeneration` function + /// when a pool must be removed by the algorithm. + /// @param _stakingAddress The staking address of the pool to be removed. + function removePool(address _stakingAddress) external onlyValidatorSetContract { + _removePool(_stakingAddress); + } + + /// @dev Removes pools which are in the `_poolsToBeRemoved` internal array from the `pools` array. + /// Called by the `ValidatorSetHbbft.newValidatorSet` function when a pool must be removed by the algorithm. + function removePools() external onlyValidatorSetContract { + address[] memory poolsToRemove = _poolsToBeRemoved.values(); + for (uint256 i = 0; i < poolsToRemove.length; i++) { + _removePool(poolsToRemove[i]); + } + } + + /// @dev Moves the specified amount of staking coins from the staker's address to the staking address of + /// the specified pool. Actually, the amount is stored in a balance of this StakingHbbft contract. + /// A staker calls this function when they want to make a stake into a pool. + /// @param _toPoolStakingAddress The staking address of the pool where the coins should be staked. + function stake(address _toPoolStakingAddress) external payable gasPriceIsValid { + address staker = msg.sender; + uint256 amount = msg.value; + _stake(_toPoolStakingAddress, staker, amount); + + emit PlacedStake(_toPoolStakingAddress, staker, stakingEpoch, amount); + } + + /// @dev Moves the specified amount of staking coins from the staking address of + /// the specified pool to the staker's address. A staker calls this function when they want to withdraw + /// their coins. + /// @param _fromPoolStakingAddress The staking address of the pool from which the coins should be withdrawn. + /// @param _amount The amount of coins to be withdrawn. The amount cannot exceed the value returned + /// by the `maxWithdrawAllowed` getter. + function withdraw(address _fromPoolStakingAddress, uint256 _amount) external gasPriceIsValid { + address payable staker = payable(msg.sender); + _withdraw(_fromPoolStakingAddress, staker, _amount); + TransferUtils.transferNativeEnsure(staker, _amount); + emit WithdrewStake(_fromPoolStakingAddress, staker, stakingEpoch, _amount); + } + + /// @dev Moves staking coins from one pool to another. A staker calls this function when they want + /// to move their coins from one pool to another without withdrawing their coins. + /// @param _fromPoolStakingAddress The staking address of the source pool. + /// @param _toPoolStakingAddress The staking address of the target pool. + /// @param _amount The amount of staking coins to be moved. The amount cannot exceed the value returned + /// by the `maxWithdrawAllowed` getter. + function moveStake( + address _fromPoolStakingAddress, + address _toPoolStakingAddress, + uint256 _amount + ) external gasPriceIsValid { + require(_fromPoolStakingAddress != _toPoolStakingAddress, "MoveStake: src and dst pool is the same"); + address staker = msg.sender; + _withdraw(_fromPoolStakingAddress, staker, _amount); + _stake(_toPoolStakingAddress, staker, _amount); + emit MovedStake(_fromPoolStakingAddress, _toPoolStakingAddress, staker, stakingEpoch, _amount); + } - if (_stakingEpochs.length == 0) { - _stakingEpochs = IBlockRewardHbbft(address(blockRewardContract)) - .epochsPoolGotRewardFor(miningAddress); + function restake( + address _poolStakingAddress, + uint256 _validatorMinRewardPercent + ) external payable onlyBlockRewardContract { + // msg.value is a pool reward + if (msg.value == 0) { + return; } - for (uint256 i = 0; i < _stakingEpochs.length; i++) { - uint256 epoch = _stakingEpochs[i]; + uint256 poolReward = msg.value; + uint256 totalStake = snapshotPoolTotalStakeAmount[stakingEpoch][_poolStakingAddress]; + uint256 validatorStake = snapshotPoolValidatorStakeAmount[stakingEpoch][_poolStakingAddress]; + + uint256 validatorReward = 0; + + if (totalStake > validatorStake) { + address[] memory delegators = poolDelegators(_poolStakingAddress); + + uint256 delegatorsStake = totalStake - validatorStake; + + bool minRewardPercentExceeded = validatorStake * (100 - _validatorMinRewardPercent) > + delegatorsStake * _validatorMinRewardPercent; + + validatorReward = _validatorRewardShare( + minRewardPercentExceeded, + validatorStake, + totalStake, + poolReward, + _validatorMinRewardPercent + ); + + for (uint256 i = 0; i < delegators.length; ++i) { + uint256 delegatorReward = _delegatorRewardShare( + minRewardPercentExceeded, + totalStake, + _getDelegatorStake(stakingEpoch, _poolStakingAddress, delegators[i]), + delegatorsStake, + poolReward, + _validatorMinRewardPercent + ); + + stakeAmount[_poolStakingAddress][delegators[i]] += delegatorReward; + _stakeAmountByEpoch[_poolStakingAddress][delegators[i]][stakingEpoch] += delegatorReward; + } + } else { + // Whole pool stake belongs to the pool owner + // and he received all the rewards. + validatorReward = poolReward; + } + + stakeAmount[_poolStakingAddress][_poolStakingAddress] += validatorReward; + stakeAmountTotal[_poolStakingAddress] += poolReward; + + _setLikelihood(_poolStakingAddress); + + emit RestakeReward(_poolStakingAddress, stakingEpoch, validatorReward, poolReward - validatorReward); + } + + /// @dev Orders coins withdrawal from the staking address of the specified pool to the + /// staker's address. The requested coins can be claimed after the current staking epoch is complete using + /// the `claimOrderedWithdraw` function. + /// @param _poolStakingAddress The staking address of the pool from which the amount will be withdrawn. + /// @param _amount The amount to be withdrawn. A positive value means the staker wants to either set or + /// increase their withdrawal amount. A negative value means the staker wants to decrease a + /// withdrawal amount that was previously set. The amount cannot exceed the value returned by the + /// `maxWithdrawOrderAllowed` getter. + function orderWithdraw(address _poolStakingAddress, int256 _amount) external gasPriceIsValid { + require(_poolStakingAddress != address(0), "poolStakingAddress must not be 0x0"); + require(_amount != 0, "ordered withdraw amount must not be 0"); + + address staker = msg.sender; + require( + _isWithdrawAllowed( + validatorSetContract.miningByStakingAddress(_poolStakingAddress), + staker != _poolStakingAddress + ), + "OrderWithdraw: not allowed" + ); + + uint256 newOrderedAmount = orderedWithdrawAmount[_poolStakingAddress][staker]; + uint256 newOrderedAmountTotal = orderedWithdrawAmountTotal[_poolStakingAddress]; + uint256 newStakeAmount = stakeAmount[_poolStakingAddress][staker]; + uint256 newStakeAmountTotal = stakeAmountTotal[_poolStakingAddress]; + if (_amount > 0) { + uint256 amount = uint256(_amount); + + // How much can `staker` order for withdrawal from `_poolStakingAddress` at the moment? require( - i == 0 || epoch > _stakingEpochs[i - 1], - "Claim: need strictly increasing order" + amount <= maxWithdrawOrderAllowed(_poolStakingAddress, staker), + "OrderWithdraw: maxWithdrawOrderAllowed exceeded" ); - require(epoch < stakingEpoch, "Claim: only before current epoch"); - if (rewardWasTaken[_poolStakingAddress][staker][epoch]) continue; + newOrderedAmount = newOrderedAmount + amount; + newOrderedAmountTotal = newOrderedAmountTotal + amount; + newStakeAmount = newStakeAmount - amount; + newStakeAmountTotal = newStakeAmountTotal - amount; + orderWithdrawEpoch[_poolStakingAddress][staker] = stakingEpoch; + } else { + uint256 amount = uint256(-_amount); + newOrderedAmount = newOrderedAmount - amount; + newOrderedAmountTotal = newOrderedAmountTotal - amount; + newStakeAmount = newStakeAmount + amount; + newStakeAmountTotal = newStakeAmountTotal + amount; + } + orderedWithdrawAmount[_poolStakingAddress][staker] = newOrderedAmount; + orderedWithdrawAmountTotal[_poolStakingAddress] = newOrderedAmountTotal; + stakeAmount[_poolStakingAddress][staker] = newStakeAmount; + stakeAmountTotal[_poolStakingAddress] = newStakeAmountTotal; - uint256 reward; + if (staker == _poolStakingAddress) { + // The amount to be withdrawn must be the whole staked amount or + // must not exceed the diff between the entire amount and `candidateMinStake` + require( + newStakeAmount == 0 || newStakeAmount >= candidateMinStake, + "newStake Amount must be greater than the min stake." + ); - if (_poolStakingAddress != staker) { - // this is a delegator - if (epoch < firstEpoch) { - // If the delegator staked for the first time after - // the `epoch`, skip this staking epoch - continue; + if (_amount > 0) { + // if the validator orders the `_amount` for withdrawal + if (newStakeAmount == 0) { + // If the validator orders their entire stake, + // mark their pool as `to be removed` + _addPoolToBeRemoved(_poolStakingAddress); } + } else { + // If the validator wants to reduce withdrawal value, + // add their pool as `active` if it hasn't been already done. + _addPoolActive(_poolStakingAddress, true); + } + } else { + // The amount to be withdrawn must be the whole staked amount or + // must not exceed the diff between the entire amount and `delegatorMinStake` + require( + newStakeAmount == 0 || newStakeAmount >= delegatorMinStake, + "newStake Amount must be greater than the min stake." + ); - if (lastEpoch <= epoch && lastEpoch != 0) { - // If the delegator withdrew all their stake before the `epoch`, - // don't check this and following epochs since it makes no sense - break; + if (_amount > 0) { + // if the delegator orders the `_amount` for withdrawal + if (newStakeAmount == 0) { + // If the delegator orders their entire stake, + // remove the delegator from delegator list of the pool + _removePoolDelegator(_poolStakingAddress, staker); } + } else { + // If the delegator wants to reduce withdrawal value, + // add them to delegator list of the pool if it hasn't already done + _addPoolDelegator(_poolStakingAddress, staker); + } - delegatorStake = _getDelegatorStake( - epoch, - firstEpoch, - delegatorStake, - _poolStakingAddress, - staker - ); - firstEpoch = epoch + 1; + // Remember stake movement to use it later in the `claimReward` function + // _snapshotDelegatorStake(_poolStakingAddress, staker); + } - reward = blockRewardContract.getDelegatorReward( - delegatorStake, - epoch, - miningAddress - ); - } else { - // this is a validator - reward = blockRewardContract.getValidatorReward( - epoch, - miningAddress - ); + _setLikelihood(_poolStakingAddress); + + emit OrderedWithdrawal(_poolStakingAddress, staker, stakingEpoch, _amount); + } + + /// @dev Withdraws the staking coins from the specified pool ordered during the previous staking epochs with + /// the `orderWithdraw` function. The ordered amount can be retrieved by the `orderedWithdrawAmount` getter. + /// @param _poolStakingAddress The staking address of the pool from which the ordered coins are withdrawn. + function claimOrderedWithdraw(address _poolStakingAddress) external gasPriceIsValid { + address payable staker = payable(msg.sender); + + require( + stakingEpoch > orderWithdrawEpoch[_poolStakingAddress][staker], + "cannot claim ordered withdraw in the same epoch it was ordered." + ); + require( + _isWithdrawAllowed( + validatorSetContract.miningByStakingAddress(_poolStakingAddress), + staker != _poolStakingAddress + ), + "ClaimOrderedWithdraw: Withdraw not allowed" + ); + + uint256 claimAmount = orderedWithdrawAmount[_poolStakingAddress][staker]; + require(claimAmount != 0, "claim amount must not be 0"); + + orderedWithdrawAmount[_poolStakingAddress][staker] = 0; + orderedWithdrawAmountTotal[_poolStakingAddress] = orderedWithdrawAmountTotal[_poolStakingAddress] - claimAmount; + + if (stakeAmount[_poolStakingAddress][staker] == 0) { + _withdrawCheckPool(_poolStakingAddress, staker); + } + + TransferUtils.transferNativeEnsure(staker, claimAmount); + + emit ClaimedOrderedWithdrawal(_poolStakingAddress, staker, stakingEpoch, claimAmount); + } + + /// @dev Distribute abandoned stakes among Reinsert and Governance pots. + /// 50% goes to reinsert and 50% to governance pot. + /// Coins are considered abandoned if they were staked on a validator inactive for 10 years. + function recoverAbandonedStakes() external gasPriceIsValid { + uint256 totalAbandonedAmount = 0; + + address[] memory inactivePools = _poolsInactive.values(); + require(inactivePools.length != 0, "nothing to recover"); + + for (uint256 i = 0; i < inactivePools.length; ++i) { + address stakingAddress = inactivePools[i]; + + if (_isPoolEmpty(stakingAddress) || !validatorSetContract.isValidatorAbandoned(stakingAddress)) { + continue; + } + + _poolsInactive.remove(stakingAddress); + abandonedAndRemoved[stakingAddress] = true; + + uint256 gatheredPerStakingAddress = stakeAmountTotal[stakingAddress]; + stakeAmountTotal[stakingAddress] = 0; + + address[] memory delegators = poolDelegators(stakingAddress); + for (uint256 j = 0; j < delegators.length; ++j) { + address delegator = delegators[j]; + + stakeAmount[stakingAddress][delegator] = 0; + _removePoolDelegator(stakingAddress, delegator); } - rewardSum = rewardSum + reward; + totalAbandonedAmount += gatheredPerStakingAddress; + + emit GatherAbandonedStakes(msg.sender, stakingAddress, gatheredPerStakingAddress); + } + + require(totalAbandonedAmount != 0, "nothing to recover"); - rewardWasTaken[_poolStakingAddress][staker][epoch] = true; + uint256 governanceShare = totalAbandonedAmount / 2; + uint256 reinsertShare = totalAbandonedAmount - governanceShare; + + IBlockRewardHbbft blockRewardHbbft = IBlockRewardHbbft(validatorSetContract.blockRewardContract()); + address governanceAddress = blockRewardHbbft.getGovernanceAddress(); + + // slither-disable-next-line arbitrary-send-eth + blockRewardHbbft.addToReinsertPot{ value: reinsertShare }(); + TransferUtils.transferNative(governanceAddress, governanceShare); + + emit RecoverAbandonedStakes(msg.sender, reinsertShare, governanceShare); + } - emit ClaimedReward(_poolStakingAddress, staker, epoch, reward); + /// @dev Makes snapshots of total amount staked into the specified pool + /// before the specified staking epoch. Used by the `reward` function. + /// @param _epoch The number of upcoming staking epoch. + /// @param _stakingPool The staking address of the pool. + function snapshotPoolStakeAmounts(uint256 _epoch, address _stakingPool) external onlyBlockRewardContract { + if (snapshotPoolTotalStakeAmount[_epoch][_stakingPool] != 0) { + return; } - blockRewardContract.transferReward(rewardSum, staker); + uint256 totalAmount = stakeAmountTotal[_stakingPool]; + if (totalAmount == 0) { + return; + } + + snapshotPoolTotalStakeAmount[_epoch][_stakingPool] = totalAmount; + snapshotPoolValidatorStakeAmount[_epoch][_stakingPool] = stakeAmount[_stakingPool][_stakingPool]; } /** @@ -174,109 +610,655 @@ contract StakingHbbft is StakingHbbftBase, ValueGuards { // =============================================== Getters ======================================================== - /// @dev Returns reward amount in native coins for the specified pool, the specified staking epochs, - /// and the specified staker address (delegator or validator). - /// @param _stakingEpochs The list of staking epochs in ascending order. - /// If the list is empty, it is taken with `BlockRewardHbbft.epochsPoolGotRewardFor` getter. - /// @param _poolStakingAddress The staking address of the pool for which the amounts need to be returned. - /// @param _staker The staker address (validator's staking address or delegator's address). - function getRewardAmount( - uint256[] memory _stakingEpochs, - address _poolStakingAddress, - address _staker - ) public view returns (uint256) { - uint256 firstEpoch = 0; - uint256 lastEpoch = 0; - - if (_poolStakingAddress != _staker) { - // this is a delegator - firstEpoch = stakeFirstEpoch[_poolStakingAddress][_staker]; - require( - firstEpoch != 0, - "Unable to get reward amount if no first epoch." - ); - lastEpoch = stakeLastEpoch[_poolStakingAddress][_staker]; + /// @dev Returns an array of the current active pools (the staking addresses of candidates and validators). + /// The size of the array cannot exceed MAX_CANDIDATES. A pool can be added to this array with the `_addPoolActive` + /// internal function which is called by the `stake` or `orderWithdraw` function. A pool is considered active + /// if its address has at least the minimum stake and this stake is not ordered to be withdrawn. + function getPools() external view returns (address[] memory) { + return _pools.values(); + } + + /// @dev Return the Public Key used by a Node to send targeted HBBFT Consensus Messages. + /// @param _poolAddress The Pool Address to query the public key for. + /// @return the public key for the given pool address. + /// Note that the public key does not convert to the ethereum address of the pool address. + /// The pool address is used for stacking, and not for signing HBBFT messages. + function getPoolPublicKey(address _poolAddress) external view returns (bytes memory) { + return poolInfo[_poolAddress].publicKey; + } + + /// @dev Returns the registered IPv4 Address for the node. + /// @param _poolAddress The Pool Address to query the IPv4Address for. + /// @return IPv4 Address for the given pool address. + function getPoolInternetAddress(address _poolAddress) external view returns (bytes16, bytes2) { + return (poolInfo[_poolAddress].internetAddress, poolInfo[_poolAddress].port); + } + + /// @dev Returns an array of the current inactive pools (the staking addresses of former candidates). + /// A pool can be added to this array with the `_addPoolInactive` internal function which is called + /// by `_removePool`. A pool is considered inactive if it is banned for some reason, if its address + /// has zero stake, or if its entire stake is ordered to be withdrawn. + function getPoolsInactive() external view returns (address[] memory) { + return _poolsInactive.values(); + } + + /// @dev Returns the array of stake amounts for each corresponding + /// address in the `poolsToBeElected` array (see the `getPoolsToBeElected` getter) and a sum of these amounts. + /// Used by the `ValidatorSetHbbft.newValidatorSet` function when randomly selecting new validators at the last + /// block of a staking epoch. An array value is updated every time any staked amount is changed in this pool + /// (see the `_setLikelihood` internal function). + /// @return likelihoods `uint256[] likelihoods` - The array of the coefficients. The array length is always equal + /// to the length of the `poolsToBeElected` array. + /// `uint256 sum` - The total sum of the amounts. + function getPoolsLikelihood() external view returns (uint256[] memory likelihoods, uint256 sum) { + return (_poolsLikelihood, _poolsLikelihoodSum); + } + + /// @dev Returns the list of pools (their staking addresses) which will participate in a new validator set + /// selection process in the `ValidatorSetHbbft.newValidatorSet` function. This is an array of pools + /// which will be considered as candidates when forming a new validator set (at the last block of a staking epoch). + /// This array is kept updated by the `_addPoolToBeElected` and `_deletePoolToBeElected` internal functions. + function getPoolsToBeElected() external view returns (address[] memory) { + return _poolsToBeElected; + } + + /// @dev Returns the list of pools (their staking addresses) which will be removed by the + /// `ValidatorSetHbbft.newValidatorSet` function from the active `pools` array (at the last block + /// of a staking epoch). This array is kept updated by the `_addPoolToBeRemoved` + /// and `_deletePoolToBeRemoved` internal functions. A pool is added to this array when the pool's + /// address withdraws (or orders) all of its own staking coins from the pool, inactivating the pool. + function getPoolsToBeRemoved() external view returns (address[] memory) { + return _poolsToBeRemoved.values(); + } + + function getPoolValidatorStakeAmount(uint256 _epoch, address _stakingPool) external view returns (uint256) { + return snapshotPoolValidatorStakeAmount[_epoch][_stakingPool]; + } + + /// @dev Determines whether staking/withdrawal operations are allowed at the moment. + /// Used by all staking/withdrawal functions. + function areStakeAndWithdrawAllowed() public pure returns (bool) { + //experimental change to always allow to stake withdraw. + //see https://github.com/DMDcoin/hbbft-posdao-contracts/issues/14 for discussion. + return true; + + // used for testing + // if (stakingFixedEpochDuration == 0){ + // return true; + // } + // uint256 currentTimestamp = block.timestamp; + // uint256 allowedDuration = stakingFixedEpochDuration - stakingWithdrawDisallowPeriod; + // return currentTimestamp - stakingEpochStartTime > allowedDuration; //TODO: should be < not <=? + } + + /// @dev Returns a flag indicating whether a specified address is in the `pools` array. + /// See the `getPools` getter. + /// @param _stakingAddress The staking address of the pool. + function isPoolActive(address _stakingAddress) public view returns (bool) { + return _pools.contains(_stakingAddress); + } + + /// @dev Returns the maximum amount which can be withdrawn from the specified pool by the specified staker + /// at the moment. Used by the `withdraw` and `moveStake` functions. + /// @param _poolStakingAddress The pool staking address from which the withdrawal will be made. + /// @param _staker The staker address that is going to withdraw. + function maxWithdrawAllowed(address _poolStakingAddress, address _staker) public view returns (uint256) { + address miningAddress = validatorSetContract.miningByStakingAddress(_poolStakingAddress); + + if ( + !_isWithdrawAllowed(miningAddress, _poolStakingAddress != _staker) || + abandonedAndRemoved[_poolStakingAddress] + ) { + return 0; } - IBlockRewardHbbftCoins blockRewardContract = IBlockRewardHbbftCoins( - validatorSetContract.blockRewardContract() - ); - address miningAddress = validatorSetContract.miningByStakingAddress( - _poolStakingAddress - ); - uint256 delegatorStake = 0; - uint256 rewardSum = 0; + uint256 canWithdraw = stakeAmount[_poolStakingAddress][_staker]; - if (_stakingEpochs.length == 0) { - _stakingEpochs = IBlockRewardHbbft(address(blockRewardContract)) - .epochsPoolGotRewardFor(miningAddress); + if (!validatorSetContract.isValidatorOrPending(miningAddress)) { + // The pool is not a validator and is not going to become one, + // so the staker can only withdraw staked amount minus already + // ordered amount + return canWithdraw; } - for (uint256 i = 0; i < _stakingEpochs.length; i++) { - uint256 epoch = _stakingEpochs[i]; + // The pool is a validator (active or pending), so the staker can only + // withdraw staked amount minus already ordered amount but + // no more than the amount staked during the current staking epoch + uint256 stakedDuringEpoch = stakeAmountByCurrentEpoch(_poolStakingAddress, _staker); - require( - i == 0 || epoch > _stakingEpochs[i - 1], - "internal Error: Staking Epochs required to be ordered." - ); - require( - epoch < stakingEpoch, - "internal Error: epoch must not be lesser than current epoch." + if (canWithdraw > stakedDuringEpoch) { + canWithdraw = stakedDuringEpoch; + } + + return canWithdraw; + } + + /// @dev Returns the maximum amount which can be ordered to be withdrawn from the specified pool by the + /// specified staker at the moment. Used by the `orderWithdraw` function. + /// @param _poolStakingAddress The pool staking address from which the withdrawal will be ordered. + /// @param _staker The staker address that is going to order the withdrawal. + function maxWithdrawOrderAllowed(address _poolStakingAddress, address _staker) public view returns (uint256) { + address miningAddress = validatorSetContract.miningByStakingAddress(_poolStakingAddress); + + if (!_isWithdrawAllowed(miningAddress, _poolStakingAddress != _staker)) { + return 0; + } + + if (!validatorSetContract.isValidatorOrPending(miningAddress)) { + // If the pool is a candidate (not an active validator and not pending one), + // no one can order withdrawal from the `_poolStakingAddress`, but + // anyone can withdraw immediately (see the `maxWithdrawAllowed` getter) + return 0; + } + + // If the pool is an active or pending validator, the staker can order withdrawal + // up to their total staking amount minus an already ordered amount + // minus an amount staked during the current staking epoch + return stakeAmount[_poolStakingAddress][_staker] - stakeAmountByCurrentEpoch(_poolStakingAddress, _staker); + } + + /// @dev Returns an array of the current active delegators of the specified pool. + /// A delegator is considered active if they have staked into the specified + /// pool and their stake is not ordered to be withdrawn. + /// @param _poolStakingAddress The pool staking address. + function poolDelegators(address _poolStakingAddress) public view returns (address[] memory) { + return _poolDelegators[_poolStakingAddress].values(); + } + + /// @dev Returns an array of the current inactive delegators of the specified pool. + /// A delegator is considered inactive if their entire stake is ordered to be withdrawn + /// but not yet claimed. + /// @param _poolStakingAddress The pool staking address. + function poolDelegatorsInactive(address _poolStakingAddress) external view returns (address[] memory) { + return _poolDelegatorsInactive[_poolStakingAddress].values(); + } + + /// @dev Returns the amount of staking coins staked into the specified pool by the specified staker + /// during the current staking epoch (see the `stakingEpoch` getter). + /// Used by the `stake`, `withdraw`, and `orderWithdraw` functions. + /// @param _poolStakingAddress The pool staking address. + /// @param _staker The staker's address. + function stakeAmountByCurrentEpoch(address _poolStakingAddress, address _staker) public view returns (uint256) { + return _stakeAmountByEpoch[_poolStakingAddress][_staker][stakingEpoch]; + } + + /// @dev indicates the time when the new validatorset for the next epoch gets chosen. + /// this is the start of a timeframe before the end of the epoch, + /// that is long enough for the validators + /// to create a new shared key. + function startTimeOfNextPhaseTransition() public view returns (uint256) { + return stakingEpochStartTime + stakingFixedEpochDuration - stakingTransitionTimeframeLength; + } + + /// @dev Returns an indicative time of the last block of the current staking epoch before key generation starts. + function stakingFixedEpochEndTime() public view returns (uint256) { + uint256 startTime = stakingEpochStartTime; + return + startTime + + stakingFixedEpochDuration + + currentKeyGenExtraTimeWindow - + (stakingFixedEpochDuration == 0 ? 0 : 1); + } + + // ============================================== Internal ======================================================== + /// @dev Initializes the network parameters. Used by the `initialize` function. + /// @param _validatorSetContract The address of the `ValidatorSetHbbft` contract. + /// @param _initialStakingAddresses The array of initial validators' staking addresses. + /// @param _delegatorMinStake The minimum allowed amount of delegator stake in Wei. + /// @param _candidateMinStake The minimum allowed amount of candidate/validator stake in Wei. + function _initialize( + address _validatorSetContract, + address[] memory _initialStakingAddresses, + uint256 _delegatorMinStake, + uint256 _candidateMinStake, + uint256 _maxStake, + bytes32[] memory _publicKeys, + bytes16[] memory _internetAddresses + ) internal { + require(_validatorSetContract != address(0), "ValidatorSet can't be 0"); + require(_initialStakingAddresses.length > 0, "Must provide initial mining addresses"); + require(_initialStakingAddresses.length * 2 == _publicKeys.length, "Must provide correct number of publicKeys"); + require( + _initialStakingAddresses.length == _internetAddresses.length, + "Must provide correct number of IP adresses" + ); + require(_delegatorMinStake != 0, "DelegatorMinStake is 0"); + require(_candidateMinStake != 0, "CandidateMinStake is 0"); + require(_maxStake > _candidateMinStake, "maximum stake must be greater then minimum stake."); + + validatorSetContract = IValidatorSetHbbft(_validatorSetContract); + + for (uint256 i = 0; i < _initialStakingAddresses.length; i++) { + require(_initialStakingAddresses[i] != address(0), "InitialStakingAddresses can't be 0"); + _addPoolActive(_initialStakingAddresses[i], false); + _addPoolToBeRemoved(_initialStakingAddresses[i]); + poolInfo[_initialStakingAddresses[i]].publicKey = abi.encodePacked( + _publicKeys[i * 2], + _publicKeys[i * 2 + 1] ); + poolInfo[_initialStakingAddresses[i]].internetAddress = _internetAddresses[i]; + } - if (rewardWasTaken[_poolStakingAddress][_staker][epoch]) continue; + delegatorMinStake = _delegatorMinStake; + candidateMinStake = _candidateMinStake; - uint256 reward; + maxStakeAmount = _maxStake; + } - if (_poolStakingAddress != _staker) { - // this is a delegator - if (epoch < firstEpoch) continue; - if (lastEpoch <= epoch && lastEpoch != 0) break; + /// @dev Adds the specified staking address to the array of active pools returned by + /// the `getPools` getter. Used by the `stake`, `addPool`, and `orderWithdraw` functions. + /// @param _stakingAddress The pool added to the array of active pools. + /// @param _toBeElected The boolean flag which defines whether the specified address should be + /// added simultaneously to the `poolsToBeElected` array. See the `getPoolsToBeElected` getter. + function _addPoolActive(address _stakingAddress, bool _toBeElected) internal { + if (!isPoolActive(_stakingAddress)) { + _pools.add(_stakingAddress); + require(_pools.length() <= _getMaxCandidates(), "MAX_CANDIDATES pools exceeded"); + } - delegatorStake = _getDelegatorStake( - epoch, - firstEpoch, - delegatorStake, - _poolStakingAddress, - _staker - ); - firstEpoch = epoch + 1; + _poolsInactive.remove(_stakingAddress); - reward = blockRewardContract.getDelegatorReward( - delegatorStake, - epoch, - miningAddress - ); + if (_toBeElected) { + _addPoolToBeElected(_stakingAddress); + } + } + + /// @dev Adds the specified staking address to the array of inactive pools returned by + /// the `getPoolsInactive` getter. Used by the `_removePool` internal function. + /// @param _stakingAddress The pool added to the array of inactive pools. + function _addPoolInactive(address _stakingAddress) internal { + // This function performs internal checks if value already exists + _poolsInactive.add(_stakingAddress); + } + + /// @dev Adds the specified staking address to the array of pools returned by the `getPoolsToBeElected` + /// getter. Used by the `_addPoolActive` internal function. See the `getPoolsToBeElected` getter. + /// @param _stakingAddress The pool added to the `poolsToBeElected` array. + function _addPoolToBeElected(address _stakingAddress) private { + uint256 index = poolToBeElectedIndex[_stakingAddress]; + uint256 length = _poolsToBeElected.length; + if (index >= length || _poolsToBeElected[index] != _stakingAddress) { + poolToBeElectedIndex[_stakingAddress] = length; + _poolsToBeElected.push(_stakingAddress); + _poolsLikelihood.push(0); // assumes the likelihood is set with `_setLikelihood` function hereinafter + } + _deletePoolToBeRemoved(_stakingAddress); + } + + /// @dev Adds the specified staking address to the array of pools returned by the `getPoolsToBeRemoved` + /// getter. Used by withdrawal functions. See the `getPoolsToBeRemoved` getter. + /// @param _stakingAddress The pool added to the `poolsToBeRemoved` array. + function _addPoolToBeRemoved(address _stakingAddress) private { + _poolsToBeRemoved.add(_stakingAddress); + + _deletePoolToBeElected(_stakingAddress); + } + + /// @dev Deletes the specified staking address from the array of pools returned by the + /// `getPoolsToBeElected` getter. Used by the `_addPoolToBeRemoved` and `_removePool` internal functions. + /// See the `getPoolsToBeElected` getter. + /// @param _stakingAddress The pool deleted from the `poolsToBeElected` array. + function _deletePoolToBeElected(address _stakingAddress) private { + if (_poolsToBeElected.length != _poolsLikelihood.length) return; + + uint256 indexToDelete = poolToBeElectedIndex[_stakingAddress]; + if (_poolsToBeElected.length > indexToDelete && _poolsToBeElected[indexToDelete] == _stakingAddress) { + if (_poolsLikelihoodSum >= _poolsLikelihood[indexToDelete]) { + _poolsLikelihoodSum -= _poolsLikelihood[indexToDelete]; } else { - // this is a validator - reward = blockRewardContract.getValidatorReward( - epoch, - miningAddress - ); + _poolsLikelihoodSum = 0; } - rewardSum += reward; + uint256 lastPoolIndex = _poolsToBeElected.length - 1; + address lastPool = _poolsToBeElected[lastPoolIndex]; + + _poolsToBeElected[indexToDelete] = lastPool; + _poolsLikelihood[indexToDelete] = _poolsLikelihood[lastPoolIndex]; + + poolToBeElectedIndex[lastPool] = indexToDelete; + poolToBeElectedIndex[_stakingAddress] = 0; + + _poolsToBeElected.pop(); + _poolsLikelihood.pop(); } + } - return rewardSum; + /// @dev Deletes the specified staking address from the array of pools returned by the + /// `getPoolsToBeRemoved` getter. Used by the `_addPoolToBeElected` and `_removePool` internal functions. + /// See the `getPoolsToBeRemoved` getter. + /// @param _stakingAddress The pool deleted from the `poolsToBeRemoved` array. + function _deletePoolToBeRemoved(address _stakingAddress) private { + _poolsToBeRemoved.remove(_stakingAddress); } - // ============================================== Internal ======================================================== + /// @dev Removes the specified staking address from the array of active pools returned by + /// the `getPools` getter. Used by the `removePool`, `removeMyPool`, and withdrawal functions. + /// @param _stakingAddress The pool removed from the array of active pools. + function _removePool(address _stakingAddress) private { + // This function performs existence check internally + _pools.remove(_stakingAddress); - /// @dev Sends coins from this contract to the specified address. - /// @param _to The target address to send amount to. - /// @param _amount The amount to send. - function _sendWithdrawnStakeAmount(address payable _to, uint256 _amount) - internal - virtual - override - { - // slither-disable-next-line arbitrary-send-eth - if (!_to.send(_amount)) { - // We use the `Sacrifice` trick to be sure the coins can be 100% sent to the receiver. - // Otherwise, if the receiver is a contract which has a revert in its fallback function, - // the sending will fail. - (new Sacrifice2){value: _amount}(_to); + if (_isPoolEmpty(_stakingAddress)) { + _poolsInactive.remove(_stakingAddress); + } else { + _addPoolInactive(_stakingAddress); + } + + _deletePoolToBeElected(_stakingAddress); + _deletePoolToBeRemoved(_stakingAddress); + } + + /// @dev Returns the max number of candidates (including validators). See the MAX_CANDIDATES constant. + /// Needed mostly for unit tests. + function _getMaxCandidates() internal pure virtual returns (uint256) { + return MAX_CANDIDATES; + } + + /// @dev Adds the specified address to the array of the current active delegators of the specified pool. + /// Used by the `stake` and `orderWithdraw` functions. See the `poolDelegators` getter. + /// @param _poolStakingAddress The pool staking address. + /// @param _delegator The delegator's address. + function _addPoolDelegator(address _poolStakingAddress, address _delegator) private { + _poolDelegators[_poolStakingAddress].add(_delegator); + + _removePoolDelegatorInactive(_poolStakingAddress, _delegator); + } + + /// @dev Adds the specified address to the array of the current inactive delegators of the specified pool. + /// Used by the `_removePoolDelegator` internal function. + /// @param _poolStakingAddress The pool staking address. + /// @param _delegator The delegator's address. + function _addPoolDelegatorInactive(address _poolStakingAddress, address _delegator) private { + _poolDelegatorsInactive[_poolStakingAddress].add(_delegator); + } + + /// @dev Removes the specified address from the array of the current active delegators of the specified pool. + /// Used by the withdrawal functions. See the `poolDelegators` getter. + /// @param _poolStakingAddress The pool staking address. + /// @param _delegator The delegator's address. + function _removePoolDelegator(address _poolStakingAddress, address _delegator) private { + _poolDelegators[_poolStakingAddress].remove(_delegator); + + if (orderedWithdrawAmount[_poolStakingAddress][_delegator] != 0) { + _addPoolDelegatorInactive(_poolStakingAddress, _delegator); + } else { + _removePoolDelegatorInactive(_poolStakingAddress, _delegator); + } + } + + /// @dev Removes the specified address from the array of the inactive delegators of the specified pool. + /// Used by the `_addPoolDelegator` and `_removePoolDelegator` internal functions. + /// @param _poolStakingAddress The pool staking address. + /// @param _delegator The delegator's address. + function _removePoolDelegatorInactive(address _poolStakingAddress, address _delegator) private { + _poolDelegatorsInactive[_poolStakingAddress].remove(_delegator); + } + + /// @dev Calculates (updates) the probability of being selected as a validator for the specified pool + /// and updates the total sum of probability coefficients. Actually, the probability is equal to the + /// amount totally staked into the pool. See the `getPoolsLikelihood` getter. + /// Used by the staking and withdrawal functions. + /// @param _poolStakingAddress The address of the pool for which the probability coefficient must be updated. + function _setLikelihood(address _poolStakingAddress) private { + (bool isToBeElected, uint256 index) = _isPoolToBeElected(_poolStakingAddress); + + if (!isToBeElected) return; + + uint256 oldValue = _poolsLikelihood[index]; + uint256 newValue = stakeAmountTotal[_poolStakingAddress]; + + _poolsLikelihood[index] = newValue; + + if (newValue >= oldValue) { + _poolsLikelihoodSum = _poolsLikelihoodSum + (newValue - oldValue); + } else { + _poolsLikelihoodSum = _poolsLikelihoodSum - (oldValue - newValue); + } + } + + /// @dev The internal function used by the `_stake` and `moveStake` functions. + /// See the `stake` public function for more details. + /// @param _poolStakingAddress The staking address of the pool where the coins should be staked. + /// @param _staker The staker's address. + /// @param _amount The amount of coins to be staked. + function _stake(address _poolStakingAddress, address _staker, uint256 _amount) private { + require(_poolStakingAddress != address(0), "Stake: stakingAddress is 0"); + + address poolMiningAddress = validatorSetContract.miningByStakingAddress(_poolStakingAddress); + require(poolMiningAddress != address(0), "Pool does not exist. miningAddress for that staking address is 0"); + require(_amount != 0, "Stake: stakingAmount is 0"); + require(!validatorSetContract.isValidatorBanned(poolMiningAddress), "Stake: Mining address is banned"); + + require(!abandonedAndRemoved[_poolStakingAddress], "Stake: pool abandoned"); + //require(areStakeAndWithdrawAllowed(), "Stake: disallowed period"); + + bool selfStake = _staker == _poolStakingAddress; + uint256 newStakeAmount = stakeAmount[_poolStakingAddress][_staker] + _amount; + + if (selfStake) { + // The staked amount must be at least CANDIDATE_MIN_STAKE + require(newStakeAmount >= candidateMinStake, "Stake: candidateStake less than candidateMinStake"); + } else { + // The staked amount must be at least DELEGATOR_MIN_STAKE + require(newStakeAmount >= delegatorMinStake, "Stake: delegatorStake is less than delegatorMinStake"); + + // The delegator cannot stake into the pool of the candidate which hasn't self-staked. + // Also, that candidate shouldn't want to withdraw all their funds. + require(stakeAmount[_poolStakingAddress][_poolStakingAddress] != 0, "Stake: can't delegate in empty pool"); + } + + require(stakeAmountTotal[_poolStakingAddress] + _amount <= maxStakeAmount, "stake limit has been exceeded"); + + _stakeAmountByEpoch[_poolStakingAddress][_staker][stakingEpoch] += _amount; + stakeAmountTotal[_poolStakingAddress] += _amount; + + if (selfStake) { + // `staker` places a stake for himself and becomes a candidate + // Add `_poolStakingAddress` to the array of pools + _addPoolActive(_poolStakingAddress, true); + + } else { + // Add `_staker` to the array of pool's delegators + _addPoolDelegator(_poolStakingAddress, _staker); + + // Save amount value staked by the delegator + _snapshotDelegatorStake(_poolStakingAddress, poolMiningAddress, _staker); + } + + stakeAmount[_poolStakingAddress][_staker] = newStakeAmount; + + _setLikelihood(_poolStakingAddress); + } + + /// @dev The internal function used by the `withdraw` and `moveStake` functions. + /// See the `withdraw` public function for more details. + /// @param _poolStakingAddress The staking address of the pool from which the coins should be withdrawn. + /// @param _staker The staker's address. + /// @param _amount The amount of coins to be withdrawn. + function _withdraw(address _poolStakingAddress, address _staker, uint256 _amount) private { + require(_poolStakingAddress != address(0), "Withdraw pool staking address must not be null"); + require(_amount != 0, "amount to withdraw must not be 0"); + + // How much can `staker` withdraw from `_poolStakingAddress` at the moment? + require(_amount <= maxWithdrawAllowed(_poolStakingAddress, _staker), "Withdraw: maxWithdrawAllowed exceeded"); + + uint256 newStakeAmount = stakeAmount[_poolStakingAddress][_staker] - _amount; + + // The amount to be withdrawn must be the whole staked amount or + // must not exceed the diff between the entire amount and MIN_STAKE + uint256 minAllowedStake = (_poolStakingAddress == _staker) ? candidateMinStake : delegatorMinStake; + require( + newStakeAmount == 0 || newStakeAmount >= minAllowedStake, + "newStake amount must be greater equal than the min stake." + ); + + if (_staker != _poolStakingAddress) { + address miningAddress = validatorSetContract.miningByStakingAddress(_poolStakingAddress); + _snapshotDelegatorStake(_poolStakingAddress, miningAddress, _staker); + } + + stakeAmount[_poolStakingAddress][_staker] = newStakeAmount; + uint256 amountByEpoch = stakeAmountByCurrentEpoch(_poolStakingAddress, _staker); + _stakeAmountByEpoch[_poolStakingAddress][_staker][stakingEpoch] = amountByEpoch >= _amount + ? amountByEpoch - _amount + : 0; + stakeAmountTotal[_poolStakingAddress] -= _amount; + + if (newStakeAmount == 0) { + _withdrawCheckPool(_poolStakingAddress, _staker); + } + + _setLikelihood(_poolStakingAddress); + } + + /// @dev The internal function used by the `_withdraw` and `claimOrderedWithdraw` functions. + /// Contains a common logic for these functions. + /// @param _poolStakingAddress The staking address of the pool from which the coins are withdrawn. + /// @param _staker The staker's address. + function _withdrawCheckPool(address _poolStakingAddress, address _staker) private { + if (_staker == _poolStakingAddress) { + address miningAddress = validatorSetContract.miningByStakingAddress(_poolStakingAddress); + if (validatorSetContract.isValidator(miningAddress)) { + _addPoolToBeRemoved(_poolStakingAddress); + } else { + _removePool(_poolStakingAddress); + } + } else { + _removePoolDelegator(_poolStakingAddress, _staker); + + if (_isPoolEmpty(_poolStakingAddress)) { + _poolsInactive.remove(_poolStakingAddress); + } + } + } + + function _snapshotDelegatorStake( + address _stakingAddress, + address _miningAddress, + address _delegator + ) private { + if (!validatorSetContract.isValidatorOrPending(_miningAddress) || stakingEpoch == 0) { + return; + } + + uint256 lastSnapshotEpochNumber = _stakeSnapshotLastEpoch[_stakingAddress][_delegator]; + + if (lastSnapshotEpochNumber < stakingEpoch) { + _delegatorStakeSnapshot[_stakingAddress][_delegator][stakingEpoch] = + stakeAmount[_stakingAddress][_delegator]; + _stakeSnapshotLastEpoch[_stakingAddress][_delegator] = stakingEpoch; + } + } + + function _getDelegatorStake( + uint256 _stakingEpoch, + address _stakingAddress, + address _delegator + ) private view returns (uint256) { + if (_stakingEpoch == 0) { + return 0; + } + + if (_stakeSnapshotLastEpoch[_stakingAddress][_delegator] == _stakingEpoch) { + return _delegatorStakeSnapshot[_stakingAddress][_delegator][_stakingEpoch]; + } else { + return stakeAmount[_stakingAddress][_delegator]; + } + } + + /// @dev Returns a boolean flag indicating whether the specified pool is fully empty + /// (all stakes are withdrawn including ordered withdrawals). + /// @param _poolStakingAddress The staking address of the pool + function _isPoolEmpty(address _poolStakingAddress) private view returns (bool) { + return stakeAmountTotal[_poolStakingAddress] == 0 && orderedWithdrawAmountTotal[_poolStakingAddress] == 0; + } + + /// @dev Determines if the specified pool is in the `poolsToBeElected` array. See the `getPoolsToBeElected` getter. + /// Used by the `_setLikelihood` internal function. + /// @param _stakingAddress The staking address of the pool. + /// @return toBeElected `bool toBeElected` - The boolean flag indicating whether the `_stakingAddress` is in the + /// `poolsToBeElected` array. + /// `uint256 index` - The position of the item in the `poolsToBeElected` array if `toBeElected` is `true`. + function _isPoolToBeElected(address _stakingAddress) private view returns (bool toBeElected, uint256 index) { + index = poolToBeElectedIndex[_stakingAddress]; + if (_poolsToBeElected.length > index && _poolsToBeElected[index] == _stakingAddress) { + return (true, index); + } + return (false, 0); + } + + /// @dev Returns `true` if withdrawal from the pool of the specified candidate/validator is allowed at the moment. + /// Used by all withdrawal functions. + /// @param _miningAddress The mining address of the validator's pool. + /// @param _isDelegator Whether the withdrawal is requested by a delegator, not by a candidate/validator. + function _isWithdrawAllowed(address _miningAddress, bool _isDelegator) private view returns (bool) { + if (_isDelegator) { + if (validatorSetContract.areDelegatorsBanned(_miningAddress)) { + // The delegator cannot withdraw from the banned validator pool until the ban is expired + return false; + } + } else { + if (validatorSetContract.isValidatorBanned(_miningAddress)) { + // The banned validator cannot withdraw from their pool until the ban is expired + return false; + } + } + + return areStakeAndWithdrawAllowed(); + } + + function _delegatorRewardShare( + bool _minRewardPercentExceeded, + uint256 _totalStake, + uint256 _delegatorStake, + uint256 _allDelegatorsStaked, + uint256 _poolReward, + uint256 _validatorMinRewardPercent + ) private pure returns (uint256) { + if (_delegatorStake == 0 || _allDelegatorsStaked == 0 || _totalStake == 0) { + return 0; + } + + unchecked { + uint256 share = 0; + + if (_minRewardPercentExceeded) { + // Validator has more than validatorMinPercent % + share = (_poolReward * _delegatorStake) / _totalStake; + } else { + // Validator has validatorMinPercent % + share = + (_poolReward * _delegatorStake * (100 - _validatorMinRewardPercent)) / + (_allDelegatorsStaked * 100); + } + + return share; + } + } + + function _validatorRewardShare( + bool _minRewardPercentExceeded, + uint256 _validatorStaked, + uint256 _totalStaked, + uint256 _poolReward, + uint256 _validatorMinRewardPercent + ) private pure returns (uint256) { + if (_validatorStaked == 0 || _totalStaked == 0) { + return 0; + } + + unchecked { + uint256 share = 0; + + if (_minRewardPercentExceeded) { + // Validator has more than validatorMinPercent % + share = (_poolReward * _validatorStaked) / _totalStaked; + } else { + // Validator has validatorMinPercent % + share = (_poolReward * _validatorMinRewardPercent) / 100; + } + + return share; } } } diff --git a/contracts/ValidatorSetHbbft.sol b/contracts/ValidatorSetHbbft.sol index 5e7165db..2d125e8f 100644 --- a/contracts/ValidatorSetHbbft.sol +++ b/contracts/ValidatorSetHbbft.sol @@ -718,11 +718,7 @@ contract ValidatorSetHbbft is Initializable, OwnableUpgradeable, IValidatorSetHb view returns (bool) { - if (isValidator[_miningAddress]) { - return true; - } - - return isPendingValidator(_miningAddress); + return isValidator[_miningAddress] || isPendingValidator(_miningAddress); } /// @dev Returns a boolean flag indicating whether the specified mining address is a pending validator. @@ -733,7 +729,7 @@ contract ValidatorSetHbbft is Initializable, OwnableUpgradeable, IValidatorSetHb view returns (bool) { - for (uint256 i = 0; i < _pendingValidators.length; i++) { + for (uint256 i = 0; i < _pendingValidators.length; ++i) { if (_miningAddress == _pendingValidators[i]) { return true; } @@ -1283,6 +1279,7 @@ contract ValidatorSetHbbft is Initializable, OwnableUpgradeable, IValidatorSetHb uint256 _likelihoodSum, uint256 _randomNumber ) internal pure returns (uint256) { + // slither-disable-next-line weak-prng uint256 random = _randomNumber % _likelihoodSum; uint256 sum = 0; uint256 index = 0; diff --git a/contracts/base/BlockRewardHbbftBase.sol b/contracts/base/BlockRewardHbbftBase.sol deleted file mode 100644 index 234460b0..00000000 --- a/contracts/base/BlockRewardHbbftBase.sol +++ /dev/null @@ -1,709 +0,0 @@ -pragma solidity =0.8.17; - -import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; -import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; - -import "../interfaces/IBlockRewardHbbft.sol"; -import "../interfaces/IRandomHbbft.sol"; -import "../interfaces/IStakingHbbft.sol"; -import "../interfaces/IValidatorSetHbbft.sol"; - -contract Sacrifice { - constructor(address payable _recipient) payable { - selfdestruct(_recipient); - } -} - -/// @dev Generates and distributes rewards according to the logic and formulas described in the POSDAO white paper. -contract BlockRewardHbbftBase is Initializable, OwnableUpgradeable, IBlockRewardHbbft { - // =============================================== Storage ======================================================== - - // WARNING: since this contract is upgradeable, do not remove - // existing storage variables and do not change their types! - - mapping(address => uint256[]) internal _epochsPoolGotRewardFor; - - /// @dev The reward amount to be distributed in native coins among participants (the validator and their - /// delegators) of the specified pool (mining address) for the specified staking epoch. - mapping(uint256 => mapping(address => uint256)) - public epochPoolNativeReward; - - /// @dev The total reward amount in native coins which is not yet distributed among pools. - uint256 public nativeRewardUndistributed; - - /// @dev The total amount staked into the specified pool (mining address) - /// before the specified staking epoch. Filled by the `_snapshotPoolStakeAmounts` function. - mapping(uint256 => mapping(address => uint256)) - public snapshotPoolTotalStakeAmount; - - /// @dev The validator's amount staked into the specified pool (mining address) - /// before the specified staking epoch. Filled by the `_snapshotPoolStakeAmounts` function. - mapping(uint256 => mapping(address => uint256)) - public snapshotPoolValidatorStakeAmount; - - /// @dev The validator's min reward percent which was actual at the specified staking epoch. - /// This percent is taken from the VALIDATOR_MIN_REWARD_PERCENT constant and saved for every staking epoch - /// by the `reward` function. Used by the `delegatorShare` and `validatorShare` public getters. - /// This is needed to have an ability to change validator's min reward percent in the VALIDATOR_MIN_REWARD_PERCENT - /// constant by upgrading the contract. - mapping(uint256 => uint256) public validatorMinRewardPercent; - - /// @dev the Delta Pool holds all coins that never got emitted, since the maximum supply is 4,380,000 - uint256 public deltaPot; - - /// @dev each epoch reward, one Fraction of the delta pool gets payed out. - /// the number is the divisor of the fraction. 60 means 1/60 of the delta pool gets payed out. - uint256 public deltaPotPayoutFraction; - - /// @dev the reinsertPot holds all coins that are designed for getting reinserted into the coin circulation. - /// sources are: - /// - uint256 public reinsertPot; - - /// @dev each epoch reward, one Fraction of the reinsert pool gets payed out. - /// the number is the divisor of the fraction. 60 means 1/60 of the reinsert pool gets payed out. - uint256 public reinsertPotPayoutFraction; - - /// @dev The address of the `ValidatorSet` contract. - IValidatorSetHbbft public validatorSetContract; - - /// @dev parts of the epoch reward get forwarded to a governance fund. - address payable public governancePotAddress; - - /// @dev nominator of the epoch reward that get's forwarded to the - /// `governancePotAddress`. See also `governancePotShareDenominator` - uint256 public governancePotShareNominator; - - /// @dev denominator of the epoch reward that get's forwarded to the - /// `governancePotAddress`. See also `governancePotShareNominator` - uint256 public governancePotShareDenominator; - - /// @dev the address of the `ConnectivityTrackerHbbft` contract. - address public connectivityTracker; - - /// @dev flag indicating whether it is needed to end current epoch earlier. - bool public earlyEpochEnd; - - uint256 public constant VALIDATOR_MIN_REWARD_PERCENT = 30; // 30% - uint256 public constant REWARD_PERCENT_MULTIPLIER = 1000000; - - // ================================================ Events ======================================================== - - /// @dev Emitted by the `reward` function. - /// @param rewards The amount minted and distributed among the validators. - event CoinsRewarded(uint256 rewards); - - // ============================================== Modifiers ======================================================= - - /// @dev Ensures the caller is the SYSTEM_ADDRESS. See https://wiki.parity.io/Block-Reward-Contract.html - modifier onlySystem() virtual { - require(msg.sender == 0xffffFFFfFFffffffffffffffFfFFFfffFFFfFFfE); - _; - } - - /// @dev Ensures the caller is the StakingHbbft contract address. - modifier onlyStakingContract() { - require( - msg.sender == address(validatorSetContract.getStakingContract()) - ); - _; - } - - /// @dev Ensures the caller is the ValidatorSetHbbft contract address. - modifier onlyValidatorSetContract() { - require(msg.sender == address(validatorSetContract)); - _; - } - - /// @dev Ensures the caller is the ConnectivityTracker contract address. - modifier onlyConnectivityTracker() { - require(msg.sender == connectivityTracker); - _; - } - - /// @custom:oz-upgrades-unsafe-allow constructor - constructor() { - // Prevents initialization of implementation contract - _disableInitializers(); - } - - // =============================================== Setters ======================================================== - - /// @dev Fallback function. Prevents direct sending native coins to this contract. - receive() external payable { - reinsertPot += msg.value; - } - - /// @dev Initializes the contract at network startup. - /// Can only be called by the constructor of the `InitializerHbbft` contract or owner. - /// @param _contractOwner The address of the contract owner - /// @param _validatorSet The address of the `ValidatorSetHbbft` contract. - function initialize( - address _contractOwner, - address _validatorSet, - address _connectivityTracker - ) external initializer { - require(_contractOwner != address(0), "Owner address must not be 0"); - require(_validatorSet != address(0), "ValidatorSet must not be 0"); - require(_connectivityTracker != address(0), "ConnectivityTracker must not be 0"); - - __Ownable_init(); - _transferOwnership(_contractOwner); - - validatorSetContract = IValidatorSetHbbft(_validatorSet); - connectivityTracker = _connectivityTracker; - - validatorMinRewardPercent[0] = VALIDATOR_MIN_REWARD_PERCENT; - - deltaPotPayoutFraction = 6000; - reinsertPotPayoutFraction = 6000; - governancePotAddress = payable( - 0xDA0da0da0Da0Da0Da0DA00DA0da0da0DA0DA0dA0 - ); - governancePotShareNominator = 1; - governancePotShareDenominator = 10; - } - - /// @dev adds the transfered value to the delta pot. - /// everyone is allowed to pile up the delta pot. - /// however, circulating coins should be added to the reinsert pot, - /// since the reinsert pot is designed for circulating coins. - function addToDeltaPot() external payable { - deltaPot += msg.value; - } - - /// @dev adds the transfered value to the reinsert pot. - /// everyone is allowed to pile up the resinsert pot, - /// the reinsert pot reinserts coins back into the payout cycle. - /// this is used by smart contracts of the ecosystem, - /// DAO decisions to fund the reinsert pot from the DAO Pool - /// and manual by hand. - /// There is no permission check, - /// everyone is welcomed to pile up the reinsert pot. - function addToReinsertPot() external payable { - reinsertPot += msg.value; - } - - /// @dev set the delta pot payout fraction. - /// every epoch, - /// a fraction of the delta pot is payed out. - /// Only theOwner, the DAO is allowed to set the delta pot payout fraction. - function setdeltaPotPayoutFraction(uint256 _value) external onlyOwner { - require(_value != 0, "Payout fraction must not be 0"); - deltaPotPayoutFraction = _value; - } - - /// @dev set the reinsert pot payout fraction. - /// every epoch, - /// a fraction of the reinsert pot is payed out. - /// (same logic than in the reinsert pot.) - /// Only theOwner, the DAO is allowed to set the reinsert pot payout fraction. - function setReinsertPotPayoutFraction(uint256 _value) external onlyOwner { - require(_value != 0, "Payout fraction must not be 0"); - reinsertPotPayoutFraction = _value; - } - - function setConnectivityTracker(address _connectivityTracker) external onlyOwner { - connectivityTracker = _connectivityTracker; - } - - /// @dev Notify block reward contract, that current epoch must be closed earlier. - /// - /// https://github.com/DMDcoin/diamond-contracts-core/issues/92 - function notifyEarlyEpochEnd() external onlyConnectivityTracker { - earlyEpochEnd = true; - } - - /// @dev Called by the engine when producing and closing a block, - /// see https://wiki.parity.io/Block-Reward-Contract.html. - /// This function performs all of the automatic operations needed for accumulating block producing statistics, - /// starting a new staking epoch, snapshotting staking amounts for the upcoming staking epoch, - /// and rewards distributing at the end of a staking epoch. - /// @param _isEpochEndBlock Indicates if this is the last block of the current epoch i.e. - /// just before the pending validators are finalized. - function reward(bool _isEpochEndBlock) - external - onlySystem - returns (uint256 rewardsNative) - { - IStakingHbbft stakingContract = IStakingHbbft( - validatorSetContract.getStakingContract() - ); - // If this is the last block of the epoch i.e. master key has been generated. - - if (_isEpochEndBlock || earlyEpochEnd) { - uint256 stakingEpoch = stakingContract.stakingEpoch(); - - uint256 nativeTotalRewardAmount = 0; - // Distribute rewards among validator pools - if (stakingEpoch != 0) { - nativeTotalRewardAmount = _distributeRewards(stakingEpoch); - } - - // Snapshot total amounts staked into the pools - uint256 i; - uint256 nextStakingEpoch = stakingEpoch + 1; - address[] memory miningAddresses; - - // We need to remember the total staked amounts for the pending addresses - // for when these pending addresses are finalized by `ValidatorSetHbbft.finalizeChange()`. - miningAddresses = validatorSetContract.getPendingValidators(); - for (i = 0; i < miningAddresses.length; i++) { - _snapshotPoolStakeAmounts( - stakingContract, - nextStakingEpoch, - miningAddresses[i] - ); - } - - // We need to remember the total staked amounts for the current validators - // for the possible case when these validators continue to be validators - // throughout the upcoming staking epoch (if the new validator set is not finalized - // for some reason) - miningAddresses = validatorSetContract.getValidators(); - for (i = 0; i < miningAddresses.length; i++) { - _snapshotPoolStakeAmounts( - stakingContract, - nextStakingEpoch, - miningAddresses[i] - ); - } - // Remember validator's min reward percent for the upcoming staking epoch - validatorMinRewardPercent[ - nextStakingEpoch - ] = VALIDATOR_MIN_REWARD_PERCENT; - - // the rewards got distributed, - // we now can finalize the epoch and start with a new one. - validatorSetContract.finalizeChange(); - - earlyEpochEnd = false; - - emit CoinsRewarded(nativeTotalRewardAmount); - return 0; - } else { - uint256 phaseTransitionTime = stakingContract - .startTimeOfNextPhaseTransition(); - - address[] memory miningAddresses = validatorSetContract - .getValidators(); - - // TODO: Problem occurs here if there are not regular blocks: - // https://github.com/DMDcoin/hbbft-posdao-contracts/issues/96 - - //we are in a transition to phase 2 if the time for it arrived, - // and we do not have pendingValidators yet. - bool isPhaseTransition = block.timestamp >= phaseTransitionTime; - bool toBeUpscaled = false; - if ( - miningAddresses.length * 3 <= - (validatorSetContract.maxValidators() * 2) - ) { - uint256 amountToBeElected = stakingContract - .getPoolsToBeElected() - .length; - if ( - (amountToBeElected > 0) && - validatorSetContract.getValidatorCountSweetSpot( - amountToBeElected - ) > - miningAddresses.length - ) { - toBeUpscaled = true; - } - } - - if ( - (isPhaseTransition || toBeUpscaled) && - validatorSetContract.getPendingValidators().length == 0 - ) { - // Choose new validators - validatorSetContract.newValidatorSet(); - } else if ( - block.timestamp >= stakingContract.stakingFixedEpochEndTime() - ) { - validatorSetContract.handleFailedKeyGeneration(); - } - } - } - - // =============================================== Getters ======================================================== - function getGovernanceAddress() external view returns (address) { - return governancePotAddress; - } - - /// @dev Returns an array of epoch numbers for which the specified pool (mining address) - /// got a non-zero reward. - function epochsPoolGotRewardFor(address _miningAddress) - public - view - returns (uint256[] memory) - { - return _epochsPoolGotRewardFor[_miningAddress]; - } - - /// @dev Returns an array of epoch numbers for which the specified staker - /// can claim a reward from the specified pool by the `StakingHbbft.claimReward` function. - /// @param _poolStakingAddress The pool staking address. - /// @param _staker The staker's address (delegator or candidate/validator). - function epochsToClaimRewardFrom( - address _poolStakingAddress, - address _staker - ) public view returns (uint256[] memory epochsToClaimFrom) { - address miningAddress = validatorSetContract.miningByStakingAddress( - _poolStakingAddress - ); - IStakingHbbft stakingContract = IStakingHbbft( - validatorSetContract.getStakingContract() - ); - bool isDelegator = _poolStakingAddress != _staker; - uint256 firstEpoch = 0; - uint256 lastEpoch = 0; - - if (isDelegator) { - firstEpoch = stakingContract.stakeFirstEpoch( - _poolStakingAddress, - _staker - ); - if (firstEpoch == 0) { - return (new uint256[](0)); - } - lastEpoch = stakingContract.stakeLastEpoch( - _poolStakingAddress, - _staker - ); - } - - uint256[] storage epochs = _epochsPoolGotRewardFor[miningAddress]; - uint256 length = epochs.length; - - uint256[] memory tmp = new uint256[](length); - uint256 tmpLength = 0; - uint256 i; - - for (i = 0; i < length; i++) { - uint256 epoch = epochs[i]; - if (isDelegator) { - if (epoch < firstEpoch) { - // If the delegator staked for the first time before - // the `epoch`, skip this staking epoch - continue; - } - if (lastEpoch <= epoch && lastEpoch != 0) { - // If the delegator withdrew all their stake before the `epoch`, - // don't check this and following epochs since it makes no sense - break; - } - } - if ( - !stakingContract.rewardWasTaken( - _poolStakingAddress, - _staker, - epoch - ) - ) { - tmp[tmpLength++] = epoch; - } - } - - epochsToClaimFrom = new uint256[](tmpLength); - for (i = 0; i < tmpLength; i++) { - epochsToClaimFrom[i] = tmp[i]; - } - } - - /// @dev Returns the reward coefficient for the specified validator. The given value should be divided by 10000 - /// to get the value of the reward percent (since EVM doesn't support floating values). If the specified staking - /// address is an address of a candidate that is not about to be a validator in the upcoming staking epoch - /// the potentially possible reward coefficient is returned. - /// @param _stakingAddress The staking address of the validator/candidate - /// pool for which the getter must return the coefficient. - function validatorRewardPercent(address _stakingAddress) - public - view - returns (uint256) - { - IStakingHbbft stakingContract = IStakingHbbft( - validatorSetContract.getStakingContract() - ); - uint256 stakingEpoch = stakingContract.stakingEpoch(); - - if (stakingEpoch == 0) { - // No one gets a reward for the initial staking epoch, so we return zero. - return 0; - } - - address miningAddress = validatorSetContract.miningByStakingAddress( - _stakingAddress - ); - - if (validatorSetContract.isValidatorOrPending(miningAddress)) { - // For the validator or the candidate that is about to be a validator in the upcoming epoch... - // ...we return the coefficient based on snapshotted total amounts. - return - validatorShare( - stakingEpoch, - snapshotPoolValidatorStakeAmount[stakingEpoch][ - miningAddress - ], - snapshotPoolTotalStakeAmount[stakingEpoch][miningAddress], - REWARD_PERCENT_MULTIPLIER - ); - } - - // For a pool that is neither a validator not a pending one, - // we return the potentially possible reward coefficient - return - validatorShare( - stakingEpoch, - stakingContract.stakeAmount(_stakingAddress, _stakingAddress), - stakingContract.stakeAmountTotal(_stakingAddress), - REWARD_PERCENT_MULTIPLIER - ); - } - - /// @dev Calculates delegator's share for the given pool reward amount and the specified staking epoch. - /// Used by the `StakingHbbft.claimReward` function. - /// @param _stakingEpoch The number of staking epoch. - /// @param _delegatorStaked The amount staked by a delegator. - /// @param _validatorStaked The amount staked by a validator. - /// @param _totalStaked The total amount staked by a validator and their delegators. - /// @param _poolReward The value of pool reward. - function delegatorShare( - uint256 _stakingEpoch, - uint256 _delegatorStaked, - uint256 _validatorStaked, - uint256 _totalStaked, - uint256 _poolReward - ) public view returns (uint256) { - if ( - _delegatorStaked == 0 || _validatorStaked == 0 || _totalStaked == 0 - ) { - return 0; - } - uint256 share = 0; - uint256 delegatorsStaked = _totalStaked >= _validatorStaked - ? _totalStaked - _validatorStaked - : 0; - uint256 validatorMinPercent = validatorMinRewardPercent[_stakingEpoch]; - if ( - _validatorStaked * (100 - validatorMinPercent) > - delegatorsStaked * validatorMinPercent - ) { - // Validator has more than validatorMinPercent % - share = (_poolReward * _delegatorStaked) / _totalStaked; - } else { - // Validator has validatorMinPercent % - share = - (_poolReward * _delegatorStaked * (100 - validatorMinPercent)) / - (delegatorsStaked * 100); - } - return share; - } - - /// @dev Calculates validator's share for the given pool reward amount and the specified staking epoch. - /// Used by the `validatorRewardPercent` and `StakingHbbft.claimReward` functions. - /// @param _stakingEpoch The number of staking epoch. - /// @param _validatorStaked The amount staked by a validator. - /// @param _totalStaked The total amount staked by a validator and their delegators. - /// @param _poolReward The value of pool reward. - function validatorShare( - uint256 _stakingEpoch, - uint256 _validatorStaked, - uint256 _totalStaked, - uint256 _poolReward - ) public view returns (uint256) { - if (_validatorStaked == 0 || _totalStaked == 0) { - return 0; - } - uint256 share = 0; - uint256 delegatorsStaked = _totalStaked >= _validatorStaked - ? _totalStaked - _validatorStaked - : 0; - uint256 validatorMinPercent = validatorMinRewardPercent[_stakingEpoch]; - if ( - _validatorStaked * (100 - validatorMinPercent) > - delegatorsStaked * validatorMinPercent - ) { - // Validator has more than validatorMinPercent % - share = (_poolReward * _validatorStaked) / _totalStaked; - } else { - // Validator has validatorMinPercent % - share = (_poolReward * validatorMinPercent) / 100; - } - return share; - } - - ///@dev Calculates and returns the percentage of the current epoch. - /// 100% MAX - function epochPercentage() public view returns (uint256) { - IStakingHbbft stakingContract = IStakingHbbft( - validatorSetContract.getStakingContract() - ); - uint256 expectedEpochDuration = stakingContract - .stakingFixedEpochEndTime() - - stakingContract.stakingEpochStartTime(); - return - block.timestamp > stakingContract.stakingFixedEpochEndTime() - ? 100 - : ((block.timestamp - stakingContract.stakingEpochStartTime()) * 100) / expectedEpochDuration; - } - - // ============================================== Internal ======================================================== - - /// @dev Distributes rewards among pools at the latest block of a staking epoch. - /// This function is called by the `reward` function. - /// @param _stakingEpoch The number of the current staking epoch. - /// @return Returns the reward amount in native coins needed to be minted - /// and accrued to the balance of this contract. - function _distributeRewards(uint256 _stakingEpoch) - internal - returns (uint256) - { - address[] memory validators = validatorSetContract.getValidators(); - - uint256 numValidators = validators.length; - require(numValidators != 0, "Empty Validator list"); - - uint256 totalReward; - - { - uint256 maxValidators = validatorSetContract.maxValidators(); - uint256 deltaPotShare = (deltaPot * - numValidators * - (epochPercentage())) / - deltaPotPayoutFraction / - maxValidators / - 100; - deltaPot -= deltaPotShare; - - // we could reuse the deltaPotShare variable here, to combat the "stack to deep" problem. - uint256 reinsertPotShare = (reinsertPot * - numValidators * - epochPercentage()) / - reinsertPotPayoutFraction / - maxValidators / - 100; - reinsertPot -= reinsertPotShare; - - totalReward = - deltaPotShare + - reinsertPotShare + - nativeRewardUndistributed; - } - if (totalReward == 0) { - return 0; - } - - // we calculate the governance share here, and store it in the distributeAmount variable. - // the distributedAmount variable is later resused to track all distributed shares - // in order to handle division results in a correct way. - // we can not write clean code here, because of EVMs restriction to use only 16 local variables. - uint256 distributedAmount = (totalReward * - governancePotShareNominator) / governancePotShareDenominator; - - governancePotAddress.transfer(distributedAmount); - - uint256 rewardToDistribute = totalReward - distributedAmount; - - // Indicates whether the validator is entitled to share the rewartds or not. - bool[] memory isRewardedValidator = new bool[](numValidators); - // Number of validators that are being rewarded. - uint256 numRewardedValidators = 0; - - for (uint256 i = 0; i < validators.length; i++) { - if ( - !validatorSetContract.isValidatorBanned(validators[i]) && - snapshotPoolValidatorStakeAmount[_stakingEpoch][ - validators[i] - ] != - 0 - ) { - isRewardedValidator[i] = true; - numRewardedValidators++; - } - } - - // No rewards distributed in this epoch - if (numRewardedValidators == 0) { - return 0; - } - - // Share the reward equally among the validators. - uint256 poolReward = rewardToDistribute / numRewardedValidators; - - if (poolReward != 0) { - for (uint256 i = 0; i < numValidators; i++) { - if (isRewardedValidator[i]) { - //DEBUG: this require has been added for debug reasons. - require( - epochPoolNativeReward[_stakingEpoch][validators[i]] == - 0, - "cant distribute rewards: there is already a pool reward defined for this epoch and validator" - ); - epochPoolNativeReward[_stakingEpoch][ - validators[i] - ] = poolReward; - - distributedAmount += poolReward; - - _epochsPoolGotRewardFor[validators[i]].push(_stakingEpoch); - } - } - } - - nativeRewardUndistributed = totalReward - distributedAmount; - - return distributedAmount; - } - - /// @dev Makes snapshots of total amount staked into the specified pool - /// before the specified staking epoch. Used by the `reward` function. - /// @param _stakingContract The address of the `StakingHbbft` contract. - /// @param _stakingEpoch The number of upcoming staking epoch. - /// @param _miningAddress The mining address of the pool. - function _snapshotPoolStakeAmounts( - IStakingHbbft _stakingContract, - uint256 _stakingEpoch, - address _miningAddress - ) internal { - if (snapshotPoolTotalStakeAmount[_stakingEpoch][_miningAddress] != 0) { - return; - } - address stakingAddress = validatorSetContract.stakingByMiningAddress( - _miningAddress - ); - uint256 totalAmount = _stakingContract.stakeAmountTotal(stakingAddress); - if (totalAmount == 0) { - return; - } - snapshotPoolTotalStakeAmount[_stakingEpoch][ - _miningAddress - ] = totalAmount; - snapshotPoolValidatorStakeAmount[_stakingEpoch][ - _miningAddress - ] = _stakingContract.stakeAmount(stakingAddress, stakingAddress); - } - - /// @dev Called by the `transferReward` of a child contract to transfer native coins - /// from the balance of the `BlockRewardHbbft` contract to the specified address as a reward. - /// @param _amount The amount of native coins to transfer as a reward. - /// @param _to The target address to transfer the amounts to. - function _transferNativeReward(uint256 _amount, address payable _to) - internal - { - if (_amount != 0 && !_to.send(_amount)) { - // We use the `Sacrifice` trick to be sure the coins can be 100% sent to the receiver. - // Otherwise, if the receiver is a contract which has a revert in its fallback function, - // the sending will fail. - (new Sacrifice){value: _amount}(_to); - } - } - - /** - * @dev This empty reserved space is put in place to allow future versions to add new - * variables without shifting down storage in the inheritance chain. - * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps - */ - uint256[49] private __gap; -} diff --git a/contracts/base/StakingHbbftBase.sol b/contracts/base/StakingHbbftBase.sol deleted file mode 100644 index f1907ab7..00000000 --- a/contracts/base/StakingHbbftBase.sol +++ /dev/null @@ -1,1693 +0,0 @@ -pragma solidity =0.8.17; - -import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; -import { OwnableUpgradeable } from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; - -import "../interfaces/IBlockRewardHbbft.sol"; -import "../interfaces/IStakingHbbft.sol"; -import "../interfaces/IValidatorSetHbbft.sol"; - -/// @dev Implements staking and withdrawal logic. -contract StakingHbbftBase is Initializable, OwnableUpgradeable, IStakingHbbft { - // =============================================== Storage ======================================================== - - // WARNING: since this contract is upgradeable, do not remove - // existing storage variables and do not change their types! - - address[] internal _pools; - address[] internal _poolsInactive; - address[] internal _poolsToBeElected; - address[] internal _poolsToBeRemoved; - uint256[] internal _poolsLikelihood; - uint256 internal _poolsLikelihoodSum; - mapping(address => address[]) internal _poolDelegators; - mapping(address => address[]) internal _poolDelegatorsInactive; - mapping(address => mapping(address => mapping(uint256 => uint256))) - internal _stakeAmountByEpoch; - - /// @dev The limit of the minimum candidate stake (CANDIDATE_MIN_STAKE). - uint256 public candidateMinStake; - - /// @dev The limit of the minimum delegator stake (DELEGATOR_MIN_STAKE). - uint256 public delegatorMinStake; - - /// @dev The snapshot of the amount staked into the specified pool by the specified delegator - /// before the specified staking epoch. Used by the `claimReward` function. - /// The first parameter is the pool staking address, the second one is delegator's address, - /// the third one is staking epoch number. - mapping(address => mapping(address => mapping(uint256 => uint256))) - public delegatorStakeSnapshot; - - /// @dev The current amount of staking coins ordered for withdrawal from the specified - /// pool by the specified staker. Used by the `orderWithdraw`, `claimOrderedWithdraw` and other functions. - /// The first parameter is the pool staking address, the second one is the staker address. - mapping(address => mapping(address => uint256)) - public orderedWithdrawAmount; - - /// @dev The current total amount of staking coins ordered for withdrawal from - /// the specified pool by all of its stakers. Pool staking address is accepted as a parameter. - mapping(address => uint256) public orderedWithdrawAmountTotal; - - /// @dev The number of the staking epoch during which the specified staker ordered - /// the latest withdraw from the specified pool. Used by the `claimOrderedWithdraw` function - /// to allow the ordered amount to be claimed only in future staking epochs. The first parameter - /// is the pool staking address, the second one is the staker address. - mapping(address => mapping(address => uint256)) public orderWithdrawEpoch; - - /// @dev The delegator's index in the array returned by the `poolDelegators` getter. - /// Used by the `_removePoolDelegator` internal function. The first parameter is a pool staking address. - /// The second parameter is delegator's address. - /// If the value is zero, it may mean the array doesn't contain the delegator. - /// Check if the delegator is in the array using the `poolDelegators` getter. - mapping(address => mapping(address => uint256)) public poolDelegatorIndex; - - /// @dev The delegator's index in the `poolDelegatorsInactive` array. - /// Used by the `_removePoolDelegatorInactive` internal function. - /// A delegator is considered inactive if they have withdrawn their stake from - /// the specified pool but haven't yet claimed an ordered amount. - /// The first parameter is a pool staking address. The second parameter is delegator's address. - mapping(address => mapping(address => uint256)) - public poolDelegatorInactiveIndex; - - /// @dev The pool's index in the array returned by the `getPoolsInactive` getter. - /// Used by the `_removePoolInactive` internal function. The pool staking address is accepted as a parameter. - mapping(address => uint256) public poolInactiveIndex; - - /// @dev The pool's index in the array returned by the `getPools` getter. - /// Used by the `_removePool` internal function. A pool staking address is accepted as a parameter. - /// If the value is zero, it may mean the array doesn't contain the address. - /// Check the address is in the array using the `isPoolActive` getter. - mapping(address => uint256) public poolIndex; - - /// @dev The pool's index in the array returned by the `getPoolsToBeElected` getter. - /// Used by the `_deletePoolToBeElected` and `_isPoolToBeElected` internal functions. - /// The pool staking address is accepted as a parameter. - /// If the value is zero, it may mean the array doesn't contain the address. - /// Check the address is in the array using the `getPoolsToBeElected` getter. - mapping(address => uint256) public poolToBeElectedIndex; - - /// @dev The pool's index in the array returned by the `getPoolsToBeRemoved` getter. - /// Used by the `_deletePoolToBeRemoved` internal function. - /// The pool staking address is accepted as a parameter. - /// If the value is zero, it may mean the array doesn't contain the address. - /// Check the address is in the array using the `getPoolsToBeRemoved` getter. - mapping(address => uint256) public poolToBeRemovedIndex; - - /// @dev A boolean flag indicating whether the reward was already taken - /// from the specified pool by the specified staker for the specified staking epoch. - /// The first parameter is the pool staking address, the second one is staker's address, - /// the third one is staking epoch number. - mapping(address => mapping(address => mapping(uint256 => bool))) - public rewardWasTaken; - - /// @dev The amount of coins currently staked into the specified pool by the specified - /// staker. Doesn't include the amount ordered for withdrawal. - /// The first parameter is the pool staking address, the second one is the staker address. - mapping(address => mapping(address => uint256)) public stakeAmount; - - /// @dev The number of staking epoch before which the specified delegator placed their first - /// stake into the specified pool. If this is equal to zero, it means the delegator never - /// staked into the specified pool. The first parameter is the pool staking address, - /// the second one is delegator's address. - mapping(address => mapping(address => uint256)) public stakeFirstEpoch; - - /// @dev The number of staking epoch before which the specified delegator withdrew their stake - /// from the specified pool. If this is equal to zero and `stakeFirstEpoch` is not zero, that means - /// the delegator still has some stake in the specified pool. The first parameter is the pool - /// staking address, the second one is delegator's address. - mapping(address => mapping(address => uint256)) public stakeLastEpoch; - - /// @dev The duration period (in blocks) at the end of staking epoch during which - /// participants are not allowed to stake/withdraw/order/claim their staking coins. - uint256 public stakingWithdrawDisallowPeriod; - - /// @dev The serial number of the current staking epoch. - uint256 public stakingEpoch; - - /// @dev The fixed duration of each staking epoch before KeyGen starts i.e. - /// before the upcoming ("pending") validators are selected. - uint256 public stakingFixedEpochDuration; - - /// @dev Length of the timeframe in seconds for the transition to the new validator set. - uint256 public stakingTransitionTimeframeLength; - - /// @dev The timestamp of the last block of the the previous epoch. - /// The timestamp of the current epoch must be '>=' than this. - uint256 public stakingEpochStartTime; - - /// @dev the blocknumber of the first block in this epoch. - /// this is mainly used for a historic lookup in the key gen history to read out the - /// ACKS and PARTS so a client is able to verify an epoch, even in the case that - /// the transition to the next epoch has already started, - /// and the information of the old keys is not available anymore. - uint256 public stakingEpochStartBlock; - - /// @dev the extra time window pending validators have to write - /// to write their honey badger key shares. - /// this value is increased in response to a failed key generation event, - /// if one or more validators miss out writing their key shares. - uint256 public currentKeyGenExtraTimeWindow; - - /// @dev Returns the total amount of staking coins currently staked into the specified pool. - /// Doesn't include the amount ordered for withdrawal. - /// The pool staking address is accepted as a parameter. - mapping(address => uint256) public stakeAmountTotal; - - /// @dev The address of the `ValidatorSetHbbft` contract. - IValidatorSetHbbft public validatorSetContract; - - struct PoolInfo { - bytes publicKey; - bytes16 internetAddress; - bytes2 port; - } - - mapping(address => PoolInfo) public poolInfo; - - /// @dev current limit of how many funds can - /// be staked on a single validator. - uint256 public maxStakeAmount; - - mapping(address => bool) public abandonedAndRemoved; - - // ============================================== Constants ======================================================= - - /// @dev The max number of candidates (including validators). This limit was determined through stress testing. - uint256 public constant MAX_CANDIDATES = 3000; - - // ================================================ Events ======================================================== - - /// @dev Emitted by the `claimOrderedWithdraw` function to signal the staker withdrew the specified - /// amount of requested coins from the specified pool during the specified staking epoch. - /// @param fromPoolStakingAddress The pool from which the `staker` withdrew the `amount`. - /// @param staker The address of the staker that withdrew the `amount`. - /// @param stakingEpoch The serial number of the staking epoch during which the claim was made. - /// @param amount The withdrawal amount. - event ClaimedOrderedWithdrawal( - address indexed fromPoolStakingAddress, - address indexed staker, - uint256 indexed stakingEpoch, - uint256 amount - ); - - /// @dev Emitted by the `moveStake` function to signal the staker moved the specified - /// amount of stake from one pool to another during the specified staking epoch. - /// @param fromPoolStakingAddress The pool from which the `staker` moved the stake. - /// @param toPoolStakingAddress The destination pool where the `staker` moved the stake. - /// @param staker The address of the staker who moved the `amount`. - /// @param stakingEpoch The serial number of the staking epoch during which the `amount` was moved. - /// @param amount The stake amount which was moved. - event MovedStake( - address fromPoolStakingAddress, - address indexed toPoolStakingAddress, - address indexed staker, - uint256 indexed stakingEpoch, - uint256 amount - ); - - /// @dev Emitted by the `orderWithdraw` function to signal the staker ordered the withdrawal of the - /// specified amount of their stake from the specified pool during the specified staking epoch. - /// @param fromPoolStakingAddress The pool from which the `staker` ordered a withdrawal of the `amount`. - /// @param staker The address of the staker that ordered the withdrawal of the `amount`. - /// @param stakingEpoch The serial number of the staking epoch during which the order was made. - /// @param amount The ordered withdrawal amount. Can be either positive or negative. - /// See the `orderWithdraw` function. - event OrderedWithdrawal( - address indexed fromPoolStakingAddress, - address indexed staker, - uint256 indexed stakingEpoch, - int256 amount - ); - - /// @dev Emitted by the `stake` function to signal the staker placed a stake of the specified - /// amount for the specified pool during the specified staking epoch. - /// @param toPoolStakingAddress The pool in which the `staker` placed the stake. - /// @param staker The address of the staker that placed the stake. - /// @param stakingEpoch The serial number of the staking epoch during which the stake was made. - /// @param amount The stake amount. - event PlacedStake( - address indexed toPoolStakingAddress, - address indexed staker, - uint256 indexed stakingEpoch, - uint256 amount - ); - - /// @dev Emitted by the `withdraw` function to signal the staker withdrew the specified - /// amount of a stake from the specified pool during the specified staking epoch. - /// @param fromPoolStakingAddress The pool from which the `staker` withdrew the `amount`. - /// @param staker The address of staker that withdrew the `amount`. - /// @param stakingEpoch The serial number of the staking epoch during which the withdrawal was made. - /// @param amount The withdrawal amount. - event WithdrewStake( - address indexed fromPoolStakingAddress, - address indexed staker, - uint256 indexed stakingEpoch, - uint256 amount - ); - - event GatherAbandonedStakes( - address indexed caller, - address indexed stakingAddress, - uint256 gatheredFunds - ); - - event RecoverAbandonedStakes( - address indexed caller, - uint256 reinsertShare, - uint256 governanceShare - ); - - // ============================================== Modifiers ======================================================= - - /// @dev Ensures the transaction gas price is not zero. - modifier gasPriceIsValid() { - require(tx.gasprice != 0, "GasPrice is 0"); - _; - } - - /// @dev Ensures the caller is the ValidatorSetHbbft contract address. - modifier onlyValidatorSetContract() virtual { - require( - msg.sender == address(validatorSetContract), - "Only ValidatorSet" - ); - _; - } - - // =============================================== Setters ======================================================== - - /// @custom:oz-upgrades-unsafe-allow constructor - constructor() { - // Prevents initialization of implementation contract - _disableInitializers(); - } - - /// @dev Fallback function. Prevents direct sending native coins to this contract. - receive() external payable { - revert("Not payable"); - } - - /// @dev Adds a new candidate's pool to the list of active pools (see the `getPools` getter) and - /// moves the specified amount of staking coins from the candidate's staking address - /// to the candidate's pool. A participant calls this function using their staking address when - /// they want to create a pool. This is a wrapper for the `stake` function. - /// @param _miningAddress The mining address of the candidate. The mining address is bound to the staking address - /// (msg.sender). This address cannot be equal to `msg.sender`. - function addPool( - address _miningAddress, - bytes calldata _publicKey, - bytes16 _ip - ) external payable gasPriceIsValid { - address stakingAddress = msg.sender; - uint256 amount = msg.value; - validatorSetContract.setStakingAddress(_miningAddress, stakingAddress); - // The staking address and the staker are the same. - _stake(stakingAddress, stakingAddress, amount); - poolInfo[stakingAddress].publicKey = _publicKey; - poolInfo[stakingAddress].internetAddress = _ip; - - emit PlacedStake(stakingAddress, stakingAddress, stakingEpoch, amount); - } - - /// @dev set's the pool info for a specific ethereum address. - /// @param _publicKey public key of the (future) signing address. - /// @param _ip (optional) IPV4 address of a running Node Software or Proxy. - /// @param _port (optional) port of IPv4 address of a running Node Software or Proxy. - /// Stores the supplied data for a staking (pool) address. - /// This function is external available without security checks, - /// since no array operations are used in the implementation, - /// this allows the flexibility to set the pool information before - /// adding the stake to the pool. - function setPoolInfo( - bytes calldata _publicKey, - bytes16 _ip, - bytes2 _port - ) external { - poolInfo[msg.sender].publicKey = _publicKey; - poolInfo[msg.sender].internetAddress = _ip; - poolInfo[msg.sender].port = _port; - } - - /// @dev set's the validators ip address. - /// this function can only be called by the validator Set contract. - /// @param _validatorAddress address if the validator. (mining address) - /// @param _ip IPV4 address of a running Node Software or Proxy. - function setValidatorInternetAddress( - address _validatorAddress, - bytes16 _ip, - bytes2 _port - ) external onlyValidatorSetContract { - poolInfo[_validatorAddress].internetAddress = _ip; - poolInfo[_validatorAddress].port = _port; - } - - /// @dev Increments the serial number of the current staking epoch. - /// Called by the `ValidatorSetHbbft.newValidatorSet` at the last block of the finished staking epoch. - function incrementStakingEpoch() external onlyValidatorSetContract { - stakingEpoch++; - currentKeyGenExtraTimeWindow = 0; - } - - /// @dev Initializes the network parameters. - /// Can only be called by the constructor of the `InitializerHbbft` contract or owner. - /// @param _contractOwner The address of the contract owner - /// @param stakingParams stores other parameters due to stack too deep issue - /// _validatorSetContract The address of the `ValidatorSetHbbft` contract. - /// _initialStakingAddresses The array of initial validators' staking addresses. - /// _delegatorMinStake The minimum allowed amount of delegator stake in Wei. - /// _candidateMinStake The minimum allowed amount of candidate/validator stake in Wei. - /// _stakingFixedEpochDuration The fixed duration of each epoch before keyGen starts. - /// _stakingTransitionTimeframeLength Length of the timeframe in seconds for the transition - /// to the new validator set. - /// _stakingWithdrawDisallowPeriod The duration period at the end of a staking epoch - /// during which participants cannot stake/withdraw/order/claim their staking coins - function initialize( - address _contractOwner, - StakingParams calldata stakingParams, - bytes32[] calldata _publicKeys, - bytes16[] calldata _internetAddresses - ) external initializer { - require(_contractOwner != address(0), "Owner address cannot be 0"); - - require( - stakingParams._stakingFixedEpochDuration != 0, - "FixedEpochDuration is 0" - ); - require( - stakingParams._stakingFixedEpochDuration > - stakingParams._stakingWithdrawDisallowPeriod, - "FixedEpochDuration must be longer than withdrawDisallowPeriod" - ); - require( - stakingParams._stakingWithdrawDisallowPeriod != 0, - "WithdrawDisallowPeriod is 0" - ); - require( - stakingParams._stakingTransitionTimeframeLength != 0, - "The transition timeframe must be longer than 0" - ); - require( - stakingParams._stakingTransitionTimeframeLength < - stakingParams._stakingFixedEpochDuration, - "The transition timeframe must be shorter then the epoch duration" - ); - - __Ownable_init(); - _transferOwnership(_contractOwner); - - _initialize( - stakingParams._validatorSetContract, - stakingParams._initialStakingAddresses, - stakingParams._delegatorMinStake, - stakingParams._candidateMinStake, - stakingParams._maxStake, - _publicKeys, - _internetAddresses - ); - stakingFixedEpochDuration = stakingParams._stakingFixedEpochDuration; - stakingWithdrawDisallowPeriod = stakingParams - ._stakingWithdrawDisallowPeriod; - //note: this might be still 0 when created in the genesis block. - stakingEpochStartTime = block.timestamp; - stakingTransitionTimeframeLength = stakingParams - ._stakingTransitionTimeframeLength; - } - - /// @dev Removes a specified pool from the `pools` array (a list of active pools which can be retrieved by the - /// `getPools` getter). Called by the `ValidatorSetHbbft._removeMaliciousValidator` internal function, - /// and the `ValidatorSetHbbft.handleFailedKeyGeneration` function - /// when a pool must be removed by the algorithm. - /// @param _stakingAddress The staking address of the pool to be removed. - function removePool(address _stakingAddress) - external - onlyValidatorSetContract - { - _removePool(_stakingAddress); - } - - /// @dev Removes pools which are in the `_poolsToBeRemoved` internal array from the `pools` array. - /// Called by the `ValidatorSetHbbft.newValidatorSet` function when a pool must be removed by the algorithm. - function removePools() external onlyValidatorSetContract { - address[] memory poolsToRemove = _poolsToBeRemoved; - for (uint256 i = 0; i < poolsToRemove.length; i++) { - _removePool(poolsToRemove[i]); - } - } - - /// @dev Removes the candidate's or validator's pool from the `pools` array (a list of active pools which - /// can be retrieved by the `getPools` getter). When a candidate or validator wants to remove their pool, - /// they should call this function from their staking address. - function removeMyPool() external gasPriceIsValid { - address stakingAddress = msg.sender; - address miningAddress = validatorSetContract.miningByStakingAddress( - stakingAddress - ); - // initial validator cannot remove their pool during the initial staking epoch - require( - stakingEpoch > 0 || - !validatorSetContract.isValidator(miningAddress), - "Can't remove pool during 1st staking epoch" - ); - _removePool(stakingAddress); - } - - function setStakingTransitionTimeframeLength(uint256 _value) - external - onlyOwner { - require(_value > 10, "The transition timeframe must be longer than 10"); - require(_value < stakingFixedEpochDuration, "The transition timeframe must be smaller than the epoch duration"); - - stakingTransitionTimeframeLength = _value; - } - - function setStakingFixedEpochDuration(uint256 _value) - external - onlyOwner { - require(_value > stakingTransitionTimeframeLength, - "The fixed epoch duration timeframe must be greater than the transition timeframe length"); - stakingFixedEpochDuration = _value; - } - - /// @dev Sets the timetamp of the current epoch's last block as the start time of the upcoming staking epoch. - /// Called by the `ValidatorSetHbbft.newValidatorSet` function at the last block of a staking epoch. - /// @param _timestamp The starting time of the very first block in the upcoming staking epoch. - function setStakingEpochStartTime(uint256 _timestamp) - external - onlyValidatorSetContract - { - stakingEpochStartTime = _timestamp; - stakingEpochStartBlock = block.number; - } - - /// @dev Moves staking coins from one pool to another. A staker calls this function when they want - /// to move their coins from one pool to another without withdrawing their coins. - /// @param _fromPoolStakingAddress The staking address of the source pool. - /// @param _toPoolStakingAddress The staking address of the target pool. - /// @param _amount The amount of staking coins to be moved. The amount cannot exceed the value returned - /// by the `maxWithdrawAllowed` getter. - function moveStake( - address _fromPoolStakingAddress, - address _toPoolStakingAddress, - uint256 _amount - ) external gasPriceIsValid { - require( - _fromPoolStakingAddress != _toPoolStakingAddress, - "MoveStake: src and dst pool is the same" - ); - address staker = msg.sender; - _withdraw(_fromPoolStakingAddress, staker, _amount); - _stake(_toPoolStakingAddress, staker, _amount); - emit MovedStake( - _fromPoolStakingAddress, - _toPoolStakingAddress, - staker, - stakingEpoch, - _amount - ); - } - - /// @dev Moves the specified amount of staking coins from the staker's address to the staking address of - /// the specified pool. Actually, the amount is stored in a balance of this StakingHbbft contract. - /// A staker calls this function when they want to make a stake into a pool. - /// @param _toPoolStakingAddress The staking address of the pool where the coins should be staked. - function stake(address _toPoolStakingAddress) - external - payable - gasPriceIsValid - { - address staker = msg.sender; - uint256 amount = msg.value; - _stake(_toPoolStakingAddress, staker, amount); - - emit PlacedStake(_toPoolStakingAddress, staker, stakingEpoch, amount); - } - - /// @dev Moves the specified amount of staking coins from the staking address of - /// the specified pool to the staker's address. A staker calls this function when they want to withdraw - /// their coins. - /// @param _fromPoolStakingAddress The staking address of the pool from which the coins should be withdrawn. - /// @param _amount The amount of coins to be withdrawn. The amount cannot exceed the value returned - /// by the `maxWithdrawAllowed` getter. - function withdraw(address _fromPoolStakingAddress, uint256 _amount) - external - gasPriceIsValid - { - address payable staker = payable(msg.sender); - _withdraw(_fromPoolStakingAddress, staker, _amount); - _sendWithdrawnStakeAmount(staker, _amount); - emit WithdrewStake( - _fromPoolStakingAddress, - staker, - stakingEpoch, - _amount - ); - } - - /// @dev Orders coins withdrawal from the staking address of the specified pool to the - /// staker's address. The requested coins can be claimed after the current staking epoch is complete using - /// the `claimOrderedWithdraw` function. - /// @param _poolStakingAddress The staking address of the pool from which the amount will be withdrawn. - /// @param _amount The amount to be withdrawn. A positive value means the staker wants to either set or - /// increase their withdrawal amount. A negative value means the staker wants to decrease a - /// withdrawal amount that was previously set. The amount cannot exceed the value returned by the - /// `maxWithdrawOrderAllowed` getter. - function orderWithdraw(address _poolStakingAddress, int256 _amount) - external - gasPriceIsValid - { - require( - _poolStakingAddress != address(0), - "poolStakingAddress must not be 0x0" - ); - require(_amount != 0, "ordered withdraw amount must not be 0"); - - address staker = msg.sender; - - require( - _isWithdrawAllowed( - validatorSetContract.miningByStakingAddress( - _poolStakingAddress - ), - staker != _poolStakingAddress - ), - "OrderWithdraw: not allowed" - ); - - uint256 newOrderedAmount = orderedWithdrawAmount[_poolStakingAddress][ - staker - ]; - uint256 newOrderedAmountTotal = orderedWithdrawAmountTotal[ - _poolStakingAddress - ]; - uint256 newStakeAmount = stakeAmount[_poolStakingAddress][staker]; - uint256 newStakeAmountTotal = stakeAmountTotal[_poolStakingAddress]; - if (_amount > 0) { - uint256 amount = uint256(_amount); - - // How much can `staker` order for withdrawal from `_poolStakingAddress` at the moment? - require( - amount <= maxWithdrawOrderAllowed(_poolStakingAddress, staker), - "OrderWithdraw: maxWithdrawOrderAllowed exceeded" - ); - - newOrderedAmount = newOrderedAmount + amount; - newOrderedAmountTotal = newOrderedAmountTotal + amount; - newStakeAmount = newStakeAmount - amount; - newStakeAmountTotal = newStakeAmountTotal - amount; - orderWithdrawEpoch[_poolStakingAddress][staker] = stakingEpoch; - } else { - uint256 amount = uint256(-_amount); - newOrderedAmount = newOrderedAmount - amount; - newOrderedAmountTotal = newOrderedAmountTotal - amount; - newStakeAmount = newStakeAmount + amount; - newStakeAmountTotal = newStakeAmountTotal + amount; - } - orderedWithdrawAmount[_poolStakingAddress][staker] = newOrderedAmount; - orderedWithdrawAmountTotal[_poolStakingAddress] = newOrderedAmountTotal; - stakeAmount[_poolStakingAddress][staker] = newStakeAmount; - stakeAmountTotal[_poolStakingAddress] = newStakeAmountTotal; - - if (staker == _poolStakingAddress) { - // The amount to be withdrawn must be the whole staked amount or - // must not exceed the diff between the entire amount and `candidateMinStake` - require( - newStakeAmount == 0 || newStakeAmount >= candidateMinStake, - "newStake Amount must be greater than the min stake." - ); - - if (_amount > 0) { - // if the validator orders the `_amount` for withdrawal - if (newStakeAmount == 0) { - // If the validator orders their entire stake, - // mark their pool as `to be removed` - _addPoolToBeRemoved(_poolStakingAddress); - } - } else { - // If the validator wants to reduce withdrawal value, - // add their pool as `active` if it hasn't been already done. - _addPoolActive(_poolStakingAddress, true); - } - } else { - // The amount to be withdrawn must be the whole staked amount or - // must not exceed the diff between the entire amount and `delegatorMinStake` - require( - newStakeAmount == 0 || newStakeAmount >= delegatorMinStake, - "newStake Amount must be greater than the min stake." - ); - - if (_amount > 0) { - // if the delegator orders the `_amount` for withdrawal - if (newStakeAmount == 0) { - // If the delegator orders their entire stake, - // remove the delegator from delegator list of the pool - _removePoolDelegator(_poolStakingAddress, staker); - } - } else { - // If the delegator wants to reduce withdrawal value, - // add them to delegator list of the pool if it hasn't already done - _addPoolDelegator(_poolStakingAddress, staker); - } - - // Remember stake movement to use it later in the `claimReward` function - _snapshotDelegatorStake(_poolStakingAddress, staker); - } - - _setLikelihood(_poolStakingAddress); - - emit OrderedWithdrawal( - _poolStakingAddress, - staker, - stakingEpoch, - _amount - ); - } - - /// @dev Withdraws the staking coins from the specified pool ordered during the previous staking epochs with - /// the `orderWithdraw` function. The ordered amount can be retrieved by the `orderedWithdrawAmount` getter. - /// @param _poolStakingAddress The staking address of the pool from which the ordered coins are withdrawn. - function claimOrderedWithdraw(address _poolStakingAddress) - external - gasPriceIsValid - { - address payable staker = payable(msg.sender); - - require( - stakingEpoch > orderWithdrawEpoch[_poolStakingAddress][staker], - "cannot claim ordered withdraw in the same epoch it was ordered." - ); - require( - _isWithdrawAllowed( - validatorSetContract.miningByStakingAddress( - _poolStakingAddress - ), - staker != _poolStakingAddress - ), - "ClaimOrderedWithdraw: Withdraw not allowed" - ); - - uint256 claimAmount = orderedWithdrawAmount[_poolStakingAddress][ - staker - ]; - require(claimAmount != 0, "claim amount must not be 0"); - - orderedWithdrawAmount[_poolStakingAddress][staker] = 0; - orderedWithdrawAmountTotal[_poolStakingAddress] = - orderedWithdrawAmountTotal[_poolStakingAddress] - - claimAmount; - - if (stakeAmount[_poolStakingAddress][staker] == 0) { - _withdrawCheckPool(_poolStakingAddress, staker); - } - - _sendWithdrawnStakeAmount(staker, claimAmount); - - emit ClaimedOrderedWithdrawal( - _poolStakingAddress, - staker, - stakingEpoch, - claimAmount - ); - } - - /// @dev Distribute abandoned stakes among Reinsert and Governance pots. - /// 50% goes to reinsert and 50% to governance pot. - /// Coins are considered abandoned if they were staked on a validator inactive for 10 years. - function recoverAbandonedStakes() external gasPriceIsValid { - uint256 totalAbandonedAmount = 0; - - address[] memory inactivePools = _poolsInactive; - require(inactivePools.length != 0, "nothing to recover"); - - for (uint256 i = 0; i < inactivePools.length; ++i) { - address stakingAddress = inactivePools[i]; - - if (_isPoolEmpty(stakingAddress) || !validatorSetContract.isValidatorAbandoned(stakingAddress)) { - continue; - } - - _removePoolInactive(stakingAddress); - abandonedAndRemoved[stakingAddress] = true; - - uint256 gatheredPerStakingAddress = stakeAmountTotal[stakingAddress]; - stakeAmountTotal[stakingAddress] = 0; - - address[] memory delegators = poolDelegators(stakingAddress); - for (uint256 j = 0; j < delegators.length; ++j) { - address delegator = delegators[j]; - - stakeAmount[stakingAddress][delegator] = 0; - _removePoolDelegator(stakingAddress, delegator); - } - - totalAbandonedAmount += gatheredPerStakingAddress; - - emit GatherAbandonedStakes(msg.sender, stakingAddress, gatheredPerStakingAddress); - } - - require(totalAbandonedAmount != 0, "nothing to recover"); - - uint256 governanceShare = totalAbandonedAmount / 2; - uint256 reinsertShare = totalAbandonedAmount - governanceShare; - - IBlockRewardHbbft blockRewardHbbft = IBlockRewardHbbft(validatorSetContract.blockRewardContract()); - address governanceAddress = blockRewardHbbft.getGovernanceAddress(); - - // slither-disable-next-line arbitrary-send-eth - blockRewardHbbft.addToReinsertPot{value: reinsertShare}(); - _transferNative(governanceAddress, governanceShare); - - emit RecoverAbandonedStakes(msg.sender, reinsertShare, governanceShare); - } - - /// @dev Sets (updates) the limit of the minimum candidate stake (CANDIDATE_MIN_STAKE). - /// Can only be called by the `owner`. - /// @param _minStake The value of a new limit in Wei. - function setCandidateMinStake(uint256 _minStake) - external - onlyOwner - { - candidateMinStake = _minStake; - } - - /// @dev Sets (updates) the limit of the minimum delegator stake (DELEGATOR_MIN_STAKE). - /// Can only be called by the `owner`. - /// @param _minStake The value of a new limit in Wei. - function setDelegatorMinStake(uint256 _minStake) - virtual - external - onlyOwner - { - delegatorMinStake = _minStake; - } - - /// @dev Notifies hbbft staking contract that the - /// key generation has failed, and a new round - /// of keygeneration starts. - function notifyKeyGenFailed() public onlyValidatorSetContract { - // we allow a extra time window for the current key generation - // equal in the size of the usual transition timeframe. - currentKeyGenExtraTimeWindow += stakingTransitionTimeframeLength; - } - - /// @dev Notifies hbbft staking contract about a detected - /// network offline time. - /// if there is no handling for this, - /// validators got chosen outside the transition timewindow - /// and get banned immediatly, since they never got their chance - /// to write their keys. - /// more about: https://github.com/DMDcoin/hbbft-posdao-contracts/issues/96 - function notifyNetworkOfftimeDetected(uint256 detectedOfflineTime) - public - onlyValidatorSetContract - { - currentKeyGenExtraTimeWindow = - currentKeyGenExtraTimeWindow + - detectedOfflineTime + - stakingTransitionTimeframeLength; - } - - /// @dev Notifies hbbft staking contract that a validator - /// asociated with the given `_stakingAddress` became - /// available again and can be put on to the list - /// of available nodes again. - function notifyAvailability(address _stakingAddress) - public - onlyValidatorSetContract - { - if ( - stakeAmount[_stakingAddress][_stakingAddress] >= candidateMinStake - ) { - _addPoolActive(_stakingAddress, true); - _setLikelihood(_stakingAddress); - } - } - - // =============================================== Getters ======================================================== - - /// @dev Returns an array of the current active pools (the staking addresses of candidates and validators). - /// The size of the array cannot exceed MAX_CANDIDATES. A pool can be added to this array with the `_addPoolActive` - /// internal function which is called by the `stake` or `orderWithdraw` function. A pool is considered active - /// if its address has at least the minimum stake and this stake is not ordered to be withdrawn. - function getPools() external view returns (address[] memory) { - return _pools; - } - - /// @dev Return the Public Key used by a Node to send targeted HBBFT Consensus Messages. - /// @param _poolAddress The Pool Address to query the public key for. - /// @return the public key for the given pool address. - /// Note that the public key does not convert to the ethereum address of the pool address. - /// The pool address is used for stacking, and not for signing HBBFT messages. - function getPoolPublicKey(address _poolAddress) - external - view - returns (bytes memory) - { - return poolInfo[_poolAddress].publicKey; - } - - /// @dev Returns the registered IPv4 Address for the node. - /// @param _poolAddress The Pool Address to query the IPv4Address for. - /// @return IPv4 Address for the given pool address. - function getPoolInternetAddress(address _poolAddress) - external - view - returns (bytes16, bytes2) - { - return ( - poolInfo[_poolAddress].internetAddress, - poolInfo[_poolAddress].port - ); - } - - /// @dev Returns an array of the current inactive pools (the staking addresses of former candidates). - /// A pool can be added to this array with the `_addPoolInactive` internal function which is called - /// by `_removePool`. A pool is considered inactive if it is banned for some reason, if its address - /// has zero stake, or if its entire stake is ordered to be withdrawn. - function getPoolsInactive() external view returns (address[] memory) { - return _poolsInactive; - } - - /// @dev Returns the array of stake amounts for each corresponding - /// address in the `poolsToBeElected` array (see the `getPoolsToBeElected` getter) and a sum of these amounts. - /// Used by the `ValidatorSetHbbft.newValidatorSet` function when randomly selecting new validators at the last - /// block of a staking epoch. An array value is updated every time any staked amount is changed in this pool - /// (see the `_setLikelihood` internal function). - /// @return likelihoods `uint256[] likelihoods` - The array of the coefficients. The array length is always equal - /// to the length of the `poolsToBeElected` array. - /// `uint256 sum` - The total sum of the amounts. - function getPoolsLikelihood() - external - view - returns (uint256[] memory likelihoods, uint256 sum) - { - return (_poolsLikelihood, _poolsLikelihoodSum); - } - - /// @dev Returns the list of pools (their staking addresses) which will participate in a new validator set - /// selection process in the `ValidatorSetHbbft.newValidatorSet` function. This is an array of pools - /// which will be considered as candidates when forming a new validator set (at the last block of a staking epoch). - /// This array is kept updated by the `_addPoolToBeElected` and `_deletePoolToBeElected` internal functions. - function getPoolsToBeElected() external view returns (address[] memory) { - return _poolsToBeElected; - } - - /// @dev Returns the list of pools (their staking addresses) which will be removed by the - /// `ValidatorSetHbbft.newValidatorSet` function from the active `pools` array (at the last block - /// of a staking epoch). This array is kept updated by the `_addPoolToBeRemoved` - /// and `_deletePoolToBeRemoved` internal functions. A pool is added to this array when the pool's - /// address withdraws (or orders) all of its own staking coins from the pool, inactivating the pool. - function getPoolsToBeRemoved() external view returns (address[] memory) { - return _poolsToBeRemoved; - } - - /// @dev Determines whether staking/withdrawal operations are allowed at the moment. - /// Used by all staking/withdrawal functions. - function areStakeAndWithdrawAllowed() public view returns (bool) { - //experimental change to always allow to stake withdraw. - //see https://github.com/DMDcoin/hbbft-posdao-contracts/issues/14 for discussion. - return true; - - // used for testing - // if (stakingFixedEpochDuration == 0){ - // return true; - // } - // uint256 currentTimestamp = block.timestamp; - // uint256 allowedDuration = stakingFixedEpochDuration - stakingWithdrawDisallowPeriod; - // return currentTimestamp - stakingEpochStartTime > allowedDuration; //TODO: should be < not <=? - } - - /// @dev Returns a flag indicating whether a specified address is in the `pools` array. - /// See the `getPools` getter. - /// @param _stakingAddress The staking address of the pool. - function isPoolActive(address _stakingAddress) public view returns (bool) { - uint256 index = poolIndex[_stakingAddress]; - return index < _pools.length && _pools[index] == _stakingAddress; - } - - /// @dev Returns the maximum amount which can be withdrawn from the specified pool by the specified staker - /// at the moment. Used by the `withdraw` and `moveStake` functions. - /// @param _poolStakingAddress The pool staking address from which the withdrawal will be made. - /// @param _staker The staker address that is going to withdraw. - function maxWithdrawAllowed(address _poolStakingAddress, address _staker) - public - view - returns (uint256) - { - address miningAddress = validatorSetContract.miningByStakingAddress( - _poolStakingAddress - ); - - if ( - !_isWithdrawAllowed(miningAddress, _poolStakingAddress != _staker) - || abandonedAndRemoved[_poolStakingAddress] - ) { - return 0; - } - - uint256 canWithdraw = stakeAmount[_poolStakingAddress][_staker]; - - if (!validatorSetContract.isValidatorOrPending(miningAddress)) { - // The pool is not a validator and is not going to become one, - // so the staker can only withdraw staked amount minus already - // ordered amount - return canWithdraw; - } - - // The pool is a validator (active or pending), so the staker can only - // withdraw staked amount minus already ordered amount but - // no more than the amount staked during the current staking epoch - uint256 stakedDuringEpoch = stakeAmountByCurrentEpoch( - _poolStakingAddress, - _staker - ); - - if (canWithdraw > stakedDuringEpoch) { - canWithdraw = stakedDuringEpoch; - } - - return canWithdraw; - } - - /// @dev Returns the maximum amount which can be ordered to be withdrawn from the specified pool by the - /// specified staker at the moment. Used by the `orderWithdraw` function. - /// @param _poolStakingAddress The pool staking address from which the withdrawal will be ordered. - /// @param _staker The staker address that is going to order the withdrawal. - function maxWithdrawOrderAllowed( - address _poolStakingAddress, - address _staker - ) public view returns (uint256) { - address miningAddress = validatorSetContract.miningByStakingAddress( - _poolStakingAddress - ); - - if ( - !_isWithdrawAllowed(miningAddress, _poolStakingAddress != _staker) - ) { - return 0; - } - - if (!validatorSetContract.isValidatorOrPending(miningAddress)) { - // If the pool is a candidate (not an active validator and not pending one), - // no one can order withdrawal from the `_poolStakingAddress`, but - // anyone can withdraw immediately (see the `maxWithdrawAllowed` getter) - return 0; - } - - // If the pool is an active or pending validator, the staker can order withdrawal - // up to their total staking amount minus an already ordered amount - // minus an amount staked during the current staking epoch - return - stakeAmount[_poolStakingAddress][_staker] - - stakeAmountByCurrentEpoch(_poolStakingAddress, _staker); - } - - /// @dev Returns an array of the current active delegators of the specified pool. - /// A delegator is considered active if they have staked into the specified - /// pool and their stake is not ordered to be withdrawn. - /// @param _poolStakingAddress The pool staking address. - function poolDelegators(address _poolStakingAddress) - public - view - returns (address[] memory) - { - return _poolDelegators[_poolStakingAddress]; - } - - /// @dev Returns an array of the current inactive delegators of the specified pool. - /// A delegator is considered inactive if their entire stake is ordered to be withdrawn - /// but not yet claimed. - /// @param _poolStakingAddress The pool staking address. - function poolDelegatorsInactive(address _poolStakingAddress) - public - view - returns (address[] memory) - { - return _poolDelegatorsInactive[_poolStakingAddress]; - } - - /// @dev Returns the amount of staking coins staked into the specified pool by the specified staker - /// during the current staking epoch (see the `stakingEpoch` getter). - /// Used by the `stake`, `withdraw`, and `orderWithdraw` functions. - /// @param _poolStakingAddress The pool staking address. - /// @param _staker The staker's address. - function stakeAmountByCurrentEpoch( - address _poolStakingAddress, - address _staker - ) public view returns (uint256) { - return _stakeAmountByEpoch[_poolStakingAddress][_staker][stakingEpoch]; - } - - /// @dev indicates the time when the new validatorset for the next epoch gets chosen. - /// this is the start of a timeframe before the end of the epoch, - /// that is long enough for the validators - /// to create a new shared key. - function startTimeOfNextPhaseTransition() public view returns (uint256) { - return - stakingEpochStartTime + - stakingFixedEpochDuration - - stakingTransitionTimeframeLength; - } - - /// @dev Returns an indicative time of the last block of the current staking epoch before key generation starts. - function stakingFixedEpochEndTime() public view returns (uint256) { - uint256 startTime = stakingEpochStartTime; - return - startTime + - stakingFixedEpochDuration + - currentKeyGenExtraTimeWindow - - (stakingFixedEpochDuration == 0 ? 0 : 1); - } - - // ============================================== Internal ======================================================== - - /// @dev Adds the specified staking address to the array of active pools returned by - /// the `getPools` getter. Used by the `stake`, `addPool`, and `orderWithdraw` functions. - /// @param _stakingAddress The pool added to the array of active pools. - /// @param _toBeElected The boolean flag which defines whether the specified address should be - /// added simultaneously to the `poolsToBeElected` array. See the `getPoolsToBeElected` getter. - function _addPoolActive(address _stakingAddress, bool _toBeElected) - internal - { - if (!isPoolActive(_stakingAddress)) { - poolIndex[_stakingAddress] = _pools.length; - _pools.push(_stakingAddress); - require( - _pools.length <= _getMaxCandidates(), - "MAX_CANDIDATES pools exceeded" - ); - } - _removePoolInactive(_stakingAddress); - if (_toBeElected) { - _addPoolToBeElected(_stakingAddress); - } - } - - /// @dev Adds the specified staking address to the array of inactive pools returned by - /// the `getPoolsInactive` getter. Used by the `_removePool` internal function. - /// @param _stakingAddress The pool added to the array of inactive pools. - function _addPoolInactive(address _stakingAddress) internal { - uint256 index = poolInactiveIndex[_stakingAddress]; - uint256 length = _poolsInactive.length; - if (index >= length || _poolsInactive[index] != _stakingAddress) { - poolInactiveIndex[_stakingAddress] = length; - _poolsInactive.push(_stakingAddress); - } - } - - /// @dev Adds the specified staking address to the array of pools returned by the `getPoolsToBeElected` - /// getter. Used by the `_addPoolActive` internal function. See the `getPoolsToBeElected` getter. - /// @param _stakingAddress The pool added to the `poolsToBeElected` array. - function _addPoolToBeElected(address _stakingAddress) internal { - uint256 index = poolToBeElectedIndex[_stakingAddress]; - uint256 length = _poolsToBeElected.length; - if (index >= length || _poolsToBeElected[index] != _stakingAddress) { - poolToBeElectedIndex[_stakingAddress] = length; - _poolsToBeElected.push(_stakingAddress); - _poolsLikelihood.push(0); // assumes the likelihood is set with `_setLikelihood` function hereinafter - } - _deletePoolToBeRemoved(_stakingAddress); - } - - /// @dev Adds the specified staking address to the array of pools returned by the `getPoolsToBeRemoved` - /// getter. Used by withdrawal functions. See the `getPoolsToBeRemoved` getter. - /// @param _stakingAddress The pool added to the `poolsToBeRemoved` array. - function _addPoolToBeRemoved(address _stakingAddress) internal { - uint256 index = poolToBeRemovedIndex[_stakingAddress]; - uint256 length = _poolsToBeRemoved.length; - if (index >= length || _poolsToBeRemoved[index] != _stakingAddress) { - poolToBeRemovedIndex[_stakingAddress] = length; - _poolsToBeRemoved.push(_stakingAddress); - } - _deletePoolToBeElected(_stakingAddress); - } - - /// @dev Deletes the specified staking address from the array of pools returned by the - /// `getPoolsToBeElected` getter. Used by the `_addPoolToBeRemoved` and `_removePool` internal functions. - /// See the `getPoolsToBeElected` getter. - /// @param _stakingAddress The pool deleted from the `poolsToBeElected` array. - function _deletePoolToBeElected(address _stakingAddress) internal { - if (_poolsToBeElected.length != _poolsLikelihood.length) return; - uint256 indexToDelete = poolToBeElectedIndex[_stakingAddress]; - if ( - _poolsToBeElected.length > indexToDelete && - _poolsToBeElected[indexToDelete] == _stakingAddress - ) { - if (_poolsLikelihoodSum >= _poolsLikelihood[indexToDelete]) { - _poolsLikelihoodSum -= _poolsLikelihood[indexToDelete]; - } else { - _poolsLikelihoodSum = 0; - } - uint256 lastPoolIndex = _poolsToBeElected.length - 1; - address lastPool = _poolsToBeElected[lastPoolIndex]; - _poolsToBeElected[indexToDelete] = lastPool; - _poolsLikelihood[indexToDelete] = _poolsLikelihood[lastPoolIndex]; - poolToBeElectedIndex[lastPool] = indexToDelete; - poolToBeElectedIndex[_stakingAddress] = 0; - _poolsToBeElected.pop(); - _poolsLikelihood.pop(); - } - } - - /// @dev Deletes the specified staking address from the array of pools returned by the - /// `getPoolsToBeRemoved` getter. Used by the `_addPoolToBeElected` and `_removePool` internal functions. - /// See the `getPoolsToBeRemoved` getter. - /// @param _stakingAddress The pool deleted from the `poolsToBeRemoved` array. - function _deletePoolToBeRemoved(address _stakingAddress) internal { - uint256 indexToDelete = poolToBeRemovedIndex[_stakingAddress]; - if ( - _poolsToBeRemoved.length > indexToDelete && - _poolsToBeRemoved[indexToDelete] == _stakingAddress - ) { - address lastPool = _poolsToBeRemoved[_poolsToBeRemoved.length - 1]; - _poolsToBeRemoved[indexToDelete] = lastPool; - poolToBeRemovedIndex[lastPool] = indexToDelete; - poolToBeRemovedIndex[_stakingAddress] = 0; - _poolsToBeRemoved.pop(); - } - } - - /// @dev Removes the specified staking address from the array of active pools returned by - /// the `getPools` getter. Used by the `removePool`, `removeMyPool`, and withdrawal functions. - /// @param _stakingAddress The pool removed from the array of active pools. - function _removePool(address _stakingAddress) internal { - uint256 indexToRemove = poolIndex[_stakingAddress]; - if ( - _pools.length > indexToRemove && - _pools[indexToRemove] == _stakingAddress - ) { - address lastPool = _pools[_pools.length - 1]; - _pools[indexToRemove] = lastPool; - poolIndex[lastPool] = indexToRemove; - poolIndex[_stakingAddress] = 0; - _pools.pop(); - } - if (_isPoolEmpty(_stakingAddress)) { - _removePoolInactive(_stakingAddress); - } else { - _addPoolInactive(_stakingAddress); - } - _deletePoolToBeElected(_stakingAddress); - _deletePoolToBeRemoved(_stakingAddress); - } - - /// @dev Removes the specified staking address from the array of inactive pools returned by - /// the `getPoolsInactive` getter. Used by withdrawal functions, by the `_addPoolActive` and - /// `_removePool` internal functions. - /// @param _stakingAddress The pool removed from the array of inactive pools. - function _removePoolInactive(address _stakingAddress) internal { - uint256 indexToRemove = poolInactiveIndex[_stakingAddress]; - if ( - _poolsInactive.length > indexToRemove && - _poolsInactive[indexToRemove] == _stakingAddress - ) { - address lastPool = _poolsInactive[_poolsInactive.length - 1]; - _poolsInactive[indexToRemove] = lastPool; - poolInactiveIndex[lastPool] = indexToRemove; - poolInactiveIndex[_stakingAddress] = 0; - _poolsInactive.pop(); - } - } - - /// @dev Initializes the network parameters. Used by the `initialize` function. - /// @param _validatorSetContract The address of the `ValidatorSetHbbft` contract. - /// @param _initialStakingAddresses The array of initial validators' staking addresses. - /// @param _delegatorMinStake The minimum allowed amount of delegator stake in Wei. - /// @param _candidateMinStake The minimum allowed amount of candidate/validator stake in Wei. - function _initialize( - address _validatorSetContract, - address[] memory _initialStakingAddresses, - uint256 _delegatorMinStake, - uint256 _candidateMinStake, - uint256 _maxStake, - bytes32[] memory _publicKeys, - bytes16[] memory _internetAddresses - ) internal { - require(_validatorSetContract != address(0), "ValidatorSet can't be 0"); - require( - _initialStakingAddresses.length > 0, - "Must provide initial mining addresses" - ); - require( - _initialStakingAddresses.length * 2 == _publicKeys.length, - "Must provide correct number of publicKeys" - ); - require( - _initialStakingAddresses.length == _internetAddresses.length, - "Must provide correct number of IP adresses" - ); - require(_delegatorMinStake != 0, "DelegatorMinStake is 0"); - require(_candidateMinStake != 0, "CandidateMinStake is 0"); - require( - _maxStake > _candidateMinStake, - "maximum stake must be greater then minimum stake." - ); - - validatorSetContract = IValidatorSetHbbft(_validatorSetContract); - - for (uint256 i = 0; i < _initialStakingAddresses.length; i++) { - require( - _initialStakingAddresses[i] != address(0), - "InitialStakingAddresses can't be 0" - ); - _addPoolActive(_initialStakingAddresses[i], false); - _addPoolToBeRemoved(_initialStakingAddresses[i]); - poolInfo[_initialStakingAddresses[i]].publicKey = abi.encodePacked( - _publicKeys[i * 2], - _publicKeys[i * 2 + 1] - ); - poolInfo[_initialStakingAddresses[i]] - .internetAddress = _internetAddresses[i]; - } - - delegatorMinStake = _delegatorMinStake; - candidateMinStake = _candidateMinStake; - - maxStakeAmount = _maxStake; - } - - /// @dev Adds the specified address to the array of the current active delegators of the specified pool. - /// Used by the `stake` and `orderWithdraw` functions. See the `poolDelegators` getter. - /// @param _poolStakingAddress The pool staking address. - /// @param _delegator The delegator's address. - function _addPoolDelegator(address _poolStakingAddress, address _delegator) - internal - { - address[] storage delegators = _poolDelegators[_poolStakingAddress]; - uint256 index = poolDelegatorIndex[_poolStakingAddress][_delegator]; - uint256 length = delegators.length; - if (index >= length || delegators[index] != _delegator) { - poolDelegatorIndex[_poolStakingAddress][_delegator] = length; - delegators.push(_delegator); - } - _removePoolDelegatorInactive(_poolStakingAddress, _delegator); - } - - /// @dev Adds the specified address to the array of the current inactive delegators of the specified pool. - /// Used by the `_removePoolDelegator` internal function. - /// @param _poolStakingAddress The pool staking address. - /// @param _delegator The delegator's address. - function _addPoolDelegatorInactive( - address _poolStakingAddress, - address _delegator - ) internal { - address[] storage delegators = _poolDelegatorsInactive[ - _poolStakingAddress - ]; - uint256 index = poolDelegatorInactiveIndex[_poolStakingAddress][ - _delegator - ]; - uint256 length = delegators.length; - if (index >= length || delegators[index] != _delegator) { - poolDelegatorInactiveIndex[_poolStakingAddress][ - _delegator - ] = length; - delegators.push(_delegator); - } - } - - /// @dev Removes the specified address from the array of the current active delegators of the specified pool. - /// Used by the withdrawal functions. See the `poolDelegators` getter. - /// @param _poolStakingAddress The pool staking address. - /// @param _delegator The delegator's address. - function _removePoolDelegator( - address _poolStakingAddress, - address _delegator - ) internal { - address[] storage delegators = _poolDelegators[_poolStakingAddress]; - uint256 indexToRemove = poolDelegatorIndex[_poolStakingAddress][ - _delegator - ]; - if ( - delegators.length > indexToRemove && - delegators[indexToRemove] == _delegator - ) { - address lastDelegator = delegators[delegators.length - 1]; - delegators[indexToRemove] = lastDelegator; - poolDelegatorIndex[_poolStakingAddress][ - lastDelegator - ] = indexToRemove; - poolDelegatorIndex[_poolStakingAddress][_delegator] = 0; - delegators.pop(); - } - if (orderedWithdrawAmount[_poolStakingAddress][_delegator] != 0) { - _addPoolDelegatorInactive(_poolStakingAddress, _delegator); - } else { - _removePoolDelegatorInactive(_poolStakingAddress, _delegator); - } - } - - /// @dev Removes the specified address from the array of the inactive delegators of the specified pool. - /// Used by the `_addPoolDelegator` and `_removePoolDelegator` internal functions. - /// @param _poolStakingAddress The pool staking address. - /// @param _delegator The delegator's address. - function _removePoolDelegatorInactive( - address _poolStakingAddress, - address _delegator - ) internal { - address[] storage delegators = _poolDelegatorsInactive[ - _poolStakingAddress - ]; - uint256 indexToRemove = poolDelegatorInactiveIndex[_poolStakingAddress][ - _delegator - ]; - if ( - delegators.length > indexToRemove && - delegators[indexToRemove] == _delegator - ) { - address lastDelegator = delegators[delegators.length - 1]; - delegators[indexToRemove] = lastDelegator; - poolDelegatorInactiveIndex[_poolStakingAddress][ - lastDelegator - ] = indexToRemove; - poolDelegatorInactiveIndex[_poolStakingAddress][_delegator] = 0; - delegators.pop(); - } - } - - function _sendWithdrawnStakeAmount(address payable _to, uint256 _amount) - internal - virtual - {} - - /// @dev Calculates (updates) the probability of being selected as a validator for the specified pool - /// and updates the total sum of probability coefficients. Actually, the probability is equal to the - /// amount totally staked into the pool. See the `getPoolsLikelihood` getter. - /// Used by the staking and withdrawal functions. - /// @param _poolStakingAddress The address of the pool for which the probability coefficient must be updated. - function _setLikelihood(address _poolStakingAddress) internal { - (bool isToBeElected, uint256 index) = _isPoolToBeElected( - _poolStakingAddress - ); - - if (!isToBeElected) return; - - uint256 oldValue = _poolsLikelihood[index]; - uint256 newValue = stakeAmountTotal[_poolStakingAddress]; - - _poolsLikelihood[index] = newValue; - - if (newValue >= oldValue) { - _poolsLikelihoodSum = _poolsLikelihoodSum + (newValue - oldValue); - } else { - _poolsLikelihoodSum = _poolsLikelihoodSum - (oldValue - newValue); - } - } - - /// @dev Makes a snapshot of the amount currently staked by the specified delegator - /// into the specified pool (staking address). Used by the `orderWithdraw`, `_stake`, and `_withdraw` functions. - /// @param _poolStakingAddress The staking address of the pool. - /// @param _delegator The address of the delegator. - function _snapshotDelegatorStake( - address _poolStakingAddress, - address _delegator - ) internal { - uint256 nextStakingEpoch = stakingEpoch + 1; - uint256 newAmount = stakeAmount[_poolStakingAddress][_delegator]; - - delegatorStakeSnapshot[_poolStakingAddress][_delegator][ - nextStakingEpoch - ] = (newAmount != 0) ? newAmount : type(uint256).max; - - if (stakeFirstEpoch[_poolStakingAddress][_delegator] == 0) { - stakeFirstEpoch[_poolStakingAddress][_delegator] = nextStakingEpoch; - } - stakeLastEpoch[_poolStakingAddress][_delegator] = (newAmount == 0) - ? nextStakingEpoch - : 0; - } - - /// @dev The internal function used by the `_stake` and `moveStake` functions. - /// See the `stake` public function for more details. - /// @param _poolStakingAddress The staking address of the pool where the coins should be staked. - /// @param _staker The staker's address. - /// @param _amount The amount of coins to be staked. - function _stake( - address _poolStakingAddress, - address _staker, - uint256 _amount - ) internal { - address poolMiningAddress = validatorSetContract.miningByStakingAddress( - _poolStakingAddress - ); - - require( - poolMiningAddress != address(0), - "Pool does not exist. miningAddress for that staking address is 0" - ); - require( - _poolStakingAddress != address(0), - "Stake: stakingAddress is 0" - ); - require(_amount != 0, "Stake: stakingAmount is 0"); - require( - !validatorSetContract.isValidatorBanned(poolMiningAddress), - "Stake: Mining address is banned" - ); - - require(!abandonedAndRemoved[_poolStakingAddress], "Stake: pool abandoned"); - //require(areStakeAndWithdrawAllowed(), "Stake: disallowed period"); - - uint256 newStakeAmount = stakeAmount[_poolStakingAddress][_staker] + - _amount; - - if (_staker == _poolStakingAddress) { - // The staked amount must be at least CANDIDATE_MIN_STAKE - require( - newStakeAmount >= candidateMinStake, - "Stake: candidateStake less than candidateMinStake" - ); - } else { - // The staked amount must be at least DELEGATOR_MIN_STAKE - require( - newStakeAmount >= delegatorMinStake, - "Stake: delegatorStake is less than delegatorMinStake" - ); - - // The delegator cannot stake into the pool of the candidate which hasn't self-staked. - // Also, that candidate shouldn't want to withdraw all their funds. - require( - stakeAmount[_poolStakingAddress][_poolStakingAddress] != 0, - "Stake: can't delegate in empty pool" - ); - } - - require( - stakeAmountTotal[_poolStakingAddress] + _amount <= maxStakeAmount, - "stake limit has been exceeded" - ); - stakeAmount[_poolStakingAddress][_staker] = newStakeAmount; - _stakeAmountByEpoch[_poolStakingAddress][_staker][stakingEpoch] = - stakeAmountByCurrentEpoch(_poolStakingAddress, _staker) + - _amount; - stakeAmountTotal[_poolStakingAddress] = - stakeAmountTotal[_poolStakingAddress] + - _amount; - - if (_staker == _poolStakingAddress) { - // `staker` places a stake for himself and becomes a candidate - // Add `_poolStakingAddress` to the array of pools - _addPoolActive(_poolStakingAddress, true); - } else { - // Add `_staker` to the array of pool's delegators - _addPoolDelegator(_poolStakingAddress, _staker); - - // Save amount value staked by the delegator - _snapshotDelegatorStake(_poolStakingAddress, _staker); - } - - _setLikelihood(_poolStakingAddress); - } - - /// @dev The internal function used by the `withdraw` and `moveStake` functions. - /// See the `withdraw` public function for more details. - /// @param _poolStakingAddress The staking address of the pool from which the coins should be withdrawn. - /// @param _staker The staker's address. - /// @param _amount The amount of coins to be withdrawn. - function _withdraw( - address _poolStakingAddress, - address _staker, - uint256 _amount - ) internal { - require( - _poolStakingAddress != address(0), - "Withdraw pool staking address must not be null" - ); - require(_amount != 0, "amount to withdraw must not be 0"); - - // How much can `staker` withdraw from `_poolStakingAddress` at the moment? - require( - _amount <= maxWithdrawAllowed(_poolStakingAddress, _staker), - "Withdraw: maxWithdrawAllowed exceeded" - ); - - uint256 newStakeAmount = stakeAmount[_poolStakingAddress][_staker] - - _amount; - - // The amount to be withdrawn must be the whole staked amount or - // must not exceed the diff between the entire amount and MIN_STAKE - uint256 minAllowedStake = (_poolStakingAddress == _staker) - ? candidateMinStake - : delegatorMinStake; - require( - newStakeAmount == 0 || newStakeAmount >= minAllowedStake, - "newStake amount must be greater equal than the min stake." - ); - - stakeAmount[_poolStakingAddress][_staker] = newStakeAmount; - uint256 amountByEpoch = stakeAmountByCurrentEpoch( - _poolStakingAddress, - _staker - ); - _stakeAmountByEpoch[_poolStakingAddress][_staker][ - stakingEpoch - ] = amountByEpoch >= _amount ? amountByEpoch - _amount : 0; - stakeAmountTotal[_poolStakingAddress] = - stakeAmountTotal[_poolStakingAddress] - - _amount; - - if (newStakeAmount == 0) { - _withdrawCheckPool(_poolStakingAddress, _staker); - } - - if (_staker != _poolStakingAddress) { - _snapshotDelegatorStake(_poolStakingAddress, _staker); - } - - _setLikelihood(_poolStakingAddress); - } - - /// @dev The internal function used by the `_withdraw` and `claimOrderedWithdraw` functions. - /// Contains a common logic for these functions. - /// @param _poolStakingAddress The staking address of the pool from which the coins are withdrawn. - /// @param _staker The staker's address. - function _withdrawCheckPool(address _poolStakingAddress, address _staker) - internal - { - if (_staker == _poolStakingAddress) { - address miningAddress = validatorSetContract.miningByStakingAddress( - _poolStakingAddress - ); - if (validatorSetContract.isValidator(miningAddress)) { - _addPoolToBeRemoved(_poolStakingAddress); - } else { - _removePool(_poolStakingAddress); - } - } else { - _removePoolDelegator(_poolStakingAddress, _staker); - - if (_isPoolEmpty(_poolStakingAddress)) { - _removePoolInactive(_poolStakingAddress); - } - } - } - - /// @dev The internal function used by the `claimReward` function and `getRewardAmount` getter. - /// Finds the stake amount made by a specified delegator into a specified pool before a specified - /// staking epoch. - function _getDelegatorStake( - uint256 _epoch, - uint256 _firstEpoch, - uint256 _prevDelegatorStake, - address _poolStakingAddress, - address _delegator - ) internal view returns (uint256 delegatorStake) { - while (true) { - delegatorStake = delegatorStakeSnapshot[_poolStakingAddress][ - _delegator - ][_epoch]; - if (delegatorStake != 0) { - delegatorStake = (delegatorStake == type(uint256).max) - ? 0 - : delegatorStake; - break; - } else if (_epoch == _firstEpoch) { - delegatorStake = _prevDelegatorStake; - break; - } - _epoch--; - } - } - - /// @dev Returns the max number of candidates (including validators). See the MAX_CANDIDATES constant. - /// Needed mostly for unit tests. - function _getMaxCandidates() internal pure virtual returns (uint256) { - return MAX_CANDIDATES; - } - - /// @dev Returns a boolean flag indicating whether the specified pool is fully empty - /// (all stakes are withdrawn including ordered withdrawals). - /// @param _poolStakingAddress The staking address of the pool - function _isPoolEmpty(address _poolStakingAddress) - internal - view - returns (bool) - { - return - stakeAmountTotal[_poolStakingAddress] == 0 && - orderedWithdrawAmountTotal[_poolStakingAddress] == 0; - } - - /// @dev Determines if the specified pool is in the `poolsToBeElected` array. See the `getPoolsToBeElected` getter. - /// Used by the `_setLikelihood` internal function. - /// @param _stakingAddress The staking address of the pool. - /// @return toBeElected `bool toBeElected` - The boolean flag indicating whether the `_stakingAddress` is in the - /// `poolsToBeElected` array. - /// `uint256 index` - The position of the item in the `poolsToBeElected` array if `toBeElected` is `true`. - function _isPoolToBeElected(address _stakingAddress) - internal - view - returns (bool toBeElected, uint256 index) - { - index = poolToBeElectedIndex[_stakingAddress]; - if ( - _poolsToBeElected.length > index && - _poolsToBeElected[index] == _stakingAddress - ) { - return (true, index); - } - return (false, 0); - } - - /// @dev Returns `true` if withdrawal from the pool of the specified candidate/validator is allowed at the moment. - /// Used by all withdrawal functions. - /// @param _miningAddress The mining address of the validator's pool. - /// @param _isDelegator Whether the withdrawal is requested by a delegator, not by a candidate/validator. - function _isWithdrawAllowed(address _miningAddress, bool _isDelegator) - internal - view - returns (bool) - { - if (_isDelegator) { - if (validatorSetContract.areDelegatorsBanned(_miningAddress)) { - // The delegator cannot withdraw from the banned validator pool until the ban is expired - return false; - } - } else { - if (validatorSetContract.isValidatorBanned(_miningAddress)) { - // The banned validator cannot withdraw from their pool until the ban is expired - return false; - } - } - - if (!areStakeAndWithdrawAllowed()) { - return false; - } - - return true; - } - - function _transferNative(address recipient, uint256 amount) internal { - require(address(this).balance >= amount, "Insufficient balance"); - - // slither-disable-next-line unchecked-lowlevel - (bool success, ) = recipient.call{ value: amount }(""); - require(success, "Transfer failed"); - } - - /** - * @dev This empty reserved space is put in place to allow future versions to add new - * variables without shifting down storage in the inheritance chain. - * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps - */ - uint256[50] private __gap; -} diff --git a/contracts/interfaces/IBlockRewardHbbft.sol b/contracts/interfaces/IBlockRewardHbbft.sol index b229646c..11a538ee 100644 --- a/contracts/interfaces/IBlockRewardHbbft.sol +++ b/contracts/interfaces/IBlockRewardHbbft.sol @@ -5,10 +5,23 @@ interface IBlockRewardHbbft { function notifyEarlyEpochEnd() external; - function epochsPoolGotRewardFor(address) - external - view - returns (uint256[] memory); + // function transferReward(uint256, address payable) external; + + // function epochsPoolGotRewardFor( + // address + // ) external view returns (uint256[] memory); function getGovernanceAddress() external view returns (address); + + // function getDelegatorReward( + // uint256, + // uint256, + // address + // ) external view returns (uint256); + + + // function getValidatorReward( + // uint256, + // address + // ) external view returns (uint256); } diff --git a/contracts/interfaces/IBlockRewardHbbftCoins.sol b/contracts/interfaces/IBlockRewardHbbftCoins.sol deleted file mode 100644 index 163064cc..00000000 --- a/contracts/interfaces/IBlockRewardHbbftCoins.sol +++ /dev/null @@ -1,16 +0,0 @@ -pragma solidity =0.8.17; - -interface IBlockRewardHbbftCoins { - function transferReward(uint256, address payable) external; - - function getDelegatorReward( - uint256, - uint256, - address - ) external view returns (uint256); - - function getValidatorReward(uint256, address) - external - view - returns (uint256); -} diff --git a/contracts/interfaces/IStakingHbbft.sol b/contracts/interfaces/IStakingHbbft.sol index efe33586..0fafc769 100644 --- a/contracts/interfaces/IStakingHbbft.sol +++ b/contracts/interfaces/IStakingHbbft.sol @@ -51,12 +51,6 @@ interface IStakingHbbft { function poolDelegators(address) external view returns (address[] memory); - function rewardWasTaken( - address, - address, - uint256 - ) external view returns (bool); - function setValidatorInternetAddress( address, bytes16, @@ -67,10 +61,6 @@ interface IStakingHbbft { function stakeAmountTotal(address) external view returns (uint256); - function stakeFirstEpoch(address, address) external view returns (uint256); - - function stakeLastEpoch(address, address) external view returns (uint256); - function stakingWithdrawDisallowPeriod() external view returns (uint256); function stakingEpoch() external view returns (uint256); @@ -84,4 +74,19 @@ interface IStakingHbbft { function stakingEpochStartTime() external view returns (uint256); function stakingEpochStartBlock() external view returns (uint256); + + function restake( + address _poolStakingAddress, + uint256 validatorReward + ) external payable; + + function snapshotPoolStakeAmounts( + uint256 _epoch, + address _stakingPool + ) external; + + function getPoolValidatorStakeAmount( + uint256 _epoch, + address _stakingPool + ) external view returns (uint256); } diff --git a/contracts/interfaces/IStakingHbbftCoins.sol b/contracts/interfaces/IStakingHbbftCoins.sol deleted file mode 100644 index 06388c4f..00000000 --- a/contracts/interfaces/IStakingHbbftCoins.sol +++ /dev/null @@ -1,3 +0,0 @@ -pragma solidity =0.8.17; - -interface IStakingHbbftCoins {} diff --git a/contracts/mockContracts/BlockRewardHbbftMock.sol b/contracts/mockContracts/BlockRewardHbbftMock.sol index 45e621f8..fff6787e 100644 --- a/contracts/mockContracts/BlockRewardHbbftMock.sol +++ b/contracts/mockContracts/BlockRewardHbbftMock.sol @@ -3,23 +3,10 @@ pragma solidity =0.8.17; import "../BlockRewardHbbft.sol"; contract BlockRewardHbbftMock is BlockRewardHbbft { - address internal _systemAddress; - - // ============================================== Modifiers ======================================================= - - modifier onlySystem() virtual override { - require(msg.sender == _getSystemAddress()); - _; - } - // =============================================== Setters ======================================================== function sendCoins() public payable {} - function setSystemAddress(address _address) public { - _systemAddress = _address; - } - function setGovernanceAddress(address _address) public { governancePotAddress = payable(_address); } @@ -31,60 +18,7 @@ contract BlockRewardHbbftMock is BlockRewardHbbft { validatorMinRewardPercent[_stakingEpoch] = _percent; } - function snapshotPoolStakeAmounts( - IStakingHbbft _stakingContract, - uint256 _stakingEpoch, - address _miningAddress - ) public { - _snapshotPoolStakeAmounts( - _stakingContract, - _stakingEpoch, - _miningAddress - ); - } - - function setSnapshotPoolValidatorStakeAmount( - uint256 _stakingEpoch, - address _poolMiningAddress, - uint256 _amount - ) public { - snapshotPoolValidatorStakeAmount[_stakingEpoch][ - _poolMiningAddress - ] = _amount; - } - - function setEpochPoolReward( - uint256 _stakingEpoch, - address _poolMiningAddress - ) public payable { - require(_stakingEpoch != 0, "SetEpochPoolReward: epoch can't be 0"); - require( - _poolMiningAddress != address(0), - "SetEpochPoolReward: epoch can't be 0" - ); - require(msg.value != 0, "SetEpochPoolReward: reward can't be 0"); - require( - epochPoolNativeReward[_stakingEpoch][_poolMiningAddress] == 0, - "SetEpochPoolReward: epochPoolNativeReward already set" - ); - epochPoolNativeReward[_stakingEpoch][_poolMiningAddress] = msg.value; - - uint256[] memory thisPoolsRewards = _epochsPoolGotRewardFor[ - _poolMiningAddress - ]; - for (uint256 i = 0; i < thisPoolsRewards.length; i++) { - require( - thisPoolsRewards[i] != _stakingEpoch, - "There is already a Reward pending for this mining address!" - ); - } - - _epochsPoolGotRewardFor[_poolMiningAddress].push(_stakingEpoch); - } - - // =============================================== Private ======================================================== - - function _getSystemAddress() internal view returns (address) { - return _systemAddress; + function getPotsShares(uint256 numValidators) external view returns(PotsShares memory) { + return _getPotsShares(numValidators); } } diff --git a/contracts/mockContracts/EtherReceiverMock.sol b/contracts/mockContracts/EtherReceiverMock.sol new file mode 100644 index 00000000..90de24d8 --- /dev/null +++ b/contracts/mockContracts/EtherReceiverMock.sol @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity =0.8.17; + +contract EtherReceiverMock { + bool public allowReceive; + + constructor() { + allowReceive = true; + } + + receive() external payable { + if (!allowReceive) { + revert(); + } + } + + function toggleReceive(bool allow) external { + allowReceive = allow; + } +} diff --git a/contracts/mockContracts/StakingHbbftMock.sol b/contracts/mockContracts/StakingHbbftMock.sol index 7701ab5d..dbe8f717 100644 --- a/contracts/mockContracts/StakingHbbftMock.sol +++ b/contracts/mockContracts/StakingHbbftMock.sol @@ -3,14 +3,11 @@ pragma solidity =0.8.17; import "../StakingHbbft.sol"; contract StakingHbbftMock is StakingHbbft { - IValidatorSetHbbft validatorSetContractMock; + IValidatorSetHbbft private validatorSetContractMock; - modifier onlyValidatorSetContract() - virtual - override { + modifier onlyValidatorSetContract() virtual override { require( - msg.sender == address(validatorSetContract) || - msg.sender == address(validatorSetContractMock), + msg.sender == address(validatorSetContract) || msg.sender == address(validatorSetContractMock), "Only ValidatorSet" ); _; @@ -25,86 +22,42 @@ contract StakingHbbftMock is StakingHbbft { _addPoolInactive(_stakingAddress); } - function clearDelegatorStakeSnapshot( - address _poolStakingAddress, - address _delegator, - uint256 _stakingEpoch - ) public { - delegatorStakeSnapshot[_poolStakingAddress][_delegator][ - _stakingEpoch - ] = 0; + function clearDelegatorStakeSnapshot(address pool, address delegator, uint256 epoch) external { + _delegatorStakeSnapshot[pool][delegator][epoch] = 0; } - function clearRewardWasTaken( - address _poolStakingAddress, - address _staker, - uint256 _epoch - ) public { - rewardWasTaken[_poolStakingAddress][_staker][_epoch] = false; - } - - function setStakeAmountTotal(address _poolStakingAddress, uint256 _amount) - public - { + function setStakeAmountTotal(address _poolStakingAddress, uint256 _amount) public { stakeAmountTotal[_poolStakingAddress] = _amount; } - function setStakeFirstEpoch( - address _poolStakingAddress, - address _delegator, - uint256 _value - ) public { - stakeFirstEpoch[_poolStakingAddress][_delegator] = _value; - } - - function setStakeLastEpoch( - address _poolStakingAddress, - address _delegator, - uint256 _value - ) public { - stakeLastEpoch[_poolStakingAddress][_delegator] = _value; - } - function setStakingEpoch(uint256 _stakingEpoch) public { stakingEpoch = _stakingEpoch; } - function setValidatorMockSetAddress(IValidatorSetHbbft _validatorSetAddress) - public - { + function setValidatorMockSetAddress(IValidatorSetHbbft _validatorSetAddress) public { validatorSetContractMock = _validatorSetAddress; } - function setValidatorSetAddress(IValidatorSetHbbft _validatorSetAddress) - public - { + function setValidatorSetAddress(IValidatorSetHbbft _validatorSetAddress) public { validatorSetContract = _validatorSetAddress; } // =============================================== Getters ======================================== + function getMaxCandidates() external pure returns (uint256) { + return _getMaxCandidates(); + } - // =============================================== Private ======================================================== + function getDelegatorStakeSnapshot(address pool, address delegator, uint256 epoch) external view returns (uint256) { + return _delegatorStakeSnapshot[pool][delegator][epoch]; + } - function _getMaxCandidates() - internal - pure - virtual - override - returns (uint256) - { - return 100; + function getStakeSnapshotLastEpoch(address pool, address delegator) external view returns (uint256) { + return _stakeSnapshotLastEpoch[pool][delegator]; } - function _sendWithdrawnStakeAmount(address payable _to, uint256 _amount) - internal - virtual - override - { - if (!_to.send(_amount)) { - // We use the `Sacrifice` trick to be sure the coins can be 100% sent to the receiver. - // Otherwise, if the receiver is a contract which has a revert in its fallback function, - // the sending will fail. - (new Sacrifice2){value: _amount}(_to); - } + // =============================================== Private ======================================================== + + function _getMaxCandidates() internal pure virtual override returns (uint256) { + return 100; } } diff --git a/contracts/mockContracts/TransferUtilsMock.sol b/contracts/mockContracts/TransferUtilsMock.sol new file mode 100644 index 00000000..6f5cadc2 --- /dev/null +++ b/contracts/mockContracts/TransferUtilsMock.sol @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity =0.8.17; + +import { TransferUtils } from "../utils/TransferUtils.sol"; + +contract TransferUtilsMock { + using TransferUtils for address; + + receive() external payable {} + + function transferNative(address recipient, uint256 amount) external payable { + recipient.transferNative(amount); + } + + function transferNativeEnsure(address recipient, uint256 amount) external payable { + TransferUtils.transferNativeEnsure(payable(recipient), amount); + } +} diff --git a/contracts/mockContracts/ValidatorSetHbbftMock.sol b/contracts/mockContracts/ValidatorSetHbbftMock.sol index 02dbf84d..dab5c873 100644 --- a/contracts/mockContracts/ValidatorSetHbbftMock.sol +++ b/contracts/mockContracts/ValidatorSetHbbftMock.sol @@ -52,6 +52,10 @@ contract ValidatorSetHbbftMock is ValidatorSetHbbft { _isFullHealth = _healthy; } + function forceFinalizeNewValidators() external { + _finalizeNewValidators(); + } + // =============================================== Getters ======================================================== function getRandomIndex( diff --git a/contracts/utils/Sacrifice.sol b/contracts/utils/Sacrifice.sol new file mode 100644 index 00000000..9d1b4217 --- /dev/null +++ b/contracts/utils/Sacrifice.sol @@ -0,0 +1,7 @@ +pragma solidity =0.8.17; + +contract Sacrifice { + constructor(address payable _recipient) payable { + selfdestruct(_recipient); + } +} diff --git a/contracts/utils/TransferUtils.sol b/contracts/utils/TransferUtils.sol new file mode 100644 index 00000000..349a21e3 --- /dev/null +++ b/contracts/utils/TransferUtils.sol @@ -0,0 +1,36 @@ +pragma solidity =0.8.17; + +import { Sacrifice } from "./Sacrifice.sol"; + +library TransferUtils { + error InsufficientBalance(); + error TransferFailed(address recipient, uint256 amount); + + function transferNative(address recipient, uint256 amount) internal { + if (address(this).balance < amount) { + revert InsufficientBalance(); + } + + // solhint-disable-next-line avoid-low-level-calls + (bool success, ) = recipient.call{ value: amount }(""); + if (!success) { + revert TransferFailed(recipient, amount); + } + } + + /// @dev Sends coins from this contract to the specified address. + /// @param _to The target address to send amount to. + /// @param _amount The amount to send. + function transferNativeEnsure( + address payable _to, + uint256 _amount + ) internal { + // slither-disable-next-line arbitrary-send-eth + if (_amount != 0 && !_to.send(_amount)) { + // We use the `Sacrifice` trick to be sure the coins can be 100% sent to the receiver. + // Otherwise, if the receiver is a contract which has a revert in its fallback function, + // the sending will fail. + (new Sacrifice){value: _amount}(_to); + } + } +} diff --git a/hardhat.config.ts b/hardhat.config.ts index 264ee582..4a9d6943 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -1,27 +1,20 @@ +import fs from "fs"; +import { ethers } from "ethers"; +import { HardhatUserConfig } from "hardhat/config"; + +import "hardhat-tracer" +import 'dotenv/config' import "@nomicfoundation/hardhat-toolbox"; -import "@nomicfoundation/hardhat-chai-matchers"; -import "@nomiclabs/hardhat-ethers"; -import "@nomiclabs/hardhat-etherscan"; +import "@nomicfoundation/hardhat-ethers"; +import "@openzeppelin/hardhat-upgrades"; import "@typechain/hardhat"; import "hardhat-gas-reporter"; -import "solidity-coverage"; import "hardhat-contract-sizer"; -import "@openzeppelin/hardhat-upgrades"; import 'solidity-docgen'; import 'hardhat-tracer'; -import { config as dotenvConfig } from "dotenv"; -import type { NetworkUserConfig } from "hardhat/types"; -// ToDo::check why config excluding gas reporter and typechain -import type { HardhatUserConfig } from "hardhat/config"; -import { resolve } from "path"; -import { utils } from "ethers"; -import fs from "fs"; -const dotenvConfigPath: string = process.env.DOTENV_CONFIG_PATH || "./.env"; -dotenvConfig({ path: resolve(__dirname, dotenvConfigPath) }); +import './tasks/make_spec'; -// ToDo::change require to smth more suitable -require('./tasks'); const getMnemonic = () => { try { @@ -33,40 +26,14 @@ const getMnemonic = () => { }; // Ensure that we have all the environment variables we need. -const mnemonic: string = process.env.MNEMONIC ? process.env.MNEMONIC : utils.entropyToMnemonic(utils.randomBytes(32)); - -const infuraApiKey: string = process.env.INFURA_API_KEY ? process.env.INFURA_API_KEY : ""; +const mnemonic: string = process.env.MNEMONIC ? process.env.MNEMONIC : ethers.Mnemonic.entropyToPhrase(ethers.randomBytes(32)); const chainIds = { hardhat: 31337, alpha2: 777012 }; -function getChainConfig(chain: keyof typeof chainIds): NetworkUserConfig { - let jsonRpcUrl: string; - switch (chain) { - case "alpha2": - jsonRpcUrl = "http://rpc.uniq.diamonds:8540"; - break; - default: - jsonRpcUrl = "https://" + chain + ".infura.io/v3/" + infuraApiKey; - } - return { - accounts: { - count: 10, - mnemonic, - path: "m/44'/60'/0'/0", - }, - chainId: chainIds[chain], - gas: 21_000_000_000, - gasPrice: 1_000_000_000, - allowUnlimitedContractSize: true, - blockGasLimit: 100000000429720, - url: jsonRpcUrl, - }; -} - -const config: {} = { +const config: HardhatUserConfig = { defaultNetwork: "hardhat", etherscan: { // apiKey: process.env.ETHERSCAN_API_KEY, @@ -192,7 +159,7 @@ const config: {} = { }, typechain: { outDir: "src/types", - target: "ethers-v5", + target: "ethers-v6", }, mocha: { timeout: 100000000 diff --git a/package-lock.json b/package-lock.json index ceca2a34..86fe619b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,40 +7,39 @@ "": { "name": "diamond-contracts-core", "version": "0.8.9", - "dependencies": { - "hardhat-tracer": "^1.3.0" - }, "devDependencies": { - "@nomicfoundation/hardhat-chai-matchers": "^1.0.2", - "@nomicfoundation/hardhat-network-helpers": "^1.0.3", - "@nomicfoundation/hardhat-toolbox": "^2.0.2", - "@nomiclabs/hardhat-ethers": "^2.0.2", - "@nomiclabs/hardhat-etherscan": "^3.1.0", - "@openzeppelin/contracts": "^4.9.2", - "@openzeppelin/contracts-upgradeable": "^4.9.2", - "@openzeppelin/hardhat-upgrades": "^1.28.0", - "@typechain/ethers-v5": "^10.1.0", - "@typechain/hardhat": "^6.1.3", + "@nomicfoundation/hardhat-ethers": "^3.0.5", + "@nomicfoundation/hardhat-toolbox": "^5.0.0", + "@openzeppelin/contracts": "^4.9.6", + "@openzeppelin/contracts-upgradeable": "^4.9.6", + "@openzeppelin/hardhat-upgrades": "^3.0.5", + "@typechain/ethers-v6": "^0.5.1", + "@typechain/hardhat": "^9.1.0", "@types/chai": "^4.3.3", - "@types/fs-extra": "^9.0.13", + "@types/fs-extra": "^11.0.4", "@types/lodash": "^4.14.186", - "@types/mocha": "^9.1.1", - "@types/node": "^18.11.2", - "chai-bn": "^0.3.1", + "@types/mocha": "^10.0.6", + "@types/node": "^20.12.2", "dotenv": "^16.0.2", - "ethers": "^5.6.9", - "hardhat": "2.12.2", + "ethers": "^6.11.1", + "hardhat": "^2.20.1", "hardhat-contract-sizer": "^2.6.1", - "hardhat-gas-reporter": "^1.0.8", + "hardhat-tracer": "^2.8.2", "lodash": "^4.17.21", "solc": "0.8.17", "solidity-coverage": "^0.8.5", "solidity-docgen": "^0.6.0-beta.29", "ts-node": "^10.9.1", "typechain": "^8.1.0", - "typescript": "^4.8.4" + "typescript": "^5.4.3" } }, + "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==", + "dev": true + }, "node_modules/@aws-crypto/sha256-js": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-1.2.2.tgz", @@ -64,22 +63,22 @@ } }, "node_modules/@aws-sdk/types": { - "version": "3.369.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.369.0.tgz", - "integrity": "sha512-0LgII+RatF2OEFaFQcNyX72py4ZgWz+/JAv++PXv0gkIaTRnsJbSveQArNynEK+aAc/rZKWJgBvwT4FvLM2vgA==", + "version": "3.535.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.535.0.tgz", + "integrity": "sha512-aY4MYfduNj+sRR37U7XxYR8wemfbKP6lx00ze2M2uubn7mZotuVrWYAafbMSXrdEMSToE5JDhr28vArSOoLcSg==", "dev": true, "dependencies": { - "@smithy/types": "1.1.0", - "tslib": "^2.5.0" + "@smithy/types": "^2.12.0", + "tslib": "^2.6.2" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@aws-sdk/types/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", "dev": true }, "node_modules/@aws-sdk/util-utf8-browser": { @@ -92,9 +91,9 @@ } }, "node_modules/@aws-sdk/util-utf8-browser/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", "dev": true }, "node_modules/@colors/colors": { @@ -111,7 +110,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==", - "devOptional": true, + "dev": true, "dependencies": { "@jridgewell/trace-mapping": "0.3.9" }, @@ -119,10 +118,73 @@ "node": ">=12" } }, + "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, + "bin": { + "rlp": "bin/rlp" + }, + "engines": { + "node": ">=14" + } + }, + "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, + "dependencies": { + "@ethereumjs/rlp": "^4.0.1", + "ethereum-cryptography": "^2.0.0", + "micro-ftch": "^0.3.1" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/@ethereumjs/util/node_modules/@noble/curves": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.3.0.tgz", + "integrity": "sha512-t01iSXPuN+Eqzb4eBX0S5oubSqXbK/xXa1Ne18Hj8f9pStxztHCE2gfboSp/dZRLSqfuLpRK2nDXDK+W9puocA==", + "dev": true, + "dependencies": { + "@noble/hashes": "1.3.3" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@ethereumjs/util/node_modules/@noble/hashes": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.3.tgz", + "integrity": "sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA==", + "dev": true, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@ethereumjs/util/node_modules/ethereum-cryptography": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.1.3.tgz", + "integrity": "sha512-BlwbIL7/P45W8FGW2r7LGuvoEZ+7PWsniMvQ4p5s2xCyw9tmaDlpfsN9HjAucbF+t/qpVHwZUisgfK24TCW8aA==", + "dev": true, + "dependencies": { + "@noble/curves": "1.3.0", + "@noble/hashes": "1.3.3", + "@scure/bip32": "1.3.3", + "@scure/bip39": "1.2.2" + } + }, "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==", + "dev": true, "funding": [ { "type": "individual", @@ -149,6 +211,7 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.7.0.tgz", "integrity": "sha512-R41c9UkchKCpAqStMYUpdunjo3pkEvZC3FAwZn5S5MGbXoMQOHIdHItezTETxAO5bevtMApSyEhn9+CHcDsWBw==", + "dev": true, "funding": [ { "type": "individual", @@ -173,6 +236,7 @@ "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==", + "dev": true, "funding": [ { "type": "individual", @@ -195,6 +259,7 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.7.0.tgz", "integrity": "sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA==", + "dev": true, "funding": [ { "type": "individual", @@ -217,6 +282,7 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.7.0.tgz", "integrity": "sha512-Dr8tcHt2mEbsZr/mwTPIQAf3Ai0Bks/7gTw9dSqk1mQvhW3XvRlmDJr/4n+wg1JmCl16NZue17CDh8xb/vZ0sQ==", + "dev": true, "funding": [ { "type": "individual", @@ -235,6 +301,7 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/basex/-/basex-5.7.0.tgz", "integrity": "sha512-ywlh43GwZLv2Voc2gQVTKBoVQ1mti3d8HK5aMxsfu/nRDnMmNqaSJ3r3n85HBByT8OpoY96SXM1FogC533T4zw==", + "dev": true, "funding": [ { "type": "individual", @@ -254,6 +321,7 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.7.0.tgz", "integrity": "sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw==", + "dev": true, "funding": [ { "type": "individual", @@ -274,6 +342,7 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.7.0.tgz", "integrity": "sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A==", + "dev": true, "funding": [ { "type": "individual", @@ -292,6 +361,7 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.7.0.tgz", "integrity": "sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA==", + "dev": true, "funding": [ { "type": "individual", @@ -310,6 +380,7 @@ "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==", + "dev": true, "funding": [ { "type": "individual", @@ -337,6 +408,7 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.7.0.tgz", "integrity": "sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g==", + "dev": true, "funding": [ { "type": "individual", @@ -363,6 +435,7 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/hdnode/-/hdnode-5.7.0.tgz", "integrity": "sha512-OmyYo9EENBPPf4ERhR7oj6uAtUAhYGqOnIS+jE5pTXvdKBS99ikzq1E7Iv0ZQZ5V36Lqx1qZLeak0Ra16qpeOg==", + "dev": true, "funding": [ { "type": "individual", @@ -392,6 +465,7 @@ "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==", + "dev": true, "funding": [ { "type": "individual", @@ -418,10 +492,17 @@ "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==", + "dev": true + }, "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==", + "dev": true, "funding": [ { "type": "individual", @@ -441,6 +522,7 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.7.0.tgz", "integrity": "sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig==", + "dev": true, "funding": [ { "type": "individual", @@ -456,6 +538,7 @@ "version": "5.7.1", "resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.7.1.tgz", "integrity": "sha512-n/MufjFYv3yFcUyfhnXotyDlNdFb7onmkSy8aQERi2PjNcnWQ66xXxa3XlS8nCcA8aJKJjIIMNJTC7tu80GwpQ==", + "dev": true, "funding": [ { "type": "individual", @@ -474,6 +557,7 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/pbkdf2/-/pbkdf2-5.7.0.tgz", "integrity": "sha512-oR/dBRZR6GTyaofd86DehG72hY6NpAjhabkhxgr3X2FpJtJuodEl2auADWBZfhDHgVCbu3/H/Ocq2uC6dpNjjw==", + "dev": true, "funding": [ { "type": "individual", @@ -493,6 +577,7 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.7.0.tgz", "integrity": "sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw==", + "dev": true, "funding": [ { "type": "individual", @@ -511,6 +596,7 @@ "version": "5.7.2", "resolved": "https://registry.npmjs.org/@ethersproject/providers/-/providers-5.7.2.tgz", "integrity": "sha512-g34EWZ1WWAVgr4aptGlVBF8mhl3VWjv+8hoAnzStu8Ah22VHBsuGzP17eb6xDVRzw895G4W7vvx60lFFur/1Rg==", + "dev": true, "funding": [ { "type": "individual", @@ -544,10 +630,32 @@ "ws": "7.4.6" } }, + "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==", + "dev": true, + "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/@ethersproject/random": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/random/-/random-5.7.0.tgz", "integrity": "sha512-19WjScqRA8IIeWclFme75VMXSBvi4e6InrUNuaR4s5pTF2qNhcGdCUwdxUVGtDDqC00sDLCO93jPQoDUH4HVmQ==", + "dev": true, "funding": [ { "type": "individual", @@ -567,6 +675,7 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.7.0.tgz", "integrity": "sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w==", + "dev": true, "funding": [ { "type": "individual", @@ -586,6 +695,7 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/sha2/-/sha2-5.7.0.tgz", "integrity": "sha512-gKlH42riwb3KYp0reLsFTokByAKoJdgFCwI+CCiX/k+Jm2mbNs6oOaCjYQSlI1+XBVejwH2KrmCbMAT/GnRDQw==", + "dev": true, "funding": [ { "type": "individual", @@ -606,6 +716,7 @@ "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==", + "dev": true, "funding": [ { "type": "individual", @@ -629,6 +740,7 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/solidity/-/solidity-5.7.0.tgz", "integrity": "sha512-HmabMd2Dt/raavyaGukF4XxizWKhKQ24DoLtdNbBmNKUOPqwjsKQSdV9GQtj9CBEea9DlzETlVER1gYeXXBGaA==", + "dev": true, "funding": [ { "type": "individual", @@ -652,6 +764,7 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.7.0.tgz", "integrity": "sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg==", + "dev": true, "funding": [ { "type": "individual", @@ -672,6 +785,7 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.7.0.tgz", "integrity": "sha512-kmcNicCp1lp8qanMTC3RIikGgoJ80ztTyvtsFvCYpSCfkjhD0jZ2LOrnbcuxuToLIUYYf+4XwD1rP+B/erDIhQ==", + "dev": true, "funding": [ { "type": "individual", @@ -698,6 +812,7 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/units/-/units-5.7.0.tgz", "integrity": "sha512-pD3xLMy3SJu9kG5xDGI7+xhTEmGXlEqXU4OfNapmfnxLVY4EMSSRp7j1k7eezutBPH7RBN/7QPnwR7hzNlEFeg==", + "dev": true, "funding": [ { "type": "individual", @@ -718,6 +833,7 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/wallet/-/wallet-5.7.0.tgz", "integrity": "sha512-MhmXlJXEJFBFVKrDLB4ZdDzxcBxQ3rLyCkhNqVu3CDYvR97E+8r01UgrI+TI99Le+aYm/in/0vp86guJuM7FCA==", + "dev": true, "funding": [ { "type": "individual", @@ -750,6 +866,7 @@ "version": "5.7.1", "resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.7.1.tgz", "integrity": "sha512-Gueu8lSvyjBWL4cYsWsjh6MtMwM0+H4HvqFPZfB6dV8ctbP9zFAO73VG1cMWae0FLPCtz0peKPpZY8/ugJJX2w==", + "dev": true, "funding": [ { "type": "individual", @@ -772,6 +889,7 @@ "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/wordlists/-/wordlists-5.7.0.tgz", "integrity": "sha512-S2TFNJNfHWVHNE6cNDjbVlZ6MgE17MIxMbMg2zv3wn+3XSJGosL1m9ZVv3GXCf/2ymSsQ+hRI5IzoMJTG6aoVA==", + "dev": true, "funding": [ { "type": "individual", @@ -790,11 +908,20 @@ "@ethersproject/strings": "^5.7.0" } }, + "node_modules/@fastify/busboy": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", + "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", + "dev": true, + "engines": { + "node": ">=14" + } + }, "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", - "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", - "devOptional": true, + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, "engines": { "node": ">=6.0.0" } @@ -803,13 +930,13 @@ "version": "1.4.15", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", - "devOptional": true + "dev": true }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.9", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", - "devOptional": true, + "dev": true, "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" @@ -819,6 +946,7 @@ "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==", + "dev": true, "dependencies": { "ethereumjs-abi": "^0.6.8", "ethereumjs-util": "^6.2.1", @@ -834,6 +962,7 @@ "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==", + "dev": true, "dependencies": { "@types/node": "*" } @@ -841,12 +970,14 @@ "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==" + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true }, "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==", + "dev": true, "dependencies": { "@types/bn.js": "^4.11.3", "bn.js": "^4.11.0", @@ -857,21 +988,35 @@ "rlp": "^2.2.3" } }, - "node_modules/@noble/hashes": { + "node_modules/@noble/curves": { "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/" - } - ] + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz", + "integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==", + "dev": true, + "dependencies": { + "@noble/hashes": "1.3.2" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "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, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } }, "node_modules/@noble/secp256k1": { "version": "1.7.1", "resolved": "https://registry.npmjs.org/@noble/secp256k1/-/secp256k1-1.7.1.tgz", "integrity": "sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw==", + "dev": true, "funding": [ { "type": "individual", @@ -915,201 +1060,329 @@ } }, "node_modules/@nomicfoundation/ethereumjs-block": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-block/-/ethereumjs-block-4.2.2.tgz", - "integrity": "sha512-atjpt4gc6ZGZUPHBAQaUJsm1l/VCo7FmyQ780tMGO8QStjLdhz09dXynmhwVTy5YbRr0FOh/uX3QaEM0yIB2Zg==", - "dependencies": { - "@nomicfoundation/ethereumjs-common": "3.1.2", - "@nomicfoundation/ethereumjs-rlp": "4.0.3", - "@nomicfoundation/ethereumjs-trie": "5.0.5", - "@nomicfoundation/ethereumjs-tx": "4.1.2", - "@nomicfoundation/ethereumjs-util": "8.0.6", + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-block/-/ethereumjs-block-5.0.4.tgz", + "integrity": "sha512-AcyacJ9eX/uPEvqsPiB+WO1ymE+kyH48qGGiGV+YTojdtas8itUTW5dehDSOXEEItWGbbzEJ4PRqnQZlWaPvDw==", + "dev": true, + "dependencies": { + "@nomicfoundation/ethereumjs-common": "4.0.4", + "@nomicfoundation/ethereumjs-rlp": "5.0.4", + "@nomicfoundation/ethereumjs-trie": "6.0.4", + "@nomicfoundation/ethereumjs-tx": "5.0.4", + "@nomicfoundation/ethereumjs-util": "9.0.4", "ethereum-cryptography": "0.1.3" }, "engines": { - "node": ">=14" + "node": ">=18" } }, "node_modules/@nomicfoundation/ethereumjs-blockchain": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-blockchain/-/ethereumjs-blockchain-6.2.2.tgz", - "integrity": "sha512-6AIB2MoTEPZJLl6IRKcbd8mUmaBAQ/NMe3O7OsAOIiDjMNPPH5KaUQiLfbVlegT4wKIg/GOsFH7XlH2KDVoJNg==", - "dependencies": { - "@nomicfoundation/ethereumjs-block": "4.2.2", - "@nomicfoundation/ethereumjs-common": "3.1.2", - "@nomicfoundation/ethereumjs-ethash": "2.0.5", - "@nomicfoundation/ethereumjs-rlp": "4.0.3", - "@nomicfoundation/ethereumjs-trie": "5.0.5", - "@nomicfoundation/ethereumjs-util": "8.0.6", - "abstract-level": "^1.0.3", + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-blockchain/-/ethereumjs-blockchain-7.0.4.tgz", + "integrity": "sha512-jYsd/kwzbmpnxx86tXsYV8wZ5xGvFL+7/P0c6OlzpClHsbFzeF41KrYA9scON8Rg6bZu3ZTv6JOAgj3t7USUfg==", + "dev": true, + "dependencies": { + "@nomicfoundation/ethereumjs-block": "5.0.4", + "@nomicfoundation/ethereumjs-common": "4.0.4", + "@nomicfoundation/ethereumjs-ethash": "3.0.4", + "@nomicfoundation/ethereumjs-rlp": "5.0.4", + "@nomicfoundation/ethereumjs-trie": "6.0.4", + "@nomicfoundation/ethereumjs-tx": "5.0.4", + "@nomicfoundation/ethereumjs-util": "9.0.4", "debug": "^4.3.3", "ethereum-cryptography": "0.1.3", - "level": "^8.0.0", - "lru-cache": "^5.1.1", - "memory-level": "^1.0.0" + "lru-cache": "^10.0.0" }, "engines": { - "node": ">=14" + "node": ">=18" + } + }, + "node_modules/@nomicfoundation/ethereumjs-blockchain/node_modules/lru-cache": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", + "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", + "dev": true, + "engines": { + "node": "14 || >=16.14" } }, "node_modules/@nomicfoundation/ethereumjs-common": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-common/-/ethereumjs-common-3.1.2.tgz", - "integrity": "sha512-JAEBpIua62dyObHM9KI2b4wHZcRQYYge9gxiygTWa3lNCr2zo+K0TbypDpgiNij5MCGNWP1eboNfNfx1a3vkvA==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-common/-/ethereumjs-common-4.0.4.tgz", + "integrity": "sha512-9Rgb658lcWsjiicr5GzNCjI1llow/7r0k50dLL95OJ+6iZJcVbi15r3Y0xh2cIO+zgX0WIHcbzIu6FeQf9KPrg==", + "dev": true, "dependencies": { - "@nomicfoundation/ethereumjs-util": "8.0.6", - "crc-32": "^1.2.0" + "@nomicfoundation/ethereumjs-util": "9.0.4" } }, "node_modules/@nomicfoundation/ethereumjs-ethash": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-ethash/-/ethereumjs-ethash-2.0.5.tgz", - "integrity": "sha512-xlLdcICGgAYyYmnI3r1t0R5fKGBJNDQSOQxXNjVO99JmxJIdXR5MgPo5CSJO1RpyzKOgzi3uIFn8agv564dZEQ==", - "dependencies": { - "@nomicfoundation/ethereumjs-block": "4.2.2", - "@nomicfoundation/ethereumjs-rlp": "4.0.3", - "@nomicfoundation/ethereumjs-util": "8.0.6", - "abstract-level": "^1.0.3", - "bigint-crypto-utils": "^3.0.23", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-ethash/-/ethereumjs-ethash-3.0.4.tgz", + "integrity": "sha512-xvIrwIMl9sSaiYKRem68+O7vYdj7Q2XWv5P7JXiIkn83918QzWHvqbswTRsH7+r6X1UEvdsURRnZbvZszEjAaQ==", + "dev": true, + "dependencies": { + "@nomicfoundation/ethereumjs-block": "5.0.4", + "@nomicfoundation/ethereumjs-rlp": "5.0.4", + "@nomicfoundation/ethereumjs-util": "9.0.4", + "bigint-crypto-utils": "^3.2.2", "ethereum-cryptography": "0.1.3" }, "engines": { - "node": ">=14" + "node": ">=18" } }, "node_modules/@nomicfoundation/ethereumjs-evm": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-evm/-/ethereumjs-evm-1.3.2.tgz", - "integrity": "sha512-I00d4MwXuobyoqdPe/12dxUQxTYzX8OckSaWsMcWAfQhgVDvBx6ffPyP/w1aL0NW7MjyerySPcSVfDJAMHjilw==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-evm/-/ethereumjs-evm-2.0.4.tgz", + "integrity": "sha512-lTyZZi1KpeMHzaO6cSVisR2tjiTTedjo7PcmhI/+GNFo9BmyY6QYzGeSti0sFttmjbEMioHgXxl5yrLNRg6+1w==", + "dev": true, "dependencies": { - "@nomicfoundation/ethereumjs-common": "3.1.2", - "@nomicfoundation/ethereumjs-util": "8.0.6", - "@types/async-eventemitter": "^0.2.1", - "async-eventemitter": "^0.2.4", + "@nomicfoundation/ethereumjs-common": "4.0.4", + "@nomicfoundation/ethereumjs-statemanager": "2.0.4", + "@nomicfoundation/ethereumjs-tx": "5.0.4", + "@nomicfoundation/ethereumjs-util": "9.0.4", + "@types/debug": "^4.1.9", "debug": "^4.3.3", "ethereum-cryptography": "0.1.3", - "mcl-wasm": "^0.7.1", - "rustbn.js": "~0.2.0" + "rustbn-wasm": "^0.2.0" }, "engines": { - "node": ">=14" + "node": ">=18" } }, "node_modules/@nomicfoundation/ethereumjs-rlp": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-rlp/-/ethereumjs-rlp-4.0.3.tgz", - "integrity": "sha512-DZMzB/lqPK78T6MluyXqtlRmOMcsZbTTbbEyAjo0ncaff2mqu/k8a79PBcyvpgAhWD/R59Fjq/x3ro5Lof0AtA==", + "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, "bin": { - "rlp": "bin/rlp" + "rlp": "bin/rlp.cjs" }, "engines": { - "node": ">=14" + "node": ">=18" } }, "node_modules/@nomicfoundation/ethereumjs-statemanager": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-statemanager/-/ethereumjs-statemanager-1.0.5.tgz", - "integrity": "sha512-CAhzpzTR5toh/qOJIZUUOnWekUXuRqkkzaGAQrVcF457VhtCmr+ddZjjK50KNZ524c1XP8cISguEVNqJ6ij1sA==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-statemanager/-/ethereumjs-statemanager-2.0.4.tgz", + "integrity": "sha512-HPDjeFrxw6llEi+BzqXkZ+KkvFnTOPczuHBtk21hRlDiuKuZz32dPzlhpRsDBGV1b5JTmRDUVqCS1lp3Gghw4Q==", + "dev": true, "dependencies": { - "@nomicfoundation/ethereumjs-common": "3.1.2", - "@nomicfoundation/ethereumjs-rlp": "4.0.3", - "@nomicfoundation/ethereumjs-trie": "5.0.5", - "@nomicfoundation/ethereumjs-util": "8.0.6", + "@nomicfoundation/ethereumjs-common": "4.0.4", + "@nomicfoundation/ethereumjs-rlp": "5.0.4", + "@nomicfoundation/ethereumjs-trie": "6.0.4", + "@nomicfoundation/ethereumjs-util": "9.0.4", "debug": "^4.3.3", "ethereum-cryptography": "0.1.3", - "functional-red-black-tree": "^1.0.1" + "js-sdsl": "^4.1.4", + "lru-cache": "^10.0.0" + }, + "peerDependencies": { + "@nomicfoundation/ethereumjs-verkle": "0.0.2" + }, + "peerDependenciesMeta": { + "@nomicfoundation/ethereumjs-verkle": { + "optional": true + } + } + }, + "node_modules/@nomicfoundation/ethereumjs-statemanager/node_modules/lru-cache": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", + "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", + "dev": true, + "engines": { + "node": "14 || >=16.14" } }, "node_modules/@nomicfoundation/ethereumjs-trie": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-trie/-/ethereumjs-trie-5.0.5.tgz", - "integrity": "sha512-+8sNZrXkzvA1NH5F4kz5RSYl1I6iaRz7mAZRsyxOm0IVY4UaP43Ofvfp/TwOalFunurQrYB5pRO40+8FBcxFMA==", + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-trie/-/ethereumjs-trie-6.0.4.tgz", + "integrity": "sha512-3nSwQiFMvr2VFe/aZUyinuohYvtytUqZCUCvIWcPJ/BwJH6oQdZRB42aNFBJ/8nAh2s3OcroWpBLskzW01mFKA==", + "dev": true, "dependencies": { - "@nomicfoundation/ethereumjs-rlp": "4.0.3", - "@nomicfoundation/ethereumjs-util": "8.0.6", + "@nomicfoundation/ethereumjs-rlp": "5.0.4", + "@nomicfoundation/ethereumjs-util": "9.0.4", + "@types/readable-stream": "^2.3.13", "ethereum-cryptography": "0.1.3", + "lru-cache": "^10.0.0", "readable-stream": "^3.6.0" }, "engines": { - "node": ">=14" + "node": ">=18" + } + }, + "node_modules/@nomicfoundation/ethereumjs-trie/node_modules/lru-cache": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", + "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", + "dev": true, + "engines": { + "node": "14 || >=16.14" } }, "node_modules/@nomicfoundation/ethereumjs-tx": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-tx/-/ethereumjs-tx-4.1.2.tgz", - "integrity": "sha512-emJBJZpmTdUa09cqxQqHaysbBI9Od353ZazeH7WgPb35miMgNY6mb7/3vBA98N5lUW/rgkiItjX0KZfIzihSoQ==", + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-tx/-/ethereumjs-tx-5.0.4.tgz", + "integrity": "sha512-Xjv8wAKJGMrP1f0n2PeyfFCCojHd7iS3s/Ab7qzF1S64kxZ8Z22LCMynArYsVqiFx6rzYy548HNVEyI+AYN/kw==", + "dev": true, "dependencies": { - "@nomicfoundation/ethereumjs-common": "3.1.2", - "@nomicfoundation/ethereumjs-rlp": "4.0.3", - "@nomicfoundation/ethereumjs-util": "8.0.6", + "@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": ">=14" + "node": ">=18" + }, + "peerDependencies": { + "c-kzg": "^2.1.2" + }, + "peerDependenciesMeta": { + "c-kzg": { + "optional": true + } } }, "node_modules/@nomicfoundation/ethereumjs-util": { - "version": "8.0.6", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-util/-/ethereumjs-util-8.0.6.tgz", - "integrity": "sha512-jOQfF44laa7xRfbfLXojdlcpkvxeHrE2Xu7tSeITsWFgoII163MzjOwFEzSNozHYieFysyoEMhCdP+NY5ikstw==", + "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, "dependencies": { - "@nomicfoundation/ethereumjs-rlp": "4.0.3", + "@nomicfoundation/ethereumjs-rlp": "5.0.4", "ethereum-cryptography": "0.1.3" }, "engines": { - "node": ">=14" + "node": ">=18" + }, + "peerDependencies": { + "c-kzg": "^2.1.2" + }, + "peerDependenciesMeta": { + "c-kzg": { + "optional": true + } + } + }, + "node_modules/@nomicfoundation/ethereumjs-verkle": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-verkle/-/ethereumjs-verkle-0.0.2.tgz", + "integrity": "sha512-bjnfZElpYGK/XuuVRmLS3yDvr+cDs85D9oonZ0YUa5A3lgFgokWMp76zXrxX2jVQ0BfHaw12y860n1+iOi6yFQ==", + "dev": true, + "dependencies": { + "@nomicfoundation/ethereumjs-rlp": "5.0.4", + "@nomicfoundation/ethereumjs-util": "9.0.4", + "lru-cache": "^10.0.0", + "rust-verkle-wasm": "^0.0.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@nomicfoundation/ethereumjs-verkle/node_modules/lru-cache": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", + "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", + "dev": true, + "engines": { + "node": "14 || >=16.14" } }, "node_modules/@nomicfoundation/ethereumjs-vm": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-vm/-/ethereumjs-vm-6.4.2.tgz", - "integrity": "sha512-PRTyxZMP6kx+OdAzBhuH1LD2Yw+hrSpaytftvaK//thDy2OI07S0nrTdbrdk7b8ZVPAc9H9oTwFBl3/wJ3w15g==", - "dependencies": { - "@nomicfoundation/ethereumjs-block": "4.2.2", - "@nomicfoundation/ethereumjs-blockchain": "6.2.2", - "@nomicfoundation/ethereumjs-common": "3.1.2", - "@nomicfoundation/ethereumjs-evm": "1.3.2", - "@nomicfoundation/ethereumjs-rlp": "4.0.3", - "@nomicfoundation/ethereumjs-statemanager": "1.0.5", - "@nomicfoundation/ethereumjs-trie": "5.0.5", - "@nomicfoundation/ethereumjs-tx": "4.1.2", - "@nomicfoundation/ethereumjs-util": "8.0.6", - "@types/async-eventemitter": "^0.2.1", - "async-eventemitter": "^0.2.4", + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/@nomicfoundation/ethereumjs-vm/-/ethereumjs-vm-7.0.4.tgz", + "integrity": "sha512-gsA4IhmtWHI4BofKy3kio9W+dqZQs5Ji5mLjLYxHCkat+JQBUt5szjRKra2F9nGDJ2XcI/wWb0YWUFNgln4zRQ==", + "dev": true, + "dependencies": { + "@nomicfoundation/ethereumjs-block": "5.0.4", + "@nomicfoundation/ethereumjs-blockchain": "7.0.4", + "@nomicfoundation/ethereumjs-common": "4.0.4", + "@nomicfoundation/ethereumjs-evm": "2.0.4", + "@nomicfoundation/ethereumjs-rlp": "5.0.4", + "@nomicfoundation/ethereumjs-statemanager": "2.0.4", + "@nomicfoundation/ethereumjs-trie": "6.0.4", + "@nomicfoundation/ethereumjs-tx": "5.0.4", + "@nomicfoundation/ethereumjs-util": "9.0.4", "debug": "^4.3.3", - "ethereum-cryptography": "0.1.3", - "functional-red-black-tree": "^1.0.1", - "mcl-wasm": "^0.7.1", - "rustbn.js": "~0.2.0" + "ethereum-cryptography": "0.1.3" }, "engines": { - "node": ">=14" + "node": ">=18" } }, "node_modules/@nomicfoundation/hardhat-chai-matchers": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-chai-matchers/-/hardhat-chai-matchers-1.0.6.tgz", - "integrity": "sha512-f5ZMNmabZeZegEfuxn/0kW+mm7+yV7VNDxLpMOMGXWFJ2l/Ct3QShujzDRF9cOkK9Ui/hbDeOWGZqyQALDXVCQ==", + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-chai-matchers/-/hardhat-chai-matchers-2.0.6.tgz", + "integrity": "sha512-Te1Uyo9oJcTCF0Jy9dztaLpshmlpjLf2yPtWXlXuLjMt3RRSmJLm/+rKVTW6gfadAEs12U/it6D0ZRnnRGiICQ==", "dev": true, + "peer": true, "dependencies": { - "@ethersproject/abi": "^5.1.2", "@types/chai-as-promised": "^7.1.3", "chai-as-promised": "^7.1.1", "deep-eql": "^4.0.1", "ordinal": "^1.0.3" }, "peerDependencies": { - "@nomiclabs/hardhat-ethers": "^2.0.0", + "@nomicfoundation/hardhat-ethers": "^3.0.0", "chai": "^4.2.0", - "ethers": "^5.0.0", + "ethers": "^6.1.0", "hardhat": "^2.9.4" } }, + "node_modules/@nomicfoundation/hardhat-ethers": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-ethers/-/hardhat-ethers-3.0.5.tgz", + "integrity": "sha512-RNFe8OtbZK6Ila9kIlHp0+S80/0Bu/3p41HUpaRIoHLm6X3WekTd83vob3rE54Duufu1edCiBDxspBzi2rxHHw==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "lodash.isequal": "^4.5.0" + }, + "peerDependencies": { + "ethers": "^6.1.0", + "hardhat": "^2.0.0" + } + }, + "node_modules/@nomicfoundation/hardhat-ignition": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-ignition/-/hardhat-ignition-0.15.0.tgz", + "integrity": "sha512-GbAe90O22uM67U/JnffXX+mBMn0HqCKSH+D98Tb5uWqR1N/M00cB3yY8OdqzVai7I6SuIKTc91mPdvtWt8R3MA==", + "dev": true, + "peer": true, + "dependencies": { + "@nomicfoundation/ignition-core": "^0.15.0", + "@nomicfoundation/ignition-ui": "^0.15.0", + "chalk": "^4.0.0", + "debug": "^4.3.2", + "fs-extra": "^10.0.0", + "prompts": "^2.4.2" + }, + "peerDependencies": { + "@nomicfoundation/hardhat-verify": "^2.0.1", + "hardhat": "^2.18.0" + } + }, + "node_modules/@nomicfoundation/hardhat-ignition-ethers": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-ignition-ethers/-/hardhat-ignition-ethers-0.15.0.tgz", + "integrity": "sha512-KmMNUc/jptfwdPA9ukQf+Ajon+m2vLBjDL2ze7d/vQdrS+fDxmoVwmbbEk4GOjianZcwgQOWD9dEWaj04QiowA==", + "dev": true, + "peer": true, + "peerDependencies": { + "@nomicfoundation/hardhat-ethers": "^3.0.4", + "@nomicfoundation/hardhat-ignition": "^0.15.0", + "@nomicfoundation/ignition-core": "^0.15.0", + "ethers": "^6.7.0", + "hardhat": "^2.18.0" + } + }, "node_modules/@nomicfoundation/hardhat-network-helpers": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-network-helpers/-/hardhat-network-helpers-1.0.8.tgz", - "integrity": "sha512-MNqQbzUJZnCMIYvlniC3U+kcavz/PhhQSsY90tbEtUyMj/IQqsLwIRZa4ctjABh3Bz0KCh9OXUZ7Yk/d9hr45Q==", + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-network-helpers/-/hardhat-network-helpers-1.0.10.tgz", + "integrity": "sha512-R35/BMBlx7tWN5V6d/8/19QCwEmIdbnA4ZrsuXgvs8i2qFx5i7h6mH5pBS4Pwi4WigLH+upl6faYusrNPuzMrQ==", "dev": true, + "peer": true, "dependencies": { "ethereumjs-util": "^7.1.4" }, @@ -1118,39 +1391,199 @@ } }, "node_modules/@nomicfoundation/hardhat-toolbox": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-toolbox/-/hardhat-toolbox-2.0.2.tgz", - "integrity": "sha512-vnN1AzxbvpSx9pfdRHbUzTRIXpMLPXnUlkW855VaDk6N1pwRaQ2gNzEmFAABk4lWf11E00PKwFd/q27HuwYrYg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-toolbox/-/hardhat-toolbox-5.0.0.tgz", + "integrity": "sha512-FnUtUC5PsakCbwiVNsqlXVIWG5JIb5CEZoSXbJUsEBun22Bivx2jhF1/q9iQbzuaGpJKFQyOhemPB2+XlEE6pQ==", "dev": true, "peerDependencies": { - "@ethersproject/abi": "^5.4.7", - "@ethersproject/providers": "^5.4.7", - "@nomicfoundation/hardhat-chai-matchers": "^1.0.0", + "@nomicfoundation/hardhat-chai-matchers": "^2.0.0", + "@nomicfoundation/hardhat-ethers": "^3.0.0", + "@nomicfoundation/hardhat-ignition-ethers": "^0.15.0", "@nomicfoundation/hardhat-network-helpers": "^1.0.0", - "@nomiclabs/hardhat-ethers": "^2.0.0", - "@nomiclabs/hardhat-etherscan": "^3.0.0", - "@typechain/ethers-v5": "^10.1.0", - "@typechain/hardhat": "^6.1.2", + "@nomicfoundation/hardhat-verify": "^2.0.0", + "@typechain/ethers-v6": "^0.5.0", + "@typechain/hardhat": "^9.0.0", "@types/chai": "^4.2.0", "@types/mocha": ">=9.1.0", - "@types/node": ">=12.0.0", + "@types/node": ">=18.0.0", "chai": "^4.2.0", - "ethers": "^5.4.7", + "ethers": "^6.4.0", "hardhat": "^2.11.0", "hardhat-gas-reporter": "^1.0.8", "solidity-coverage": "^0.8.1", "ts-node": ">=8.0.0", - "typechain": "^8.1.0", + "typechain": "^8.3.0", "typescript": ">=4.5.0" } }, - "node_modules/@nomicfoundation/solidity-analyzer": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer/-/solidity-analyzer-0.1.1.tgz", - "integrity": "sha512-1LMtXj1puAxyFusBgUIy5pZk3073cNXYnXUpuNKFghHbIit/xZgbk0AokpUADbNm3gyD6bFWl3LRFh3dhVdREg==", - "engines": { - "node": ">= 12" - }, + "node_modules/@nomicfoundation/hardhat-verify": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nomicfoundation/hardhat-verify/-/hardhat-verify-2.0.5.tgz", + "integrity": "sha512-Tg4zu8RkWpyADSFIgF4FlJIUEI4VkxcvELsmbJn2OokbvH2SnUrqKmw0BBfDrtvP0hhmx8wsnrRKP5DV/oTyTA==", + "dev": true, + "peer": true, + "dependencies": { + "@ethersproject/abi": "^5.1.2", + "@ethersproject/address": "^5.0.2", + "cbor": "^8.1.0", + "chalk": "^2.4.2", + "debug": "^4.1.1", + "lodash.clonedeep": "^4.5.0", + "semver": "^6.3.0", + "table": "^6.8.0", + "undici": "^5.14.0" + }, + "peerDependencies": { + "hardhat": "^2.0.4" + } + }, + "node_modules/@nomicfoundation/hardhat-verify/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, + "peer": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@nomicfoundation/hardhat-verify/node_modules/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, + "peer": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@nomicfoundation/hardhat-verify/node_modules/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, + "peer": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@nomicfoundation/hardhat-verify/node_modules/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, + "peer": true + }, + "node_modules/@nomicfoundation/hardhat-verify/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, + "peer": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@nomicfoundation/hardhat-verify/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, + "peer": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@nomicfoundation/hardhat-verify/node_modules/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, + "peer": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@nomicfoundation/ignition-core": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/@nomicfoundation/ignition-core/-/ignition-core-0.15.0.tgz", + "integrity": "sha512-d/h8jgJHY4xIroHqdaGeTkTqjQeuzmU759AOn1Fg88cuxVhS7JM22ZI0bQWyLNSMsVstHBIo+lSMIsvm9jBF2w==", + "dev": true, + "peer": true, + "dependencies": { + "@ethersproject/address": "5.6.1", + "cbor": "^9.0.0", + "debug": "^4.3.2", + "ethers": "^6.7.0", + "fs-extra": "^10.0.0", + "immer": "10.0.2", + "lodash": "4.17.21", + "ndjson": "2.0.0" + } + }, + "node_modules/@nomicfoundation/ignition-core/node_modules/@ethersproject/address": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.6.1.tgz", + "integrity": "sha512-uOgF0kS5MJv9ZvCz7x6T2EXJSzotiybApn4XlOgoTX0xdtyVIJ7pF+6cGPxiEq/dpBiTfMiw7Yc81JcwhSYA0Q==", + "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" + } + ], + "peer": true, + "dependencies": { + "@ethersproject/bignumber": "^5.6.2", + "@ethersproject/bytes": "^5.6.1", + "@ethersproject/keccak256": "^5.6.1", + "@ethersproject/logger": "^5.6.0", + "@ethersproject/rlp": "^5.6.1" + } + }, + "node_modules/@nomicfoundation/ignition-core/node_modules/cbor": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/cbor/-/cbor-9.0.2.tgz", + "integrity": "sha512-JPypkxsB10s9QOWwa6zwPzqE1Md3vqpPc+cai4sAecuCsRyAtAl/pMyhPlMbT/xtPnm2dznJZYRLui57qiRhaQ==", + "dev": true, + "peer": true, + "dependencies": { + "nofilter": "^3.1.0" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@nomicfoundation/ignition-ui": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/@nomicfoundation/ignition-ui/-/ignition-ui-0.15.0.tgz", + "integrity": "sha512-RBvvQ0e8RcEc/LoSzNTPVKZZ5vEwlmxt7PXG278+6DqCrOqxqmh6W9PtK/4mwwvnTeBqds+8j81jDf6vJbOVBQ==", + "dev": true, + "peer": true + }, + "node_modules/@nomicfoundation/solidity-analyzer": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer/-/solidity-analyzer-0.1.1.tgz", + "integrity": "sha512-1LMtXj1puAxyFusBgUIy5pZk3073cNXYnXUpuNKFghHbIit/xZgbk0AokpUADbNm3gyD6bFWl3LRFh3dhVdREg==", + "dev": true, + "engines": { + "node": ">= 12" + }, "optionalDependencies": { "@nomicfoundation/solidity-analyzer-darwin-arm64": "0.1.1", "@nomicfoundation/solidity-analyzer-darwin-x64": "0.1.1", @@ -1171,6 +1604,7 @@ "cpu": [ "arm64" ], + "dev": true, "optional": true, "os": [ "darwin" @@ -1186,6 +1620,7 @@ "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "darwin" @@ -1201,6 +1636,7 @@ "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "freebsd" @@ -1216,6 +1652,7 @@ "cpu": [ "arm64" ], + "dev": true, "optional": true, "os": [ "linux" @@ -1231,6 +1668,7 @@ "cpu": [ "arm64" ], + "dev": true, "optional": true, "os": [ "linux" @@ -1246,6 +1684,7 @@ "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "linux" @@ -1261,6 +1700,7 @@ "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "linux" @@ -1276,6 +1716,7 @@ "cpu": [ "arm64" ], + "dev": true, "optional": true, "os": [ "win32" @@ -1291,6 +1732,7 @@ "cpu": [ "ia32" ], + "dev": true, "optional": true, "os": [ "win32" @@ -1306,6 +1748,7 @@ "cpu": [ "x64" ], + "dev": true, "optional": true, "os": [ "win32" @@ -1314,79 +1757,83 @@ "node": ">= 10" } }, - "node_modules/@nomiclabs/hardhat-ethers": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/@nomiclabs/hardhat-ethers/-/hardhat-ethers-2.2.3.tgz", - "integrity": "sha512-YhzPdzb612X591FOe68q+qXVXGG2ANZRvDo0RRUtimev85rCrAlv/TLMEZw5c+kq9AbzocLTVX/h2jVIFPL9Xg==", - "dev": true, - "peerDependencies": { - "ethers": "^5.0.0", - "hardhat": "^2.0.0" - } + "node_modules/@openzeppelin/contracts": { + "version": "4.9.6", + "resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-4.9.6.tgz", + "integrity": "sha512-xSmezSupL+y9VkHZJGDoCBpmnB2ogM13ccaYDWqJTfS3dbuHkgjuwDFUmaFauBCboQMGB/S5UqUl2y54X99BmA==", + "dev": true }, - "node_modules/@nomiclabs/hardhat-etherscan": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/@nomiclabs/hardhat-etherscan/-/hardhat-etherscan-3.1.7.tgz", - "integrity": "sha512-tZ3TvSgpvsQ6B6OGmo1/Au6u8BrAkvs1mIC/eURA3xgIfznUZBhmpne8hv7BXUzw9xNL3fXdpOYgOQlVMTcoHQ==", - "dev": true, - "dependencies": { - "@ethersproject/abi": "^5.1.2", - "@ethersproject/address": "^5.0.2", - "cbor": "^8.1.0", - "chalk": "^2.4.2", - "debug": "^4.1.1", - "fs-extra": "^7.0.1", - "lodash": "^4.17.11", - "semver": "^6.3.0", - "table": "^6.8.0", - "undici": "^5.14.0" - }, - "peerDependencies": { - "hardhat": "^2.0.4" - } + "node_modules/@openzeppelin/contracts-upgradeable": { + "version": "4.9.6", + "resolved": "https://registry.npmjs.org/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-4.9.6.tgz", + "integrity": "sha512-m4iHazOsOCv1DgM7eD7GupTJ+NFVujRZt1wzddDPSVGpWdKq1SKkla5htKG7+IS4d2XOCtzkUNwRZ7Vq5aEUMA==", + "dev": true }, - "node_modules/@nomiclabs/hardhat-etherscan/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "node_modules/@openzeppelin/defender-admin-client": { + "version": "1.54.1", + "resolved": "https://registry.npmjs.org/@openzeppelin/defender-admin-client/-/defender-admin-client-1.54.1.tgz", + "integrity": "sha512-kRpSUdTsnSqntp4FOXIm95t+6VKHc8CUY2Si71VDuxs0q7HSPZkdpRPSntcolwEzWy9L4a8NS/QMwDF5NJ4X1g==", "dev": true, "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" + "@openzeppelin/defender-base-client": "1.54.1", + "axios": "^1.4.0", + "ethers": "^5.7.2", + "lodash": "^4.17.19", + "node-fetch": "^2.6.0" } }, - "node_modules/@nomiclabs/hardhat-etherscan/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "node_modules/@openzeppelin/defender-admin-client/node_modules/ethers": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.7.2.tgz", + "integrity": "sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg==", "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" + } + ], "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" + "@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/@openzeppelin/contracts": { - "version": "4.9.2", - "resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-4.9.2.tgz", - "integrity": "sha512-mO+y6JaqXjWeMh9glYVzVu8HYPGknAAnWyxTRhGeckOruyXQMNnlcW6w/Dx9ftLeIQk6N+ZJFuVmTwF7lEIFrg==", - "dev": true - }, - "node_modules/@openzeppelin/contracts-upgradeable": { - "version": "4.9.2", - "resolved": "https://registry.npmjs.org/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-4.9.2.tgz", - "integrity": "sha512-siviV3PZV/fHfPaoIC51rf1Jb6iElkYWnNYZ0leO23/ukXuvOyoC/ahy8jqiV7g+++9Nuo3n/rk5ajSN/+d/Sg==", - "dev": true - }, "node_modules/@openzeppelin/defender-base-client": { - "version": "1.47.0", - "resolved": "https://registry.npmjs.org/@openzeppelin/defender-base-client/-/defender-base-client-1.47.0.tgz", - "integrity": "sha512-y9dDm+gX0MHHEn17W7f7oO3X083JAVMk3YcuXHavSE7kjiCLoFOaZ23joYqoHeaccL10nGt7KOOzZ0sh9iJHTQ==", + "version": "1.54.1", + "resolved": "https://registry.npmjs.org/@openzeppelin/defender-base-client/-/defender-base-client-1.54.1.tgz", + "integrity": "sha512-DRGz/7KN3ZQwu28YWMOaojrC7jjPkz/uCwkC8/C8B11qwZhA5qIVvyhYHhhFOCl0J84+E3TNdvkPD2q3p2WaJw==", "dev": true, "dependencies": { "amazon-cognito-identity-js": "^6.0.1", @@ -1396,121 +1843,176 @@ "node-fetch": "^2.6.0" } }, + "node_modules/@openzeppelin/defender-sdk-base-client": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@openzeppelin/defender-sdk-base-client/-/defender-sdk-base-client-1.11.0.tgz", + "integrity": "sha512-HNcbRhbcMZZM5Ri5IfUwJaiJZGIrc0yboRZRlXJfG2aFS/EMfUFnQHC0tyyXtCOAoAZcn+iMlsSj5h8CoUeCfw==", + "dev": true, + "dependencies": { + "amazon-cognito-identity-js": "^6.3.6", + "async-retry": "^1.3.3" + } + }, + "node_modules/@openzeppelin/defender-sdk-deploy-client": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@openzeppelin/defender-sdk-deploy-client/-/defender-sdk-deploy-client-1.11.0.tgz", + "integrity": "sha512-ELYVihsrTOlH7Sy5C/+Yf64hV3ICeTY2OcczOWVQ/o6rHBWKSnHSZCE/oB1cfOpyg/gCrCLXozs4NyrS5z3GUw==", + "dev": true, + "dependencies": { + "@openzeppelin/defender-sdk-base-client": "^1.11.0", + "axios": "^1.6.7", + "lodash": "^4.17.21" + } + }, + "node_modules/@openzeppelin/defender-sdk-network-client": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/@openzeppelin/defender-sdk-network-client/-/defender-sdk-network-client-1.11.0.tgz", + "integrity": "sha512-CPy1TA6RyFYtACbvXZJhJpsYW2u4yxTSNU8cVIw1lH/9iArXzfWuJ2p8Deidc0sJBbMeJYkv1AvqTBJNifjKMg==", + "dev": true, + "dependencies": { + "@openzeppelin/defender-sdk-base-client": "^1.11.0", + "axios": "^1.6.7", + "lodash": "^4.17.21" + } + }, "node_modules/@openzeppelin/hardhat-upgrades": { - "version": "1.28.0", - "resolved": "https://registry.npmjs.org/@openzeppelin/hardhat-upgrades/-/hardhat-upgrades-1.28.0.tgz", - "integrity": "sha512-7sb/Jf+X+uIufOBnmHR0FJVWuxEs2lpxjJnLNN6eCJCP8nD0v+Ot5lTOW2Qb/GFnh+fLvJtEkhkowz4ZQ57+zQ==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@openzeppelin/hardhat-upgrades/-/hardhat-upgrades-3.0.5.tgz", + "integrity": "sha512-7Klg1B6fH45+7Zxzr6d9mLqudrL9Uk6CUG5AeG5NckPfP4ZlQRo1squcQ8yJPwqDS8rQjfChiqKDelp4LTjyZQ==", "dev": true, "dependencies": { - "@openzeppelin/defender-base-client": "^1.46.0", - "@openzeppelin/platform-deploy-client": "^0.8.0", - "@openzeppelin/upgrades-core": "^1.27.0", + "@openzeppelin/defender-admin-client": "^1.52.0", + "@openzeppelin/defender-base-client": "^1.52.0", + "@openzeppelin/defender-sdk-base-client": "^1.10.0", + "@openzeppelin/defender-sdk-deploy-client": "^1.10.0", + "@openzeppelin/defender-sdk-network-client": "^1.10.0", + "@openzeppelin/upgrades-core": "^1.32.0", "chalk": "^4.1.0", "debug": "^4.1.1", - "proper-lockfile": "^4.1.1" + "ethereumjs-util": "^7.1.5", + "proper-lockfile": "^4.1.1", + "undici": "^6.0.0" }, "bin": { "migrate-oz-cli-project": "dist/scripts/migrate-oz-cli-project.js" }, "peerDependencies": { - "@nomiclabs/hardhat-ethers": "^2.0.0", - "@nomiclabs/hardhat-etherscan": "^3.1.0", - "ethers": "^5.0.5", + "@nomicfoundation/hardhat-ethers": "^3.0.0", + "@nomicfoundation/hardhat-verify": "^2.0.0", + "ethers": "^6.6.0", "hardhat": "^2.0.2" }, "peerDependenciesMeta": { - "@nomiclabs/harhdat-etherscan": { + "@nomicfoundation/hardhat-verify": { "optional": true } } }, - "node_modules/@openzeppelin/platform-deploy-client": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@openzeppelin/platform-deploy-client/-/platform-deploy-client-0.8.0.tgz", - "integrity": "sha512-POx3AsnKwKSV/ZLOU/gheksj0Lq7Is1q2F3pKmcFjGZiibf+4kjGxr4eSMrT+2qgKYZQH1ZLQZ+SkbguD8fTvA==", - "dev": true, - "dependencies": { - "@ethersproject/abi": "^5.6.3", - "@openzeppelin/defender-base-client": "^1.46.0", - "axios": "^0.21.2", - "lodash": "^4.17.19", - "node-fetch": "^2.6.0" - } - }, - "node_modules/@openzeppelin/platform-deploy-client/node_modules/axios": { - "version": "0.21.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", - "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", + "node_modules/@openzeppelin/hardhat-upgrades/node_modules/undici": { + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.10.2.tgz", + "integrity": "sha512-HcVuBy7ACaDejIMdwCzAvO22OsiE6ir6ziTIr9kAE0vB+PheVe29ZvRN8p7FXCO2uZHTjEoUs5bPiFpuc/hwwQ==", "dev": true, - "dependencies": { - "follow-redirects": "^1.14.0" + "engines": { + "node": ">=18.0" } }, "node_modules/@openzeppelin/upgrades-core": { - "version": "1.27.3", - "resolved": "https://registry.npmjs.org/@openzeppelin/upgrades-core/-/upgrades-core-1.27.3.tgz", - "integrity": "sha512-IqlSMUkno1XKF4L46aUqZ4BqHxj4dF0BRGrFcKeG2Q0vrsKoazhY67JG9bO+wMYG4zxl6jgmG0bd5ef9HLcLmw==", + "version": "1.32.5", + "resolved": "https://registry.npmjs.org/@openzeppelin/upgrades-core/-/upgrades-core-1.32.5.tgz", + "integrity": "sha512-R0wprsyJ4xWiRW05kaTfZZkRVpG2g0af3/hpjE7t2mX0Eb2n40MQLokTwqIk4LDzpp910JfLSpB0vBuZ6WNPog==", "dev": true, "dependencies": { - "cbor": "^8.0.0", + "cbor": "^9.0.0", "chalk": "^4.1.0", "compare-versions": "^6.0.0", "debug": "^4.1.1", "ethereumjs-util": "^7.0.3", "minimist": "^1.2.7", "proper-lockfile": "^4.1.1", - "solidity-ast": "^0.4.15" + "solidity-ast": "^0.4.51" }, "bin": { "openzeppelin-upgrades-core": "dist/cli/cli.js" } }, + "node_modules/@openzeppelin/upgrades-core/node_modules/cbor": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/cbor/-/cbor-9.0.2.tgz", + "integrity": "sha512-JPypkxsB10s9QOWwa6zwPzqE1Md3vqpPc+cai4sAecuCsRyAtAl/pMyhPlMbT/xtPnm2dznJZYRLui57qiRhaQ==", + "dev": true, + "dependencies": { + "nofilter": "^3.1.0" + }, + "engines": { + "node": ">=16" + } + }, "node_modules/@scure/base": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.1.tgz", - "integrity": "sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA==", - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ] + "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==", + "dev": true, + "funding": { + "url": "https://paulmillr.com/funding/" + } }, "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/" - } - ], + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.3.3.tgz", + "integrity": "sha512-LJaN3HwRbfQK0X1xFSi0Q9amqOgzQnnDngIt+ZlsBC3Bm7/nE7K0kwshZHyaru79yIVRv/e1mQAjZyuZG6jOFQ==", + "dev": true, "dependencies": { - "@noble/hashes": "~1.2.0", - "@noble/secp256k1": "~1.7.0", - "@scure/base": "~1.1.0" + "@noble/curves": "~1.3.0", + "@noble/hashes": "~1.3.2", + "@scure/base": "~1.1.4" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip32/node_modules/@noble/curves": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.3.0.tgz", + "integrity": "sha512-t01iSXPuN+Eqzb4eBX0S5oubSqXbK/xXa1Ne18Hj8f9pStxztHCE2gfboSp/dZRLSqfuLpRK2nDXDK+W9puocA==", + "dev": true, + "dependencies": { + "@noble/hashes": "1.3.3" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip32/node_modules/@noble/hashes": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.3.tgz", + "integrity": "sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA==", + "dev": true, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" } }, "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": "individual", - "url": "https://paulmillr.com/funding/" - } - ], + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.2.2.tgz", + "integrity": "sha512-HYf9TUXG80beW+hGAt3TRM8wU6pQoYur9iNypTROm42dorCGmLnFe3eWjz3gOq6G62H2WRh0FCzAR1PI+29zIA==", + "dev": true, "dependencies": { - "@noble/hashes": "~1.2.0", - "@scure/base": "~1.1.0" + "@noble/hashes": "~1.3.2", + "@scure/base": "~1.1.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==", + "dev": true, "dependencies": { "@sentry/hub": "5.30.0", "@sentry/minimal": "5.30.0", @@ -1526,6 +2028,7 @@ "version": "5.30.0", "resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-5.30.0.tgz", "integrity": "sha512-2tYrGnzb1gKz2EkMDQcfLrDTvmGcQPuWxLnJKXJvYTQDGLlEvi2tWz1VIHjunmOvJrB5aIQLhm+dcMRwFZDCqQ==", + "dev": true, "dependencies": { "@sentry/types": "5.30.0", "@sentry/utils": "5.30.0", @@ -1539,6 +2042,7 @@ "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==", + "dev": true, "dependencies": { "@sentry/hub": "5.30.0", "@sentry/types": "5.30.0", @@ -1552,6 +2056,7 @@ "version": "5.30.0", "resolved": "https://registry.npmjs.org/@sentry/node/-/node-5.30.0.tgz", "integrity": "sha512-Br5oyVBF0fZo6ZS9bxbJZG4ApAjRqAnqFFurMVJJdunNb80brh7a5Qva2kjhm+U6r9NJAB5OmDyPkA1Qnt+QVg==", + "dev": true, "dependencies": { "@sentry/core": "5.30.0", "@sentry/hub": "5.30.0", @@ -1571,6 +2076,7 @@ "version": "5.30.0", "resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-5.30.0.tgz", "integrity": "sha512-dUFowCr0AIMwiLD7Fs314Mdzcug+gBVo/+NCMyDw8tFxJkwWAKl7Qa2OZxLQ0ZHjakcj1hNKfCQJ9rhyfOl4Aw==", + "dev": true, "dependencies": { "@sentry/hub": "5.30.0", "@sentry/minimal": "5.30.0", @@ -1586,6 +2092,7 @@ "version": "5.30.0", "resolved": "https://registry.npmjs.org/@sentry/types/-/types-5.30.0.tgz", "integrity": "sha512-R8xOqlSTZ+htqrfteCWU5Nk0CDN5ApUTvrlvBuiH1DyP6czDZ4ktbZB0hAgBlVcK0U+qpD3ag3Tqqpa5Q67rPw==", + "dev": true, "engines": { "node": ">=6" } @@ -1594,6 +2101,7 @@ "version": "5.30.0", "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-5.30.0.tgz", "integrity": "sha512-zaYmoH0NWWtvnJjC9/CBseXMtKHm/tm40sz3YfJRxeQjyzRqNQPgivpd9R/oDJCYj999mzdW382p/qi2ypjLww==", + "dev": true, "dependencies": { "@sentry/types": "5.30.0", "tslib": "^1.9.3" @@ -1603,21 +2111,21 @@ } }, "node_modules/@smithy/types": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-1.1.0.tgz", - "integrity": "sha512-KzmvisMmuwD2jZXuC9e65JrgsZM97y5NpDU7g347oB+Q+xQLU6hQZ5zFNNbEfwwOJHoOvEVTna+dk1h/lW7alw==", + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-2.12.0.tgz", + "integrity": "sha512-QwYgloJ0sVNBeBuBs65cIkTbfzV/Q6ZNPCJ99EICFEdJYG50nGIY/uYXp+TbsdJReIuPr0a0kXmCvren3MbRRw==", "dev": true, "dependencies": { - "tslib": "^2.5.0" + "tslib": "^2.6.2" }, "engines": { "node": ">=14.0.0" } }, "node_modules/@smithy/types/node_modules/tslib": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", - "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", "dev": true }, "node_modules/@solidity-parser/parser": { @@ -1625,66 +2133,63 @@ "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.14.5.tgz", "integrity": "sha512-6dKnHZn7fg/iQATVEzqyUOyEidbn05q7YA2mQ9hC0MMXhhV3/JrsxmFSYZAcr7j1yUP700LLhTruvJ3MiQmjJg==", "dev": true, + "peer": true, "dependencies": { "antlr4ts": "^0.5.0-alpha.4" } }, "node_modules/@tsconfig/node10": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", - "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", - "devOptional": true + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", + "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==", + "dev": true }, "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==", - "devOptional": true + "dev": true }, "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==", - "devOptional": true + "dev": true }, "node_modules/@tsconfig/node16": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", - "devOptional": true + "dev": true }, - "node_modules/@typechain/ethers-v5": { - "version": "10.2.1", - "resolved": "https://registry.npmjs.org/@typechain/ethers-v5/-/ethers-v5-10.2.1.tgz", - "integrity": "sha512-n3tQmCZjRE6IU4h6lqUGiQ1j866n5MTCBJreNEHHVWXa2u9GJTaeYyU1/k+1qLutkyw+sS6VAN+AbeiTqsxd/A==", + "node_modules/@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, "dependencies": { "lodash": "^4.17.15", "ts-essentials": "^7.0.1" }, "peerDependencies": { - "@ethersproject/abi": "^5.0.0", - "@ethersproject/providers": "^5.0.0", - "ethers": "^5.1.3", - "typechain": "^8.1.1", - "typescript": ">=4.3.0" + "ethers": "6.x", + "typechain": "^8.3.2", + "typescript": ">=4.7.0" } }, "node_modules/@typechain/hardhat": { - "version": "6.1.6", - "resolved": "https://registry.npmjs.org/@typechain/hardhat/-/hardhat-6.1.6.tgz", - "integrity": "sha512-BiVnegSs+ZHVymyidtK472syodx1sXYlYJJixZfRstHVGYTi8V1O7QG4nsjyb0PC/LORcq7sfBUcHto1y6UgJA==", + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/@typechain/hardhat/-/hardhat-9.1.0.tgz", + "integrity": "sha512-mtaUlzLlkqTlfPwB3FORdejqBskSnh+Jl8AIJGjXNAQfRQ4ofHADPl1+oU7Z3pAJzmZbUXII8MhOLQltcHgKnA==", "dev": true, "dependencies": { "fs-extra": "^9.1.0" }, "peerDependencies": { - "@ethersproject/abi": "^5.4.7", - "@ethersproject/providers": "^5.4.7", - "@typechain/ethers-v5": "^10.2.1", - "ethers": "^5.4.7", + "@typechain/ethers-v6": "^0.5.1", + "ethers": "^6.1.0", "hardhat": "^2.9.9", - "typechain": "^8.1.1" + "typechain": "^8.3.2" } }, "node_modules/@typechain/hardhat/node_modules/fs-extra": { @@ -1702,51 +2207,27 @@ "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/async-eventemitter": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/@types/async-eventemitter/-/async-eventemitter-0.2.1.tgz", - "integrity": "sha512-M2P4Ng26QbAeITiH7w1d7OxtldgfAe0wobpyJzVK/XOb0cUGKU2R4pfAhqcJBXAe2ife5ZOhSv4wk7p+ffURtg==" - }, "node_modules/@types/bn.js": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.1.tgz", - "integrity": "sha512-qNrYbZqMx0uJAfKnKclPh+dTwK33KfLHYqtyODwd5HnXOjnkhc4qgn3BrK6RWyGZm5+sIFE7Q7Vz6QQtJB7w7g==", + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.5.tgz", + "integrity": "sha512-V46N0zwKRF5Q00AZ6hWtN0T8gGmDUaUzLWQvHFo5yThtVwK/VCenFY3wXVbOvNfajEpsTfQM4IN9k/d6gUVX3A==", + "dev": true, "dependencies": { "@types/node": "*" } }, "node_modules/@types/chai": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.5.tgz", - "integrity": "sha512-mEo1sAde+UCE6b2hxn332f1g1E8WfYRu6p5SvTKr2ZKC1f7gFJXk4h5PyGP9Dt6gCaG8y8XhwnXWC6Iy2cmBng==", + "version": "4.3.14", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.14.tgz", + "integrity": "sha512-Wj71sXE4Q4AkGdG9Tvq1u/fquNz9EdG4LIJMwVVII7ashjD/8cf8fyIfJAjRr6YcsXnSE8cOGQPq1gqeR8z+3w==", "dev": true }, "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, + "peer": true, "dependencies": { "@types/chai": "*" } @@ -1756,25 +2237,37 @@ "resolved": "https://registry.npmjs.org/@types/concat-stream/-/concat-stream-1.6.1.tgz", "integrity": "sha512-eHE4cQPoj6ngxBZMvVf6Hw7Mh4jMW4U9lpGmS5GBPB9RYxlFg+CHaVN7ErNY4W9XfLIEn20b4VDYaIrbq0q4uA==", "dev": true, + "peer": true, "dependencies": { "@types/node": "*" } }, + "node_modules/@types/debug": { + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", + "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", + "dev": true, + "dependencies": { + "@types/ms": "*" + } + }, "node_modules/@types/form-data": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/@types/form-data/-/form-data-0.0.33.tgz", "integrity": "sha512-8BSvG1kGm83cyJITQMZSulnl6QV8jqAGreJsc5tPu1Jq0vTSOiY/k24Wx82JRpWwZSqrala6sd5rWi6aNXvqcw==", "dev": true, + "peer": true, "dependencies": { "@types/node": "*" } }, "node_modules/@types/fs-extra": { - "version": "9.0.13", - "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.13.tgz", - "integrity": "sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==", + "version": "11.0.4", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-11.0.4.tgz", + "integrity": "sha512-yTbItCNreRooED33qjunPthRcSjERP1r4MqCZc7wv0u2sUkzTFp45tgUfS5+r7FrZPdmCCNflLhVSP/o+SemsQ==", "dev": true, "dependencies": { + "@types/jsonfile": "*", "@types/node": "*" } }, @@ -1788,16 +2281,26 @@ "@types/node": "*" } }, + "node_modules/@types/jsonfile": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/@types/jsonfile/-/jsonfile-6.1.4.tgz", + "integrity": "sha512-D5qGUYwjvnNNextdU59/+fI+spnwtTFmyQP0h+PfIOSkNfpU6AOICUOkm4i0OnSk+NyjdPJrxCDro0sJsWlRpQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/lodash": { - "version": "4.14.195", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.195.tgz", - "integrity": "sha512-Hwx9EUgdwf2GLarOjQp5ZH8ZmblzcbTBC2wtQWNKARBSxM9ezRIAUpeDTgoQRAFB0+8CNWXVA9+MaSOzOF3nPg==", + "version": "4.17.0", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.0.tgz", + "integrity": "sha512-t7dhREVv6dbNj0q17X12j7yDG4bD/DHYX7o5/DbDxobP0HnGPgpRz2Ej77aL7TZT3DSw13fqUTj8J4mMnqa7WA==", "dev": true }, "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==", + "dev": true }, "node_modules/@types/minimatch": { "version": "5.1.2", @@ -1806,20 +2309,31 @@ "dev": true }, "node_modules/@types/mocha": { - "version": "9.1.1", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-9.1.1.tgz", - "integrity": "sha512-Z61JK7DKDtdKTWwLeElSEBcWGRLY8g95ic5FoQqI9CMx0ns/Ghep3B4DfcEimiKMvtamNVULVNKEsiwV3aQmXw==", + "version": "10.0.6", + "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.6.tgz", + "integrity": "sha512-dJvrYWxP/UcXm36Qn36fxhUKu8A/xMRXVT2cliFF1Z7UA9liG5Psj3ezNSZw+5puH2czDXRLcXQxf8JbJt0ejg==", + "dev": true + }, + "node_modules/@types/ms": { + "version": "0.7.34", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.34.tgz", + "integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==", "dev": true }, "node_modules/@types/node": { - "version": "18.16.19", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.16.19.tgz", - "integrity": "sha512-IXl7o+R9iti9eBW4Wg2hx1xQDig183jj7YLn8F7udNceyfkbn1ZxmzZXuak20gR40D7pIkIY1kYGx5VIGbaHKA==" + "version": "20.12.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.2.tgz", + "integrity": "sha512-zQ0NYO87hyN6Xrclcqp7f8ZbXNbRfoGWNcMvHTPQp9UUrwI0mI7XBz+cu7/W6/VClYo2g63B0cjull/srU7LgQ==", + "dev": true, + "dependencies": { + "undici-types": "~5.26.4" + } }, "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, "dependencies": { "@types/node": "*" } @@ -1831,15 +2345,33 @@ "dev": true }, "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==", + "version": "6.9.14", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.14.tgz", + "integrity": "sha512-5khscbd3SwWMhFqylJBLQ0zIu7c1K6Vz0uBIt915BI3zV0q1nfjRQD3RqSBcPaO6PHEF4ov/t9y89fSiyThlPA==", + "dev": true, + "peer": true + }, + "node_modules/@types/readable-stream": { + "version": "2.3.15", + "resolved": "https://registry.npmjs.org/@types/readable-stream/-/readable-stream-2.3.15.tgz", + "integrity": "sha512-oM5JSKQCcICF1wvGgmecmHldZ48OZamtMxcGGVICOJA8o8cahXC1zEVAif8iwoc5j8etxFaRFnf095+CDsuoFQ==", + "dev": true, + "dependencies": { + "@types/node": "*", + "safe-buffer": "~5.1.1" + } + }, + "node_modules/@types/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true }, "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, "dependencies": { "@types/node": "*" } @@ -1850,62 +2382,11 @@ "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==", - "dependencies": { - "event-target-shim": "^5.0.0" - }, - "engines": { - "node": ">=6.5" - } - }, - "node_modules/abstract-level": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/abstract-level/-/abstract-level-1.0.3.tgz", - "integrity": "sha512-t6jv+xHy+VYwc4xqZMn2Pa9DjcdzvzZmQGRjTFc8spIbRGHgBrEKbPq+rYXc7CCo0lxgYvSgKVg9qZAhpVQSjA==", - "dependencies": { - "buffer": "^6.0.3", - "catering": "^2.1.0", - "is-buffer": "^2.0.5", - "level-supports": "^4.0.0", - "level-transcoder": "^1.0.1", - "module-error": "^1.0.1", - "queue-microtask": "^1.2.3" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/abstract-level/node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" - } - }, "node_modules/acorn": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", - "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", - "devOptional": true, + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", + "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", + "dev": true, "bin": { "acorn": "bin/acorn" }, @@ -1914,40 +2395,34 @@ } }, "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==", - "devOptional": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/address": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/address/-/address-1.2.2.tgz", - "integrity": "sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==", + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", + "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==", "dev": true, "engines": { - "node": ">= 10.0.0" + "node": ">=0.4.0" } }, "node_modules/adm-zip": { "version": "0.4.16", "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.16.tgz", "integrity": "sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg==", + "dev": true, "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==", + "dev": true }, "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==", + "dev": true, "dependencies": { "debug": "4" }, @@ -1959,6 +2434,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "dev": true, "dependencies": { "clean-stack": "^2.0.0", "indent-string": "^4.0.0" @@ -1968,14 +2444,15 @@ } }, "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", "dev": true, + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", "uri-js": "^4.2.2" }, "funding": { @@ -1984,9 +2461,9 @@ } }, "node_modules/amazon-cognito-identity-js": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/amazon-cognito-identity-js/-/amazon-cognito-identity-js-6.3.1.tgz", - "integrity": "sha512-PxBdufgS8uZShrcIFAsRjmqNXsh/4fXOWUGQOUhKLHWWK1pcp/y+VeFF48avXIWefM8XwsT3JlN6m9J2eHt4LA==", + "version": "6.3.12", + "resolved": "https://registry.npmjs.org/amazon-cognito-identity-js/-/amazon-cognito-identity-js-6.3.12.tgz", + "integrity": "sha512-s7NKDZgx336cp+oDeUtB2ZzT8jWJp/v2LWuYl+LQtMEODe22RF1IJ4nRiDATp+rp1pTffCZcm44Quw4jx2bqNg==", "dev": true, "dependencies": { "@aws-crypto/sha256-js": "1.2.2", @@ -2006,10 +2483,20 @@ "node": ">=0.4.2" } }, + "node_modules/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==", + "dev": true, + "dependencies": { + "string-width": "^4.1.0" + } + }, "node_modules/ansi-colors": { "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==", + "dev": true, "engines": { "node": ">=6" } @@ -2018,6 +2505,7 @@ "version": "4.3.2", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, "dependencies": { "type-fest": "^0.21.3" }, @@ -2032,31 +2520,38 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, "engines": { "node": ">=8" } }, "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==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, "dependencies": { - "color-convert": "^1.9.0" + "color-convert": "^2.0.1" }, "engines": { - "node": ">=4" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, "node_modules/antlr4ts": { "version": "0.5.0-alpha.4", "resolved": "https://registry.npmjs.org/antlr4ts/-/antlr4ts-0.5.0-alpha.4.tgz", "integrity": "sha512-WPQDt1B74OfPv/IMS2ekXAKkTZIHl88uMetg6q3OTqgFxZ/dxDXI0EWLyZid/1Pe6hTftyg5N7gel5wNAGxXyQ==", - "dev": true + "dev": true, + "peer": true }, "node_modules/anymatch": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -2069,12 +2564,13 @@ "version": "4.1.3", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "devOptional": true + "dev": true }, "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==", + "dev": true }, "node_modules/array-back": { "version": "3.1.0", @@ -2086,13 +2582,16 @@ } }, "node_modules/array-buffer-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", - "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "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, "dependencies": { - "call-bind": "^1.0.2", - "is-array-buffer": "^3.0.1" + "call-bind": "^1.0.5", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -2112,21 +2611,23 @@ "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", "integrity": "sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==", "dev": true, + "peer": true, "engines": { "node": ">=0.10.0" } }, - "node_modules/array.prototype.reduce": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/array.prototype.reduce/-/array.prototype.reduce-1.0.5.tgz", - "integrity": "sha512-kDdugMl7id9COE8R7MHF5jWk7Dqt/fs4Pv+JXoICnYwqpjjjbUurz6w5fT5IG6brLdJhv6/VoHB0H7oyIBXd+Q==", + "node_modules/array.prototype.findlast": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", + "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "es-array-method-boxes-properly": "^1.0.0", - "is-string": "^1.0.7" + "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" }, "engines": { "node": ">= 0.4" @@ -2135,29 +2636,34 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/asap": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", - "dev": true - }, - "node_modules/asn1": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", - "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "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==", "dev": true, "dependencies": { - "safer-buffer": "~2.1.0" + "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" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", + "node_modules/asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", "dev": true, - "engines": { - "node": ">=0.8" - } + "peer": true }, "node_modules/assertion-error": { "version": "1.1.0", @@ -2174,25 +2680,16 @@ "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", "dev": true, + "peer": true, "engines": { "node": ">=8" } }, "node_modules/async": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", - "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", - "dependencies": { - "lodash": "^4.17.14" - } - }, - "node_modules/async-eventemitter": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/async-eventemitter/-/async-eventemitter-0.2.4.tgz", - "integrity": "sha512-pd20BwL7Yt1zwDFy+8MX8F1+WCT8aQeKj0kQnTrH9WaeRETlRamVhD0JtRPmrV4GfOJ2F9CvdQkZeZhnh2TuHw==", - "dependencies": { - "async": "^2.4.0" - } + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha512-nSVgobk4rv61R9PUSDtYt7mPVB2olxNR5RWJcAsH676/ef11bUZwvu7+RGYrYauVdDPcO519v68wRhXQtxsV9w==", + "dev": true }, "node_modules/async-retry": { "version": "1.3.3", @@ -2219,10 +2716,13 @@ } }, "node_modules/available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "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, + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, "engines": { "node": ">= 0.4" }, @@ -2230,28 +2730,13 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/aws4": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.12.0.tgz", - "integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg==", - "dev": true - }, "node_modules/axios": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.4.0.tgz", - "integrity": "sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==", + "version": "1.6.8", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.8.tgz", + "integrity": "sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ==", "dev": true, "dependencies": { - "follow-redirects": "^1.15.0", + "follow-redirects": "^1.15.6", "form-data": "^4.0.0", "proxy-from-env": "^1.1.0" } @@ -2259,12 +2744,14 @@ "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==", + "dev": true }, "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==", + "dev": true, "dependencies": { "safe-buffer": "^5.0.1" } @@ -2273,6 +2760,7 @@ "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", @@ -2288,56 +2776,84 @@ } ] }, - "node_modules/bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", - "dev": true, - "dependencies": { - "tweetnacl": "^0.14.3" - } - }, - "node_modules/bcrypt-pbkdf/node_modules/tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", - "dev": true - }, "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==", + "dev": true }, "node_modules/bigint-crypto-utils": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/bigint-crypto-utils/-/bigint-crypto-utils-3.3.0.tgz", "integrity": "sha512-jOTSb+drvEDxEq6OuUybOAv/xxoh3cuYRUIPyu8sSHQNKM303UQ2R1DAo45o1AkcIXw6fzbaFI1+xGGdaXs2lg==", + "dev": true, "engines": { "node": ">=14.0.0" } }, "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==", + "dev": true, "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 }, "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==", + "dev": true + }, + "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==", + "dev": true, + "dependencies": { + "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" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/boxen/node_modules/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==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, "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, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -2347,6 +2863,7 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, "dependencies": { "fill-range": "^7.0.1" }, @@ -2357,28 +2874,20 @@ "node_modules/brorand": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==" - }, - "node_modules/browser-level": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/browser-level/-/browser-level-1.0.1.tgz", - "integrity": "sha512-XECYKJ+Dbzw0lbydyQuJzwNXtOpbMSq737qxJN11sIRTErOMShvDpbzTlgju7orJKvx4epULolZAuJGLzCmWRQ==", - "dependencies": { - "abstract-level": "^1.0.2", - "catering": "^2.1.1", - "module-error": "^1.0.2", - "run-parallel-limit": "^1.1.0" - } + "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==", + "dev": true }, "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==", + "dev": true }, "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, "dependencies": { "buffer-xor": "^1.0.3", "cipher-base": "^1.0.0", @@ -2392,6 +2901,7 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/bs58/-/bs58-4.0.1.tgz", "integrity": "sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==", + "dev": true, "dependencies": { "base-x": "^3.0.2" } @@ -2400,6 +2910,7 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/bs58check/-/bs58check-2.1.2.tgz", "integrity": "sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==", + "dev": true, "dependencies": { "bs58": "^4.0.0", "create-hash": "^1.1.0", @@ -2420,39 +2931,38 @@ "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==", + "dev": true }, "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/busboy": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", - "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", - "dependencies": { - "streamsearch": "^1.1.0" - }, - "engines": { - "node": ">=10.16.0" - } + "integrity": "sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==", + "dev": true }, "node_modules/bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "dev": true, "engines": { "node": ">= 0.8" } }, "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dev": true, "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "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" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -2462,6 +2972,7 @@ "version": "6.3.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, "engines": { "node": ">=10" }, @@ -2473,21 +2984,15 @@ "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", - "dev": true - }, - "node_modules/catering": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/catering/-/catering-2.1.1.tgz", - "integrity": "sha512-K7Qy8O9p76sL3/3m7/zLKbRkyOlSZAgzEaLhyj2mXS8PsCud2Eo4hAb8aLtZqHh0QGqLcb9dlJSu6lHRVENm1w==", - "engines": { - "node": ">=6" - } + "dev": true, + "peer": true }, "node_modules/cbor": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/cbor/-/cbor-8.1.0.tgz", "integrity": "sha512-DwGjNW9omn6EwP70aXsn7FQJx5kO12tX0bZkaTjzdVFM6/7nhA4t0EENocKGx6D2Bch9PE2KzCUf5SceBdeijg==", "dev": true, + "peer": true, "dependencies": { "nofilter": "^3.1.0" }, @@ -2496,19 +3001,19 @@ } }, "node_modules/chai": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.7.tgz", - "integrity": "sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.4.1.tgz", + "integrity": "sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==", "dev": true, "peer": true, "dependencies": { "assertion-error": "^1.1.0", - "check-error": "^1.0.2", - "deep-eql": "^4.1.2", - "get-func-name": "^2.0.0", - "loupe": "^2.3.1", + "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.0.5" + "type-detect": "^4.0.8" }, "engines": { "node": ">=4" @@ -2519,6 +3024,7 @@ "resolved": "https://registry.npmjs.org/chai-as-promised/-/chai-as-promised-7.1.1.tgz", "integrity": "sha512-azL6xMoi+uxu6z4rhWQ1jbdUhOMhis2PvscD/xjLqNMkv3BPPp2JyyuTHOrf9BOosGpNQ11v6BKv/g57RXbiaA==", "dev": true, + "peer": true, "dependencies": { "check-error": "^1.0.2" }, @@ -2526,20 +3032,11 @@ "chai": ">= 2.1.2 < 5" } }, - "node_modules/chai-bn": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/chai-bn/-/chai-bn-0.3.1.tgz", - "integrity": "sha512-vuzEy0Cb+k8zqi2SHOmvZdRSbKcSOJfS1Nv8+6YDJIyCzfxkTCHLNRyjRIoRJ3WJtYb/c7OHjrvLoGeyO4A/gA==", - "dev": true, - "peerDependencies": { - "bn.js": "^5.0.0", - "chai": "^4.0.0" - } - }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -2551,64 +3048,34 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/chalk/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/chalk/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/chalk/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, "node_modules/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, + "peer": true, "engines": { "node": "*" } }, "node_modules/check-error": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", - "integrity": "sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==", + "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, + "peer": true, + "dependencies": { + "get-func-name": "^2.0.2" + }, "engines": { "node": "*" } }, "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": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -2621,6 +3088,9 @@ "engines": { "node": ">= 8.10.0" }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, "optionalDependencies": { "fsevents": "~2.3.2" } @@ -2628,45 +3098,44 @@ "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==", + "dev": true }, "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==", + "dev": true, "dependencies": { "inherits": "^2.0.1", "safe-buffer": "^5.0.1" } }, - "node_modules/classic-level": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/classic-level/-/classic-level-1.3.0.tgz", - "integrity": "sha512-iwFAJQYtqRTRM0F6L8h4JCt00ZSGdOyqh7yVrhhjrOpFhmBjNlRUey64MCiyo6UmQHMJ+No3c81nujPv+n9yrg==", - "hasInstallScript": true, - "dependencies": { - "abstract-level": "^1.0.2", - "catering": "^2.1.0", - "module-error": "^1.0.1", - "napi-macros": "^2.2.2", - "node-gyp-build": "^4.3.0" - }, - "engines": { - "node": ">=12" - } - }, "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==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/cli-boxes": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", + "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", + "dev": true, "engines": { "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/cli-table3": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.3.tgz", - "integrity": "sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg==", + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.4.tgz", + "integrity": "sha512-Lm3L0p+/npIQWNIiyF/nAn7T5dnOwR3xNTHXYEBFBFVPXzCVNZ5lqEC/1eo/EVfpDsQ1I+TX4ORPQgp+UI0CRw==", "dev": true, "dependencies": { "string-width": "^4.2.0" @@ -2682,6 +3151,7 @@ "version": "7.0.4", "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", @@ -2689,23 +3159,29 @@ } }, "node_modules/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==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "dependencies": { - "color-name": "1.1.3" + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" } }, "node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, "node_modules/colors": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", "dev": true, + "peer": true, "engines": { "node": ">=0.1.90" } @@ -2725,7 +3201,8 @@ "node_modules/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==" + "integrity": "sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==", + "dev": true }, "node_modules/command-line-args": { "version": "5.2.1", @@ -2757,6 +3234,18 @@ "node": ">=8.0.0" } }, + "node_modules/command-line-usage/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, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/command-line-usage/node_modules/array-back": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.2.tgz", @@ -2780,6 +3269,39 @@ "node": ">=4" } }, + "node_modules/command-line-usage/node_modules/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, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/command-line-usage/node_modules/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 + }, + "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, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/command-line-usage/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, + "engines": { + "node": ">=4" + } + }, "node_modules/command-line-usage/node_modules/supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -2811,15 +3333,16 @@ } }, "node_modules/compare-versions": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-6.0.0.tgz", - "integrity": "sha512-s2MzYxfRsE9f/ow8hjn7ysa7pod1xhHdQMsgiJtKx6XSNf4x2N1KG4fjrkUmXcP/e9Y2ZX4zB6sHIso0Lm6evQ==", + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-6.1.0.tgz", + "integrity": "sha512-LNZQXhqUvqUTotpZ00qLSaify3b4VFD588aRr8MKFw4CMUr98ytzCW5wDH5qx/DEY5kCDXcbcRuCqL0szEf2tg==", "dev": true }, "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 }, "node_modules/concat-stream": { "version": "1.6.2", @@ -2829,6 +3352,7 @@ "engines": [ "node >= 0.8" ], + "peer": true, "dependencies": { "buffer-from": "^1.0.0", "inherits": "^2.0.3", @@ -2841,6 +3365,7 @@ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "dev": true, + "peer": true, "dependencies": { "core-util-is": "~1.0.0", "inherits": "~2.0.3", @@ -2855,13 +3380,15 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true + "dev": true, + "peer": true }, "node_modules/concat-stream/node_modules/string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, + "peer": true, "dependencies": { "safe-buffer": "~5.1.0" } @@ -2870,31 +3397,23 @@ "version": "0.4.2", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "dev": true, "engines": { "node": ">= 0.6" } }, "node_modules/core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", - "dev": true - }, - "node_modules/crc-32": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", - "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", - "bin": { - "crc32": "bin/crc32.njs" - }, - "engines": { - "node": ">=0.8" - } + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true, + "peer": true }, "node_modules/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==", + "dev": true, "dependencies": { "cipher-base": "^1.0.1", "inherits": "^2.0.1", @@ -2907,6 +3426,7 @@ "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, "dependencies": { "cipher-base": "^1.0.3", "create-hash": "^1.1.0", @@ -2920,39 +3440,80 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "devOptional": true + "dev": true }, "node_modules/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, + "peer": true, "engines": { "node": "*" } }, - "node_modules/dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", + "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==", "dev": true, "dependencies": { - "assert-plus": "^1.0.0" + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" }, "engines": { - "node": ">=0.10" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/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 + "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==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/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 }, "node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, "dependencies": { "ms": "2.1.2" }, @@ -2969,6 +3530,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", + "dev": true, "engines": { "node": ">=10" }, @@ -2981,6 +3543,7 @@ "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==", "dev": true, + "peer": true, "dependencies": { "type-detect": "^4.0.0" }, @@ -3003,12 +3566,30 @@ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, + "node_modules/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==", + "dev": true, + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/define-properties": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", - "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", "dev": true, "dependencies": { + "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", "object-keys": "^1.1.1" }, @@ -3032,28 +3613,16 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "dev": true, "engines": { "node": ">= 0.8" } }, - "node_modules/detect-port": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/detect-port/-/detect-port-1.5.1.tgz", - "integrity": "sha512-aBzdj76lueB6uUst5iAs7+0H/oOjqI5D16XUWxlWMIMROhcM0rfsNVk93zTngq1dDNpoXRr++Sus7ETAExppAQ==", - "dev": true, - "dependencies": { - "address": "^1.0.1", - "debug": "4" - }, - "bin": { - "detect": "bin/detect-port.js", - "detect-port": "bin/detect-port.js" - } - }, "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==", + "dev": true, "engines": { "node": ">=0.3.1" } @@ -3083,31 +3652,22 @@ } }, "node_modules/dotenv": { - "version": "16.3.1", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz", - "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==", + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", "dev": true, "engines": { "node": ">=12" }, "funding": { - "url": "https://github.com/motdotla/dotenv?sponsor=1" - } - }, - "node_modules/ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", - "dev": true, - "dependencies": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" + "url": "https://dotenvx.com" } }, "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==", + "dev": true, "dependencies": { "bn.js": "^4.11.9", "brorand": "^1.1.0", @@ -3121,19 +3681,23 @@ "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==" + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true }, "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==", + "dev": true }, "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==", + "dev": true, "dependencies": { - "ansi-colors": "^4.1.1" + "ansi-colors": "^4.1.1", + "strip-ansi": "^6.0.1" }, "engines": { "node": ">=8.6" @@ -3143,51 +3707,63 @@ "version": "2.2.1", "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "dev": true, "engines": { "node": ">=6" } }, "node_modules/es-abstract": { - "version": "1.21.3", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.21.3.tgz", - "integrity": "sha512-ZU4miiY1j3sGPFLJ34VJXEqhpmL+HGByCinGHv4HC+Fxl2fI2Z4yR6tl0mORnDr6PA8eihWo4LmSWDbvhALckg==", - "dev": true, - "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "es-set-tostringtag": "^2.0.1", + "version": "1.23.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", + "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", + "dev": true, + "dependencies": { + "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.5", - "get-intrinsic": "^1.2.1", - "get-symbol-description": "^1.0.0", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.4", + "get-symbol-description": "^1.0.2", "globalthis": "^1.0.3", "gopd": "^1.0.1", - "has": "^1.0.3", - "has-property-descriptors": "^1.0.0", - "has-proto": "^1.0.1", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", "has-symbols": "^1.0.3", - "internal-slot": "^1.0.5", - "is-array-buffer": "^3.0.2", + "hasown": "^2.0.2", + "internal-slot": "^1.0.7", + "is-array-buffer": "^3.0.4", "is-callable": "^1.2.7", - "is-negative-zero": "^2.0.2", + "is-data-view": "^1.0.1", + "is-negative-zero": "^2.0.3", "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", + "is-shared-array-buffer": "^1.0.3", "is-string": "^1.0.7", - "is-typed-array": "^1.1.10", + "is-typed-array": "^1.1.13", "is-weakref": "^1.0.2", - "object-inspect": "^1.12.3", + "object-inspect": "^1.13.1", "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.5.0", - "safe-regex-test": "^1.0.0", - "string.prototype.trim": "^1.2.7", - "string.prototype.trimend": "^1.0.6", - "string.prototype.trimstart": "^1.0.6", - "typed-array-byte-offset": "^1.0.0", - "typed-array-length": "^1.0.4", + "object.assign": "^4.1.5", + "regexp.prototype.flags": "^1.5.2", + "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.10" + "which-typed-array": "^1.1.15" }, "engines": { "node": ">= 0.4" @@ -3196,44 +3772,62 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/es-abstract/node_modules/object.assign": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", - "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "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==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "has-symbols": "^1.0.3", - "object-keys": "^1.1.1" + "get-intrinsic": "^1.2.4" }, "engines": { "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/es-array-method-boxes-properly": { + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", - "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==", - "dev": true + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", + "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } }, "node_modules/es-set-tostringtag": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", - "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", + "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, "dependencies": { - "get-intrinsic": "^1.1.3", - "has": "^1.0.3", - "has-tostringtag": "^1.0.0" + "get-intrinsic": "^1.2.4", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.1" }, "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==", + "dev": true, + "dependencies": { + "hasown": "^2.0.0" + } + }, "node_modules/es-to-primitive": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", @@ -3252,19 +3846,24 @@ } }, "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", + "dev": true, "engines": { "node": ">=6" } }, "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==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, "engines": { - "node": ">=0.8.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/escodegen": { @@ -3321,24 +3920,23 @@ } }, "node_modules/eth-gas-reporter": { - "version": "0.2.25", - "resolved": "https://registry.npmjs.org/eth-gas-reporter/-/eth-gas-reporter-0.2.25.tgz", - "integrity": "sha512-1fRgyE4xUB8SoqLgN3eDfpDfwEfRxh2Sz1b7wzFbyQA+9TekMmvSjjoRu9SKcSVyK+vLkLIsVbJDsTWjw195OQ==", + "version": "0.2.27", + "resolved": "https://registry.npmjs.org/eth-gas-reporter/-/eth-gas-reporter-0.2.27.tgz", + "integrity": "sha512-femhvoAM7wL0GcI8ozTdxfuBtBFJ9qsyIAsmKVjlWAHUbdnnXHt+lKzz/kmldM5lA9jLuNHGwuIxorNpLbR1Zw==", "dev": true, + "peer": true, "dependencies": { - "@ethersproject/abi": "^5.0.0-beta.146", "@solidity-parser/parser": "^0.14.0", + "axios": "^1.5.1", "cli-table3": "^0.5.0", "colors": "1.4.0", "ethereum-cryptography": "^1.0.3", - "ethers": "^4.0.40", + "ethers": "^5.7.2", "fs-readdir-recursive": "^1.1.0", "lodash": "^4.17.14", "markdown-table": "^1.1.3", - "mocha": "^7.1.1", + "mocha": "^10.2.0", "req-cwd": "^2.0.0", - "request": "^2.88.0", - "request-promise-native": "^1.0.5", "sha1": "^1.1.1", "sync-request": "^6.0.0" }, @@ -3351,668 +3949,178 @@ } } }, - "node_modules/eth-gas-reporter/node_modules/ansi-colors": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", - "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/eth-gas-reporter/node_modules/ansi-regex": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", - "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/eth-gas-reporter/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/eth-gas-reporter/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==", - "dev": true - }, - "node_modules/eth-gas-reporter/node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/eth-gas-reporter/node_modules/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, - "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eth-gas-reporter/node_modules/chalk/node_modules/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, - "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eth-gas-reporter/node_modules/chokidar": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.3.0.tgz", - "integrity": "sha512-dGmKLDdT3Gdl7fBUe8XK+gAtGmzy5Fn0XkkWQuYxGIgWVPPse2CxFA5mtrlD0TOHaHjEUqkWNyP1XdHoJES/4A==", - "dev": true, - "dependencies": { - "anymatch": "~3.1.1", - "braces": "~3.0.2", - "glob-parent": "~5.1.0", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.2.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.1.1" - } - }, - "node_modules/eth-gas-reporter/node_modules/cli-table3": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.5.1.tgz", - "integrity": "sha512-7Qg2Jrep1S/+Q3EceiZtQcDPWxhAvBw+ERf1162v4sikJrvojMHFqXt8QIVha8UlH9rgU0BeWPytZ9/TzYqlUw==", - "dev": true, - "dependencies": { - "object-assign": "^4.1.0", - "string-width": "^2.1.1" - }, - "engines": { - "node": ">=6" - }, - "optionalDependencies": { - "colors": "^1.1.2" - } - }, - "node_modules/eth-gas-reporter/node_modules/cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", - "dev": true, - "dependencies": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - } - }, - "node_modules/eth-gas-reporter/node_modules/cliui/node_modules/ansi-regex": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", - "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/eth-gas-reporter/node_modules/cliui/node_modules/string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/eth-gas-reporter/node_modules/cliui/node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "dependencies": { - "ansi-regex": "^4.1.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/eth-gas-reporter/node_modules/debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "deprecated": "Debug versions >=3.2.0 <3.2.7 || >=4 <4.3.1 have a low-severity ReDos regression when used in a Node.js environment. It is recommended you upgrade to 3.2.7 or 4.3.1. (https://github.com/visionmedia/debug/issues/797)", - "dev": true, - "dependencies": { - "ms": "^2.1.1" - } - }, - "node_modules/eth-gas-reporter/node_modules/decamelize": { + "node_modules/eth-gas-reporter/node_modules/@noble/hashes": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eth-gas-reporter/node_modules/diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", - "dev": true, - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/eth-gas-reporter/node_modules/emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true - }, - "node_modules/eth-gas-reporter/node_modules/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, - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eth-gas-reporter/node_modules/ethereum-cryptography": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-1.2.0.tgz", - "integrity": "sha512-6yFQC9b5ug6/17CQpCyE3k9eKBMdhyVjzUy1WkiuY/E4vj/SXDBbCw8QEIaXqf0Mf2SnY6RmpDcwlUmBSS0EJw==", - "dev": true, - "dependencies": { - "@noble/hashes": "1.2.0", - "@noble/secp256k1": "1.7.1", - "@scure/bip32": "1.1.5", - "@scure/bip39": "1.1.1" - } - }, - "node_modules/eth-gas-reporter/node_modules/ethers": { - "version": "4.0.49", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-4.0.49.tgz", - "integrity": "sha512-kPltTvWiyu+OktYy1IStSO16i2e7cS9D9OxZ81q2UUaiNPVrm/RTcbxamCXF9VUSKzJIdJV68EAIhTEVBalRWg==", - "dev": true, - "dependencies": { - "aes-js": "3.0.0", - "bn.js": "^4.11.9", - "elliptic": "6.5.4", - "hash.js": "1.1.3", - "js-sha3": "0.5.7", - "scrypt-js": "2.0.4", - "setimmediate": "1.0.4", - "uuid": "2.0.1", - "xmlhttprequest": "1.8.0" - } - }, - "node_modules/eth-gas-reporter/node_modules/find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "dependencies": { - "locate-path": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/eth-gas-reporter/node_modules/flat": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.1.tgz", - "integrity": "sha512-FmTtBsHskrU6FJ2VxCnsDb84wu9zhmO3cUX2kGFb5tuwhfXxGciiT0oRY+cck35QmG+NmGh5eLz6lLCpWTqwpA==", - "dev": true, - "dependencies": { - "is-buffer": "~2.0.3" - }, - "bin": { - "flat": "cli.js" - } - }, - "node_modules/eth-gas-reporter/node_modules/fsevents": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", - "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", - "deprecated": "\"Please update to latest v2.3 or v2.2\"", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.2.0.tgz", + "integrity": "sha512-FZfhjEDbT5GRswV3C6uvLPHMiVD6lQBmpoX5+eSiPaMTXte/IKqI5dykDxzZB/WBeK/CDuQRBWarPdi3FNY2zQ==", "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/eth-gas-reporter/node_modules/glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", - "dev": true, - "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" - }, - "engines": { - "node": "*" - } - }, - "node_modules/eth-gas-reporter/node_modules/hash.js": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.3.tgz", - "integrity": "sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.0" - } - }, - "node_modules/eth-gas-reporter/node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/eth-gas-reporter/node_modules/js-sha3": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz", - "integrity": "sha512-GII20kjaPX0zJ8wzkTbNDYMY7msuZcTWk8S5UOh6806Jq/wz1J8/bnr8uGU0DAUmYDjj2Mr4X1cW8v/GLYnR+g==", - "dev": true - }, - "node_modules/eth-gas-reporter/node_modules/js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", - "dev": true, - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/eth-gas-reporter/node_modules/locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "dependencies": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/eth-gas-reporter/node_modules/log-symbols": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-3.0.0.tgz", - "integrity": "sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ==", - "dev": true, - "dependencies": { - "chalk": "^2.4.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/eth-gas-reporter/node_modules/minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/eth-gas-reporter/node_modules/mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dev": true, - "dependencies": { - "minimist": "^1.2.5" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, - "node_modules/eth-gas-reporter/node_modules/mocha": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-7.2.0.tgz", - "integrity": "sha512-O9CIypScywTVpNaRrCAgoUnJgozpIofjKUYmJhiCIJMiuYnLI6otcb1/kpW9/n/tJODHGZ7i8aLQoDVsMtOKQQ==", - "dev": true, - "dependencies": { - "ansi-colors": "3.2.3", - "browser-stdout": "1.3.1", - "chokidar": "3.3.0", - "debug": "3.2.6", - "diff": "3.5.0", - "escape-string-regexp": "1.0.5", - "find-up": "3.0.0", - "glob": "7.1.3", - "growl": "1.10.5", - "he": "1.2.0", - "js-yaml": "3.13.1", - "log-symbols": "3.0.0", - "minimatch": "3.0.4", - "mkdirp": "0.5.5", - "ms": "2.1.1", - "node-environment-flags": "1.0.6", - "object.assign": "4.1.0", - "strip-json-comments": "2.0.1", - "supports-color": "6.0.0", - "which": "1.3.1", - "wide-align": "1.1.3", - "yargs": "13.3.2", - "yargs-parser": "13.1.2", - "yargs-unparser": "1.6.0" - }, - "bin": { - "_mocha": "bin/_mocha", - "mocha": "bin/mocha" - }, - "engines": { - "node": ">= 8.10.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mochajs" - } - }, - "node_modules/eth-gas-reporter/node_modules/ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true - }, - "node_modules/eth-gas-reporter/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eth-gas-reporter/node_modules/p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "dependencies": { - "p-limit": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/eth-gas-reporter/node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/eth-gas-reporter/node_modules/readdirp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.2.0.tgz", - "integrity": "sha512-crk4Qu3pmXwgxdSgGhgA/eXiJAPQiX4GMOZZMXnqKxHX7TaoL+3gQVo/WeuAiogr07DpnfjIMpXXa+PAIvwPGQ==", - "dev": true, - "dependencies": { - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/eth-gas-reporter/node_modules/scrypt-js": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-2.0.4.tgz", - "integrity": "sha512-4KsaGcPnuhtCZQCxFxN3GVYIhKFPTdLd8PLC552XwbMndtD0cjRFAhDuuydXQ0h08ZfPgzqe6EKHozpuH74iDw==", - "dev": true - }, - "node_modules/eth-gas-reporter/node_modules/setimmediate": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.4.tgz", - "integrity": "sha512-/TjEmXQVEzdod/FFskf3o7oOAsGhHf2j1dZqRFbDzq4F3mvvxflIIi4Hd3bLQE9y/CpwqfSQam5JakI/mi3Pog==", - "dev": true - }, - "node_modules/eth-gas-reporter/node_modules/string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "dependencies": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/eth-gas-reporter/node_modules/strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==", - "dev": true, - "dependencies": { - "ansi-regex": "^3.0.0" - }, - "engines": { - "node": ">=4" - } + "peer": true }, - "node_modules/eth-gas-reporter/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, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/eth-gas-reporter/node_modules/supports-color": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz", - "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==", + "node_modules/eth-gas-reporter/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==", "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "peer": true, "dependencies": { - "has-flag": "^3.0.0" - }, - "engines": { - "node": ">=6" + "@noble/hashes": "~1.2.0", + "@noble/secp256k1": "~1.7.0", + "@scure/base": "~1.1.0" } }, - "node_modules/eth-gas-reporter/node_modules/uuid": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.1.tgz", - "integrity": "sha512-nWg9+Oa3qD2CQzHIP4qKUqwNfzKn8P0LtFhotaCTFchsV7ZfDhAybeip/HZVeMIpZi9JgY1E3nUlwaCmZT1sEg==", - "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", - "dev": true - }, - "node_modules/eth-gas-reporter/node_modules/wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "node_modules/eth-gas-reporter/node_modules/@scure/bip39": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.1.1.tgz", + "integrity": "sha512-t+wDck2rVkh65Hmv280fYdVdY25J9YeEUIgn2LG1WM6gxFkGzcksoDiUkWVpVp3Oex9xGC68JU2dSbUfwZ2jPg==", "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "peer": true, "dependencies": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" - }, - "engines": { - "node": ">=6" + "@noble/hashes": "~1.2.0", + "@scure/base": "~1.1.0" } }, - "node_modules/eth-gas-reporter/node_modules/wrap-ansi/node_modules/ansi-regex": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", - "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "node_modules/eth-gas-reporter/node_modules/ansi-regex": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", + "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", "dev": true, + "peer": true, "engines": { - "node": ">=6" + "node": ">=4" } }, - "node_modules/eth-gas-reporter/node_modules/wrap-ansi/node_modules/string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "node_modules/eth-gas-reporter/node_modules/cli-table3": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.5.1.tgz", + "integrity": "sha512-7Qg2Jrep1S/+Q3EceiZtQcDPWxhAvBw+ERf1162v4sikJrvojMHFqXt8QIVha8UlH9rgU0BeWPytZ9/TzYqlUw==", "dev": true, + "peer": true, "dependencies": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" + "object-assign": "^4.1.0", + "string-width": "^2.1.1" }, "engines": { "node": ">=6" - } - }, - "node_modules/eth-gas-reporter/node_modules/wrap-ansi/node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "dependencies": { - "ansi-regex": "^4.1.0" }, - "engines": { - "node": ">=6" - } - }, - "node_modules/eth-gas-reporter/node_modules/y18n": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", - "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", - "dev": true - }, - "node_modules/eth-gas-reporter/node_modules/yargs": { - "version": "13.3.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", - "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", - "dev": true, - "dependencies": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.2" + "optionalDependencies": { + "colors": "^1.1.2" } }, - "node_modules/eth-gas-reporter/node_modules/yargs-parser": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", - "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "node_modules/eth-gas-reporter/node_modules/ethereum-cryptography": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-1.2.0.tgz", + "integrity": "sha512-6yFQC9b5ug6/17CQpCyE3k9eKBMdhyVjzUy1WkiuY/E4vj/SXDBbCw8QEIaXqf0Mf2SnY6RmpDcwlUmBSS0EJw==", "dev": true, + "peer": true, "dependencies": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" + "@noble/hashes": "1.2.0", + "@noble/secp256k1": "1.7.1", + "@scure/bip32": "1.1.5", + "@scure/bip39": "1.1.1" } }, - "node_modules/eth-gas-reporter/node_modules/yargs-unparser": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.0.tgz", - "integrity": "sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw==", + "node_modules/eth-gas-reporter/node_modules/ethers": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.7.2.tgz", + "integrity": "sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg==", "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" + } + ], + "peer": true, "dependencies": { - "flat": "^4.1.0", - "lodash": "^4.17.15", - "yargs": "^13.3.0" - }, - "engines": { - "node": ">=6" + "@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/eth-gas-reporter/node_modules/yargs/node_modules/ansi-regex": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", - "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "node_modules/eth-gas-reporter/node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", "dev": true, + "peer": true, "engines": { - "node": ">=6" + "node": ">=4" } }, - "node_modules/eth-gas-reporter/node_modules/yargs/node_modules/string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "node_modules/eth-gas-reporter/node_modules/string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", "dev": true, + "peer": true, "dependencies": { - "emoji-regex": "^7.0.1", "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" + "strip-ansi": "^4.0.0" }, "engines": { - "node": ">=6" + "node": ">=4" } }, - "node_modules/eth-gas-reporter/node_modules/yargs/node_modules/strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "node_modules/eth-gas-reporter/node_modules/strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==", "dev": true, + "peer": true, "dependencies": { - "ansi-regex": "^4.1.0" + "ansi-regex": "^3.0.0" }, "engines": { - "node": ">=6" + "node": ">=4" } }, "node_modules/ethereum-bloom-filters": { @@ -4028,6 +4136,7 @@ "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", @@ -4050,6 +4159,7 @@ "version": "0.6.8", "resolved": "https://registry.npmjs.org/ethereumjs-abi/-/ethereumjs-abi-0.6.8.tgz", "integrity": "sha512-Tx0r/iXI6r+lRsdvkFDlut0N08jWMnKRZ6Gkq+Nmw75lZe4e6o3EkSnkaBP5NF6+m5PTGAr9JP43N3LyeoglsA==", + "dev": true, "dependencies": { "bn.js": "^4.11.8", "ethereumjs-util": "^6.0.0" @@ -4059,6 +4169,7 @@ "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==", + "dev": true, "dependencies": { "@types/node": "*" } @@ -4066,12 +4177,14 @@ "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==" + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true }, "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==", + "dev": true, "dependencies": { "@types/bn.js": "^4.11.3", "bn.js": "^4.11.0", @@ -4099,13 +4212,14 @@ } }, "node_modules/ethers": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.7.2.tgz", - "integrity": "sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg==", + "version": "6.11.1", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.11.1.tgz", + "integrity": "sha512-mxTAE6wqJQAbp5QAe/+o+rXOID7Nw91OZXvgpjDa1r4fAbq2Nu314oEZSbjoRLacuCzs7kUC3clEvkCQowffGg==", + "dev": true, "funding": [ { "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + "url": "https://github.com/sponsors/ethers-io/" }, { "type": "individual", @@ -4113,38 +4227,30 @@ } ], "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" + "@adraffy/ens-normalize": "1.10.1", + "@noble/curves": "1.2.0", + "@noble/hashes": "1.3.2", + "@types/node": "18.15.13", + "aes-js": "4.0.0-beta.5", + "tslib": "2.4.0", + "ws": "8.5.0" + }, + "engines": { + "node": ">=14.0.0" } }, + "node_modules/ethers/node_modules/@types/node": { + "version": "18.15.13", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.13.tgz", + "integrity": "sha512-N+0kuo9KgrUQ1Sn/ifDXsvg0TTleP7rIy4zOBGECxAljqvqfqpTfzx0Q1NUedOixRMBfe2Whhb056a42cWs26Q==", + "dev": true + }, + "node_modules/ethers/node_modules/tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", + "dev": true + }, "node_modules/ethjs-unit": { "version": "0.1.6", "resolved": "https://registry.npmjs.org/ethjs-unit/-/ethjs-unit-0.1.6.tgz", @@ -4169,6 +4275,7 @@ "version": "0.1.6", "resolved": "https://registry.npmjs.org/ethjs-util/-/ethjs-util-0.1.6.tgz", "integrity": "sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==", + "dev": true, "dependencies": { "is-hex-prefixed": "1.0.0", "strip-hex-prefix": "1.0.0" @@ -4178,38 +4285,16 @@ "npm": ">=3" } }, - "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==", - "engines": { - "node": ">=6" - } - }, "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, "dependencies": { "md5.js": "^1.3.4", "safe-buffer": "^5.1.1" } }, - "node_modules/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true - }, - "node_modules/extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", - "dev": true, - "engines": [ - "node >=0.6.0" - ] - }, "node_modules/fast-base64-decode": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fast-base64-decode/-/fast-base64-decode-1.0.0.tgz", @@ -4220,12 +4305,13 @@ "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, + "peer": true }, "node_modules/fast-glob": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.0.tgz", - "integrity": "sha512-ChDuvbOypPuNjO8yIDf36x7BlZX1smcUMTTcyoIjycexOxd6DFsKsg21qVBzEmr3G7fUKIRy2/psii+CIUt7FA==", + "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, "dependencies": { "@nodelib/fs.stat": "^2.0.2", @@ -4238,12 +4324,6 @@ "node": ">=8.6.0" } }, - "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 - }, "node_modules/fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", @@ -4251,9 +4331,9 @@ "dev": true }, "node_modules/fastq": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", - "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", "dev": true, "dependencies": { "reusify": "^1.0.4" @@ -4263,6 +4343,7 @@ "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, "dependencies": { "to-regex-range": "^5.0.1" }, @@ -4286,6 +4367,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==", + "dev": true, "dependencies": { "locate-path": "^2.0.0" }, @@ -4297,14 +4379,16 @@ "version": "5.0.2", "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", + "dev": true, "bin": { "flat": "cli.js" } }, "node_modules/follow-redirects": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz", - "integrity": "sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==", + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", + "dev": true, "funding": [ { "type": "individual", @@ -4329,15 +4413,6 @@ "is-callable": "^1.1.3" } }, - "node_modules/forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", - "dev": true, - "engines": { - "node": "*" - } - }, "node_modules/form-data": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", @@ -4355,36 +4430,42 @@ "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==", + "dev": true }, "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==", + "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==", + "dev": true, + "peer": true, "dependencies": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" }, "engines": { - "node": ">=6 <7 || >=8" + "node": ">=12" } }, "node_modules/fs-readdir-recursive": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz", "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==", - "dev": true + "dev": true, + "peer": 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==" + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true }, "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, "hasInstallScript": true, "optional": true, "os": [ @@ -4395,20 +4476,24 @@ } }, "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/function.prototype.name": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.5.tgz", - "integrity": "sha512-uN7m/BzVKQnCUF/iW8jYea67v++2u7m5UgENbHRtdDVclOUP+FMPlCNdmk0h/ysGyo2tavMJEDqJAkJdRa1vMA==", + "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, "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.3", - "es-abstract": "^1.19.0", - "functions-have-names": "^1.2.2" + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "functions-have-names": "^1.2.3" }, "engines": { "node": ">= 0.4" @@ -4417,11 +4502,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==" - }, "node_modules/functions-have-names": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", @@ -4435,14 +4515,15 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, "engines": { "node": "6.* || 8.* || >= 10.*" } }, "node_modules/get-func-name": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", - "integrity": "sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==", + "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, "peer": true, "engines": { @@ -4450,14 +4531,19 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", - "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dev": true, "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", "has-proto": "^1.0.1", - "has-symbols": "^1.0.3" + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -4468,18 +4554,20 @@ "resolved": "https://registry.npmjs.org/get-port/-/get-port-3.2.0.tgz", "integrity": "sha512-x5UJKlgeUiNT8nyo/AcnwLnZuZNcSjSw0kogRB+Whd1fjjFq4B1hySFxSFWWSn4mIBzg3sRNUDFYc4g5gjPoLg==", "dev": true, + "peer": true, "engines": { "node": ">=4" } }, "node_modules/get-symbol-description": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", - "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "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, "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" + "call-bind": "^1.0.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4" }, "engines": { "node": ">= 0.4" @@ -4488,15 +4576,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", - "dev": true, - "dependencies": { - "assert-plus": "^1.0.0" - } - }, "node_modules/ghost-testrpc": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/ghost-testrpc/-/ghost-testrpc-0.0.2.tgz", @@ -4510,6 +4589,18 @@ "testrpc-sc": "index.js" } }, + "node_modules/ghost-testrpc/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, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/ghost-testrpc/node_modules/chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", @@ -4524,6 +4615,39 @@ "node": ">=4" } }, + "node_modules/ghost-testrpc/node_modules/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, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/ghost-testrpc/node_modules/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 + }, + "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, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/ghost-testrpc/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, + "engines": { + "node": ">=4" + } + }, "node_modules/ghost-testrpc/node_modules/supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -4540,6 +4664,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -4559,6 +4684,7 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, "dependencies": { "is-glob": "^4.0.1" }, @@ -4641,25 +4767,17 @@ "node_modules/graceful-fs": { "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==" - }, - "node_modules/growl": { - "version": "1.10.5", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", - "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", - "dev": true, - "engines": { - "node": ">=4.x" - } + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true }, "node_modules/handlebars": { - "version": "4.7.7", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", - "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", + "version": "4.7.8", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", + "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", "dev": true, "dependencies": { "minimist": "^1.2.5", - "neo-async": "^2.6.0", + "neo-async": "^2.6.2", "source-map": "^0.6.1", "wordwrap": "^1.0.0" }, @@ -4682,54 +4800,33 @@ "node": ">=0.10.0" } }, - "node_modules/har-schema": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", - "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/har-validator": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", - "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", - "deprecated": "this library is no longer supported", - "dev": true, - "dependencies": { - "ajv": "^6.12.3", - "har-schema": "^2.0.0" - }, - "engines": { - "node": ">=6" - } - }, "node_modules/hardhat": { - "version": "2.12.2", - "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-2.12.2.tgz", - "integrity": "sha512-f3ZhzXy1uyQv0UXnAQ8GCBOWjzv++WJNb7bnm10SsyC3dB7vlPpsMWBNhq7aoRxKrNhX9tCev81KFV3i5BTeMQ==", + "version": "2.20.1", + "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-2.20.1.tgz", + "integrity": "sha512-q75xDQiQtCZcTMBwjTovrXEU5ECr49baxr4/OBkIu/ULTPzlB20yk1dRWNmD2IFbAeAeXggaWvQAdpiScaHtPw==", + "dev": true, "dependencies": { "@ethersproject/abi": "^5.1.2", "@metamask/eth-sig-util": "^4.0.0", - "@nomicfoundation/ethereumjs-block": "^4.0.0", - "@nomicfoundation/ethereumjs-blockchain": "^6.0.0", - "@nomicfoundation/ethereumjs-common": "^3.0.0", - "@nomicfoundation/ethereumjs-evm": "^1.0.0", - "@nomicfoundation/ethereumjs-rlp": "^4.0.0", - "@nomicfoundation/ethereumjs-statemanager": "^1.0.0", - "@nomicfoundation/ethereumjs-trie": "^5.0.0", - "@nomicfoundation/ethereumjs-tx": "^4.0.0", - "@nomicfoundation/ethereumjs-util": "^8.0.0", - "@nomicfoundation/ethereumjs-vm": "^6.0.0", + "@nomicfoundation/ethereumjs-block": "5.0.4", + "@nomicfoundation/ethereumjs-blockchain": "7.0.4", + "@nomicfoundation/ethereumjs-common": "4.0.4", + "@nomicfoundation/ethereumjs-evm": "2.0.4", + "@nomicfoundation/ethereumjs-rlp": "5.0.4", + "@nomicfoundation/ethereumjs-statemanager": "2.0.4", + "@nomicfoundation/ethereumjs-trie": "6.0.4", + "@nomicfoundation/ethereumjs-tx": "5.0.4", + "@nomicfoundation/ethereumjs-util": "9.0.4", + "@nomicfoundation/ethereumjs-verkle": "0.0.2", + "@nomicfoundation/ethereumjs-vm": "7.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", - "abort-controller": "^3.0.0", "adm-zip": "^0.4.16", "aggregate-error": "^3.0.0", "ansi-escapes": "^4.3.0", + "boxen": "^5.1.2", "chalk": "^2.4.2", "chokidar": "^3.4.0", "ci-info": "^2.0.0", @@ -4749,7 +4846,6 @@ "mnemonist": "^0.38.0", "mocha": "^10.0.0", "p-map": "^4.0.0", - "qs": "^6.7.0", "raw-body": "^2.4.1", "resolve": "1.17.0", "semver": "^6.3.0", @@ -4757,15 +4853,12 @@ "source-map-support": "^0.5.13", "stacktrace-parser": "^0.1.10", "tsort": "0.0.1", - "undici": "^5.4.0", + "undici": "^5.14.0", "uuid": "^8.3.2", "ws": "^7.4.6" }, "bin": { - "hardhat": "internal/cli/cli.js" - }, - "engines": { - "node": "^14.0.0 || ^16.0.0 || ^18.0.0" + "hardhat": "internal/cli/bootstrap.js" }, "peerDependencies": { "ts-node": "*", @@ -4795,10 +4888,11 @@ } }, "node_modules/hardhat-gas-reporter": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/hardhat-gas-reporter/-/hardhat-gas-reporter-1.0.9.tgz", - "integrity": "sha512-INN26G3EW43adGKBNzYWOlI3+rlLnasXTwW79YNnUhXPDa+yHESgt639dJEs37gCjhkbNKcRRJnomXEuMFBXJg==", + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/hardhat-gas-reporter/-/hardhat-gas-reporter-1.0.10.tgz", + "integrity": "sha512-02N4+So/fZrzJ88ci54GqwVA3Zrf0C9duuTyGt0CFRIh/CdNwbnTgkXkRfojOMLBQ+6t+lBIkgbsOtqMvNwikA==", "dev": true, + "peer": true, "dependencies": { "array-uniq": "1.0.3", "eth-gas-reporter": "^0.2.25", @@ -4809,22 +4903,130 @@ } }, "node_modules/hardhat-tracer": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/hardhat-tracer/-/hardhat-tracer-1.3.0.tgz", - "integrity": "sha512-mUYuRJWlxCwY4R2urCpNM4ecVSq/iMLiVP9YZKlfXyv4R8T+4HAcTfumilUOXHGe6wHI+8Ki2EaTon3KgzATDA==", + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/hardhat-tracer/-/hardhat-tracer-2.8.2.tgz", + "integrity": "sha512-kNi13qdwJsclM9PoIZpZGRGteTFmnVio7xoq3xrca5PWxnQZGO+E1Oig++b6g4gXLkAA3QNFBJip05zsp4qvyQ==", + "dev": true, "dependencies": { + "chalk": "^4.1.2", + "debug": "^4.3.4", "ethers": "^5.6.1" }, "peerDependencies": { - "chalk": "4.x", - "ethers": "5.x", - "hardhat": "2.x" + "chai": "4.x", + "hardhat": ">=2.16 <2.21.0" + } + }, + "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==", + "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" + } + ], + "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/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==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ] + }, + "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==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "@noble/hashes": "~1.2.0", + "@noble/secp256k1": "~1.7.0", + "@scure/base": "~1.1.0" + } + }, + "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==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "@noble/hashes": "~1.2.0", + "@scure/base": "~1.1.0" + } + }, + "node_modules/hardhat/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, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" } }, "node_modules/hardhat/node_modules/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, "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", @@ -4834,15 +5036,41 @@ "node": ">=4" } }, + "node_modules/hardhat/node_modules/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, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/hardhat/node_modules/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 + }, "node_modules/hardhat/node_modules/commander": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/commander/-/commander-3.0.2.tgz", - "integrity": "sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow==" + "integrity": "sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow==", + "dev": true + }, + "node_modules/hardhat/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, + "engines": { + "node": ">=0.8.0" + } }, "node_modules/hardhat/node_modules/ethereum-cryptography": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-1.2.0.tgz", "integrity": "sha512-6yFQC9b5ug6/17CQpCyE3k9eKBMdhyVjzUy1WkiuY/E4vj/SXDBbCw8QEIaXqf0Mf2SnY6RmpDcwlUmBSS0EJw==", + "dev": true, "dependencies": { "@noble/hashes": "1.2.0", "@noble/secp256k1": "1.7.1", @@ -4850,10 +5078,34 @@ "@scure/bip39": "1.1.1" } }, + "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==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/hardhat/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, + "engines": { + "node": ">=4" + } + }, "node_modules/hardhat/node_modules/jsonfile": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", - "integrity": "sha512-PKllAqbgLgxHaj8TElYymKCAgrASebJrWpTnEkOaTowt23VKXXN0sUeriJ+eh7y6ufb/CC5ap11pz71/cM0hUw==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "dev": true, "optionalDependencies": { "graceful-fs": "^4.1.6" } @@ -4862,6 +5114,7 @@ "version": "0.7.3", "resolved": "https://registry.npmjs.org/solc/-/solc-0.7.3.tgz", "integrity": "sha512-GAsWNAjGzIDg7VxzP6mPjdurby3IkGCjQcM8GFYZT6RyaoUZKmMU6Y7YwG+tFGhv7dwZ8rmR4iwFDrrD99JwqA==", + "dev": true, "dependencies": { "command-exists": "^1.2.8", "commander": "3.0.2", @@ -4884,6 +5137,7 @@ "version": "0.30.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz", "integrity": "sha512-UvSPKyhMn6LEd/WpUaV9C9t3zATuqoqfWc3QdPhPLb58prN9tqYPlPWi8Krxi44loBoUzlobqZ3+8tGpxxSzwA==", + "dev": true, "dependencies": { "graceful-fs": "^4.1.2", "jsonfile": "^2.1.0", @@ -4892,10 +5146,20 @@ "rimraf": "^2.2.8" } }, + "node_modules/hardhat/node_modules/solc/node_modules/jsonfile": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", + "integrity": "sha512-PKllAqbgLgxHaj8TElYymKCAgrASebJrWpTnEkOaTowt23VKXXN0sUeriJ+eh7y6ufb/CC5ap11pz71/cM0hUw==", + "dev": true, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, "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==", + "dev": true, "bin": { "semver": "bin/semver" } @@ -4904,6 +5168,7 @@ "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, "dependencies": { "has-flag": "^3.0.0" }, @@ -4911,15 +5176,34 @@ "node": ">=4" } }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dependencies": { - "function-bind": "^1.1.1" - }, + "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==", + "dev": true, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/hardhat/node_modules/ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "dev": true, "engines": { - "node": ">= 0.4.0" + "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": { @@ -4932,29 +5216,31 @@ } }, "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==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, "engines": { - "node": ">=4" + "node": ">=8" } }, "node_modules/has-property-descriptors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", - "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "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, "dependencies": { - "get-intrinsic": "^1.1.1" + "es-define-property": "^1.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/has-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "dev": true, "engines": { "node": ">= 0.4" }, @@ -4966,6 +5252,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true, "engines": { "node": ">= 0.4" }, @@ -4974,12 +5261,12 @@ } }, "node_modules/has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "dev": true, "dependencies": { - "has-symbols": "^1.0.2" + "has-symbols": "^1.0.3" }, "engines": { "node": ">= 0.4" @@ -4992,6 +5279,7 @@ "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, "dependencies": { "inherits": "^2.0.4", "readable-stream": "^3.6.0", @@ -5005,15 +5293,29 @@ "version": "1.1.7", "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "dev": true, "dependencies": { "inherits": "^2.0.3", "minimalistic-assert": "^1.0.1" } }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, "bin": { "he": "bin/he" } @@ -5028,6 +5330,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==", + "dev": true, "dependencies": { "hash.js": "^1.0.3", "minimalistic-assert": "^1.0.0", @@ -5039,6 +5342,7 @@ "resolved": "https://registry.npmjs.org/http-basic/-/http-basic-8.1.3.tgz", "integrity": "sha512-/EcDMwJZh3mABI2NhGfHOGOeOZITqfkEO4p/xK+l3NpyncIHUQBoMvCSF/b5GqvKtySC2srL/GGG3+EtlqlmCw==", "dev": true, + "peer": true, "dependencies": { "caseless": "^0.12.0", "concat-stream": "^1.6.2", @@ -5053,6 +5357,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dev": true, "dependencies": { "depd": "2.0.0", "inherits": "2.0.4", @@ -5069,6 +5374,7 @@ "resolved": "https://registry.npmjs.org/http-response-object/-/http-response-object-3.0.2.tgz", "integrity": "sha512-bqX0XTF6fnXSQcEJ2Iuyr75yVakyjIDCqroJQ/aHfSdlM743Cwqoi2nDYMzLGWUcuTWGWy8AAvOKXTfiv6q9RA==", "dev": true, + "peer": true, "dependencies": { "@types/node": "^10.0.3" } @@ -5077,27 +5383,14 @@ "version": "10.17.60", "resolved": "https://registry.npmjs.org/@types/node/-/node-10.17.60.tgz", "integrity": "sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==", - "dev": true - }, - "node_modules/http-signature": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", - "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==", "dev": true, - "dependencies": { - "assert-plus": "^1.0.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" - }, - "engines": { - "node": ">=0.8", - "npm": ">=1.3.7" - } + "peer": true }, "node_modules/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==", + "dev": true, "dependencies": { "agent-base": "6", "debug": "4" @@ -5110,6 +5403,7 @@ "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, "dependencies": { "safer-buffer": ">= 2.1.2 < 3" }, @@ -5121,6 +5415,7 @@ "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", @@ -5137,23 +5432,36 @@ ] }, "node_modules/ignore": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", "dev": true, "engines": { "node": ">= 4" } }, + "node_modules/immer": { + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/immer/-/immer-10.0.2.tgz", + "integrity": "sha512-Rx3CqeqQ19sxUtYV9CU911Vhy8/721wRFnJv3REVGWUmoAcIwzifTsdmJte/MV+0/XpM35LZdQMBGkRIoLPwQA==", + "dev": true, + "peer": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/immer" + } + }, "node_modules/immutable": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.1.tgz", - "integrity": "sha512-lj9cnmB/kVS0QHsJnYKD1uo3o39nrbKxszjnqS9Fr6NB7bZzW45U6WSGBPKXDL/CvDKqDNPA4r3DoDQ8GTxo2A==" + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.5.tgz", + "integrity": "sha512-8eabxkth9gZatlwl5TBuJnCsoTADlL6ftEr7A4qgdaTsPyreilDSnUk57SO+jfKcNtxPa22U5KK6DSeAYhpBJw==", + "dev": true }, "node_modules/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==", + "dev": true, "engines": { "node": ">=8" } @@ -5162,6 +5470,7 @@ "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -5170,7 +5479,8 @@ "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true }, "node_modules/ini": { "version": "1.3.8", @@ -5179,13 +5489,13 @@ "dev": true }, "node_modules/internal-slot": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", - "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", + "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, "dependencies": { - "get-intrinsic": "^1.2.0", - "has": "^1.0.3", + "es-errors": "^1.3.0", + "hasown": "^2.0.0", "side-channel": "^1.0.4" }, "engines": { @@ -5205,19 +5515,22 @@ "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==", + "dev": true, "dependencies": { "fp-ts": "^1.0.0" } }, "node_modules/is-array-buffer": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", - "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "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, "dependencies": { "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.0", - "is-typed-array": "^1.1.10" + "get-intrinsic": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -5239,6 +5552,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==", + "dev": true, "dependencies": { "binary-extensions": "^2.0.0" }, @@ -5262,28 +5576,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-buffer": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz", - "integrity": "sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "engines": { - "node": ">=4" - } - }, "node_modules/is-callable": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", @@ -5296,6 +5588,21 @@ "url": "https://github.com/sponsors/ljharb" } }, + "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==", + "dev": true, + "dependencies": { + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-date-object": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", @@ -5315,6 +5622,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -5323,6 +5631,7 @@ "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, "engines": { "node": ">=8" } @@ -5331,6 +5640,7 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, "dependencies": { "is-extglob": "^2.1.1" }, @@ -5342,15 +5652,16 @@ "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, "engines": { "node": ">=6.5.0", "npm": ">=3" } }, "node_modules/is-negative-zero": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", - "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", "dev": true, "engines": { "node": ">= 0.4" @@ -5363,6 +5674,7 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, "engines": { "node": ">=0.12.0" } @@ -5386,6 +5698,7 @@ "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==", + "dev": true, "engines": { "node": ">=8" } @@ -5407,12 +5720,15 @@ } }, "node_modules/is-shared-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", - "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "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, "dependencies": { - "call-bind": "^1.0.2" + "call-bind": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -5449,16 +5765,12 @@ } }, "node_modules/is-typed-array": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", - "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", + "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, "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0" + "which-typed-array": "^1.1.14" }, "engines": { "node": ">= 0.4" @@ -5467,16 +5779,11 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", - "dev": true - }, "node_modules/is-unicode-supported": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true, "engines": { "node": ">=10" }, @@ -5518,27 +5825,33 @@ "unfetch": "^4.2.0" } }, - "node_modules/isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", - "dev": true - }, "node_modules/js-cookie": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-2.2.1.tgz", "integrity": "sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ==", "dev": true }, + "node_modules/js-sdsl": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.4.2.tgz", + "integrity": "sha512-dwXFwByc/ajSV6m5bcKAPwe4yDDF6D614pxmIi5odytzxRlwqF6nwoiCek80Ixc7Cvma5awClxrzFtxCQvcM8w==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/js-sdsl" + } + }, "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==", + "dev": true }, "node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, "dependencies": { "argparse": "^2.0.1" }, @@ -5546,34 +5859,28 @@ "js-yaml": "bin/js-yaml.js" } }, - "node_modules/jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", - "dev": true - }, - "node_modules/json-schema": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", - "dev": true - }, "node_modules/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 + "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, + "peer": true }, "node_modules/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==", - "dev": true + "dev": true, + "peer": true }, "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==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, "optionalDependencies": { "graceful-fs": "^4.1.6" } @@ -5587,25 +5894,11 @@ "node": "*" } }, - "node_modules/jsprim": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", - "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", - "dev": true, - "dependencies": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.4.0", - "verror": "1.10.0" - }, - "engines": { - "node": ">=0.6.0" - } - }, "node_modules/keccak": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.3.tgz", - "integrity": "sha512-JZrLIAJWuZxKbCilMpNz5Vj7Vtb4scDG3dMXLOsbzBmQGyjwE61BbW7bJkfKKCShXiQZt3T6sBgALRtmd+nZaQ==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.4.tgz", + "integrity": "sha512-3vKuW0jV8J3XNTzvfyicFR5qvxrSAGl7KIhvgOu5cmWwM7tZRj3fMbj/pfIf4be7aznbc+prBWGjywox/g2Y6Q==", + "dev": true, "hasInstallScript": true, "dependencies": { "node-addon-api": "^2.0.0", @@ -5629,67 +5922,19 @@ "version": "1.3.1", "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", "integrity": "sha512-TED5xi9gGQjGpNnvRWknrwAB1eL5GciPfVFOt3Vk1OJCVDQbzuSfrF3hkUQKlsgKrG1F+0t5W0m+Fje1jIt8rw==", + "dev": true, "optionalDependencies": { "graceful-fs": "^4.1.9" } }, - "node_modules/level": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/level/-/level-8.0.0.tgz", - "integrity": "sha512-ypf0jjAk2BWI33yzEaaotpq7fkOPALKAgDBxggO6Q9HGX2MRXn0wbP1Jn/tJv1gtL867+YOjOB49WaUF3UoJNQ==", - "dependencies": { - "browser-level": "^1.0.1", - "classic-level": "^1.2.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/level" - } - }, - "node_modules/level-supports": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/level-supports/-/level-supports-4.0.1.tgz", - "integrity": "sha512-PbXpve8rKeNcZ9C1mUicC9auIYFyGpkV9/i6g76tLgANwWhtG2v7I4xNBUlkn3lE2/dZF3Pi0ygYGtLc4RXXdA==", - "engines": { - "node": ">=12" - } - }, - "node_modules/level-transcoder": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/level-transcoder/-/level-transcoder-1.0.1.tgz", - "integrity": "sha512-t7bFwFtsQeD8cl8NIoQ2iwxA0CL/9IFw7/9gAjOonH0PWTTiRfY7Hq+Ejbsxh86tXobDQ6IOiddjNYIfOBs06w==", - "dependencies": { - "buffer": "^6.0.3", - "module-error": "^1.0.1" - }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true, + "peer": true, "engines": { - "node": ">=12" - } - }, - "node_modules/level-transcoder/node_modules/buffer": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", - "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.2.1" + "node": ">=6" } }, "node_modules/levn": { @@ -5709,6 +5954,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==", + "dev": true, "dependencies": { "p-locate": "^2.0.0", "path-exists": "^3.0.0" @@ -5720,7 +5966,8 @@ "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==", + "dev": true }, "node_modules/lodash.camelcase": { "version": "4.3.0", @@ -5728,16 +5975,31 @@ "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", "dev": true }, + "node_modules/lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==", + "dev": true, + "peer": true + }, + "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==", + "dev": true + }, "node_modules/lodash.truncate": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==", - "dev": true + "dev": true, + "peer": true }, "node_modules/log-symbols": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, "dependencies": { "chalk": "^4.1.0", "is-unicode-supported": "^0.1.0" @@ -5750,75 +6012,62 @@ } }, "node_modules/loupe": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.6.tgz", - "integrity": "sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==", + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.7.tgz", + "integrity": "sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==", "dev": true, "peer": true, "dependencies": { - "get-func-name": "^2.0.0" + "get-func-name": "^2.0.1" } }, "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==", + "dev": true }, "node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "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, "dependencies": { - "yallist": "^3.0.2" + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" } }, "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==", - "devOptional": true + "dev": true }, "node_modules/markdown-table": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-1.1.3.tgz", "integrity": "sha512-1RUZVgQlpJSPWYbFSpmudq5nHY1doEIv89gBtF0s4gW1GF2XorxcA/70M5vq7rLv0a6mhOUccRsqkwhwLCIQ2Q==", - "dev": true - }, - "node_modules/mcl-wasm": { - "version": "0.7.9", - "resolved": "https://registry.npmjs.org/mcl-wasm/-/mcl-wasm-0.7.9.tgz", - "integrity": "sha512-iJIUcQWA88IJB/5L15GnJVnSQJmf/YaxxV6zRavv83HILHaJQb6y0iFyDMdDO0gN8X37tdxmAOrH/P8B6RB8sQ==", - "engines": { - "node": ">=8.9.0" - } + "dev": true, + "peer": true }, "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, "dependencies": { "hash-base": "^3.0.0", "inherits": "^2.0.1", "safe-buffer": "^5.1.2" } }, - "node_modules/memory-level": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/memory-level/-/memory-level-1.0.0.tgz", - "integrity": "sha512-UXzwewuWeHBz5krr7EvehKcmLFNoXxGcvuYhC41tRnkrTbJohtS7kVn9akmgirtRygg+f7Yjsfi8Uu5SGSQ4Og==", - "dependencies": { - "abstract-level": "^1.0.0", - "functional-red-black-tree": "^1.0.1", - "module-error": "^1.0.1" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/memorystream": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", "integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==", + "dev": true, "engines": { "node": ">= 0.10.0" } @@ -5832,6 +6081,12 @@ "node": ">= 8" } }, + "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 + }, "node_modules/micromatch": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", @@ -5869,17 +6124,20 @@ "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==", + "dev": true }, "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==", + "dev": true }, "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, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -5912,14 +6170,16 @@ "version": "0.38.5", "resolved": "https://registry.npmjs.org/mnemonist/-/mnemonist-0.38.5.tgz", "integrity": "sha512-bZTFT5rrPKtPJxj8KSV0WkPyNxl72vQepqqVUAW2ARUpUSF2qXMB6jZj7hW5/k7C1rtpzqbD/IIbJwLXUjCHeg==", + "dev": true, "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==", + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.4.0.tgz", + "integrity": "sha512-eqhGB8JKapEYcC4ytX/xrzKforgEc3j1pGlAXVy3eRwrtAy5/nIfT1SvgGzfN0XZZxeLq0aQWkOUAmqIJiv+bA==", + "dev": true, "dependencies": { "ansi-colors": "4.1.1", "browser-stdout": "1.3.1", @@ -5928,13 +6188,12 @@ "diff": "5.0.0", "escape-string-regexp": "4.0.0", "find-up": "5.0.0", - "glob": "7.2.0", + "glob": "8.1.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", @@ -5949,16 +6208,13 @@ }, "engines": { "node": ">= 14.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mochajs" } }, "node_modules/mocha/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==", + "dev": true, "engines": { "node": ">=6" } @@ -5967,25 +6223,43 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, "dependencies": { "balanced-match": "^1.0.0" } }, - "node_modules/mocha/node_modules/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==", + "node_modules/mocha/node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "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": ">=10" + "node": ">= 8.10.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "optionalDependencies": { + "fsevents": "~2.3.2" } }, "node_modules/mocha/node_modules/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==", + "dev": true, "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" @@ -5997,18 +6271,30 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/mocha/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==", + "node_modules/mocha/node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/mocha/node_modules/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==", + "dev": true, "dependencies": { "p-locate": "^5.0.0" }, @@ -6023,6 +6309,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", + "dev": true, "dependencies": { "brace-expansion": "^2.0.1" }, @@ -6033,12 +6320,14 @@ "node_modules/mocha/node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true }, "node_modules/mocha/node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, "dependencies": { "yocto-queue": "^0.1.0" }, @@ -6053,6 +6342,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==", + "dev": true, "dependencies": { "p-limit": "^3.0.2" }, @@ -6067,6 +6357,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, "engines": { "node": ">=8" } @@ -6075,6 +6366,7 @@ "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -6085,35 +6377,32 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/module-error": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/module-error/-/module-error-1.0.2.tgz", - "integrity": "sha512-0yuvsqSCv8LbaOKhnsQ/T5JhyFlCYLPXK3U2sgV10zoKQwzs/MyfuQUOZQ1V/6OCOJsK/TRgNVrPuPDqtdMFtA==", - "engines": { - "node": ">=10" - } - }, "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==" + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true }, - "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==", + "node_modules/ndjson": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ndjson/-/ndjson-2.0.0.tgz", + "integrity": "sha512-nGl7LRGrzugTtaFcJMhLbpzJM6XdivmbkdlaGcrk/LXg2KL/YBC6z1g70xh0/al+oFuVFP8N8kiWRucmeEH/qQ==", + "dev": true, + "peer": true, + "dependencies": { + "json-stringify-safe": "^5.0.1", + "minimist": "^1.2.5", + "readable-stream": "^3.6.0", + "split2": "^3.0.0", + "through2": "^4.0.0" + }, "bin": { - "nanoid": "bin/nanoid.cjs" + "ndjson": "cli.js" }, "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + "node": ">=10" } }, - "node_modules/napi-macros": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/napi-macros/-/napi-macros-2.2.2.tgz", - "integrity": "sha512-hmEVtAGYzVQpCKdbQea4skABsdXW4RUh5t5mJ2zzqowJS2OyXZTU1KhDVFhx+NlWZ4ap9mqR9TcDO3LTTttd+g==" - }, "node_modules/neo-async": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", @@ -6123,7 +6412,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==", + "dev": true }, "node_modules/node-emoji": { "version": "1.11.0", @@ -6134,29 +6424,10 @@ "lodash": "^4.17.21" } }, - "node_modules/node-environment-flags": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.6.tgz", - "integrity": "sha512-5Evy2epuL+6TM0lCQGpFIj6KwiEsGh1SrHUhTbNX+sLbBtjidPZFAnVK9y5yU1+h//RitLbRHTIMyxQPtxMdHw==", - "dev": true, - "dependencies": { - "object.getownpropertydescriptors": "^2.0.3", - "semver": "^5.7.0" - } - }, - "node_modules/node-environment-flags/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, "node_modules/node-fetch": { - "version": "2.6.12", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.12.tgz", - "integrity": "sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", "dev": true, "dependencies": { "whatwg-url": "^5.0.0" @@ -6174,9 +6445,10 @@ } }, "node_modules/node-gyp-build": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.6.0.tgz", - "integrity": "sha512-NTZVKn9IylLwUzaKjkas1e4u2DLNcV4rdYagA4PWdPwW87Bi7z+BznyKSRwS/761tV/lzCGXplWsiaMjLqP2zQ==", + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.0.tgz", + "integrity": "sha512-u6fs2AEUljNho3EYTJNBfImO5QTo/J/1Etd+NVdCj7qWKUSN/bSLkZwhDv7I+w/MSC6qJ4cknepkAYykDdK8og==", + "dev": true, "bin": { "node-gyp-build": "bin.js", "node-gyp-build-optional": "optional.js", @@ -6208,6 +6480,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -6232,28 +6505,21 @@ "integrity": "sha512-XWwnNNFCuuSQ0m3r3C4LE3EiORltHd9M05pq6FOlVeiophzRbMo50Sbz1ehl8K3Z+jw9+vmgnXefY1hz8X+2wA==", "dev": true }, - "node_modules/oauth-sign": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", - "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", - "dev": true, - "engines": { - "node": "*" - } - }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", "dev": true, + "peer": true, "engines": { "node": ">=0.10.0" } }, "node_modules/object-inspect": { - "version": "1.12.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", - "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "dev": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -6268,34 +6534,18 @@ } }, "node_modules/object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "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, "dependencies": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" }, "engines": { "node": ">= 0.4" - } - }, - "node_modules/object.getownpropertydescriptors": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.6.tgz", - "integrity": "sha512-lq+61g26E/BgHv0ZTFgRvi7NMEPuAxLkFU7rukXjc/AlwH4Am5xXVnIXy3un1bg/JPbXHrixRkK1itUzzPiIjQ==", - "dev": true, - "dependencies": { - "array.prototype.reduce": "^1.0.5", - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.21.2", - "safe-array-concat": "^1.0.0" - }, - "engines": { - "node": ">= 0.8" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -6304,12 +6554,14 @@ "node_modules/obliterator": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/obliterator/-/obliterator-2.0.4.tgz", - "integrity": "sha512-lgHwxlxV1qIg1Eap7LgIeoBWIMFibOjbrYPIPJZcI1mmGAI2m3lNYpK12Y+GBdPQ0U1hRwSord7GIaawz962qQ==" + "integrity": "sha512-lgHwxlxV1qIg1Eap7LgIeoBWIMFibOjbrYPIPJZcI1mmGAI2m3lNYpK12Y+GBdPQ0U1hRwSord7GIaawz962qQ==", + "dev": true }, "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==", + "dev": true, "dependencies": { "wrappy": "1" } @@ -6335,12 +6587,14 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/ordinal/-/ordinal-1.0.3.tgz", "integrity": "sha512-cMddMgb2QElm8G7vdaa02jhUNbTSrhsgAGUz1OokD83uJTwSUn+nKoNoKVVaRa08yF6sgfO7Maou1+bgLd9rdQ==", - "dev": true + "dev": true, + "peer": true }, "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==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -6349,6 +6603,7 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, "dependencies": { "p-try": "^1.0.0" }, @@ -6360,6 +6615,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==", + "dev": true, "dependencies": { "p-limit": "^1.1.0" }, @@ -6371,6 +6627,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dev": true, "dependencies": { "aggregate-error": "^3.0.0" }, @@ -6385,6 +6642,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==", + "dev": true, "engines": { "node": ">=4" } @@ -6393,12 +6651,14 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/parse-cache-control/-/parse-cache-control-1.0.1.tgz", "integrity": "sha512-60zvsJReQPX5/QP0Kzfd/VrpjScIQ7SHBW6bFCYfEP+fp0Eppr1SHhIO5nd1PjZtvclzSzES9D/p5nFJurwfWg==", - "dev": true + "dev": true, + "peer": true }, "node_modules/path-exists": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "dev": true, "engines": { "node": ">=4" } @@ -6407,6 +6667,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -6414,7 +6675,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==", + "dev": true }, "node_modules/path-type": { "version": "4.0.0", @@ -6439,6 +6701,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", + "dev": true, "dependencies": { "create-hash": "^1.1.2", "create-hmac": "^1.1.4", @@ -6450,16 +6713,11 @@ "node": ">=0.12" } }, - "node_modules/performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==", - "dev": true - }, "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, "engines": { "node": ">=8.6" }, @@ -6476,6 +6734,15 @@ "node": ">=6" } }, + "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==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/prelude-ls": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", @@ -6504,17 +6771,33 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true + "dev": true, + "peer": true }, "node_modules/promise": { "version": "8.3.0", "resolved": "https://registry.npmjs.org/promise/-/promise-8.3.0.tgz", "integrity": "sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg==", "dev": true, + "peer": true, "dependencies": { "asap": "~2.0.6" } }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dev": true, + "peer": true, + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/proper-lockfile": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/proper-lockfile/-/proper-lockfile-4.1.2.tgz", @@ -6541,27 +6824,24 @@ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", "dev": true }, - "node_modules/psl": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", - "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", - "dev": true - }, "node_modules/punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, + "peer": true, "engines": { "node": ">=6" } }, "node_modules/qs": { - "version": "6.11.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.2.tgz", - "integrity": "sha512-tDNIz22aBzCDxLtVH++VnTfzxlfeK5CbqohpSqpJgj1Wg/cQbStNAz3NuqCs5vV+pjBsK4x4pN9HlVh7rcYRiA==", + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.12.0.tgz", + "integrity": "sha512-trVZiI6RMOkO476zLGaBIzszOdFPnCCXHPG9kn0yuS1uz6xdVxPfZdB3vUig9pxPFDM9BRAgz/YUIVQ1/vuiUg==", + "dev": true, + "peer": true, "dependencies": { - "side-channel": "^1.0.4" + "side-channel": "^1.0.6" }, "engines": { "node": ">=0.6" @@ -6574,6 +6854,7 @@ "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, "funding": [ { "type": "github", @@ -6593,6 +6874,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, "dependencies": { "safe-buffer": "^5.1.0" } @@ -6601,6 +6883,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==", + "dev": true, "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", @@ -6615,6 +6898,7 @@ "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -6628,6 +6912,7 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, "dependencies": { "picomatch": "^2.2.1" }, @@ -6669,14 +6954,15 @@ } }, "node_modules/regexp.prototype.flags": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz", - "integrity": "sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", + "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "functions-have-names": "^1.2.3" + "call-bind": "^1.0.6", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "set-function-name": "^2.0.1" }, "engines": { "node": ">= 0.4" @@ -6690,6 +6976,7 @@ "resolved": "https://registry.npmjs.org/req-cwd/-/req-cwd-2.0.0.tgz", "integrity": "sha512-ueoIoLo1OfB6b05COxAA9UpeoscNpYyM+BqYlA7H6LVF4hKGPXQQSSaD2YmvDVJMkk4UDpAHIeU1zG53IqjvlQ==", "dev": true, + "peer": true, "dependencies": { "req-from": "^2.0.0" }, @@ -6702,6 +6989,7 @@ "resolved": "https://registry.npmjs.org/req-from/-/req-from-2.0.0.tgz", "integrity": "sha512-LzTfEVDVQHBRfjOUMgNBA+V6DWsSnoeKzf42J7l0xa/B4jyPOuuF5MlNSmomLNGemWTnV2TIdjSSLnEn95fOQA==", "dev": true, + "peer": true, "dependencies": { "resolve-from": "^3.0.0" }, @@ -6709,108 +6997,11 @@ "node": ">=4" } }, - "node_modules/request": { - "version": "2.88.2", - "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", - "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", - "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", - "dev": true, - "dependencies": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~2.3.2", - "har-validator": "~5.1.3", - "http-signature": "~1.2.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "oauth-sign": "~0.9.0", - "performance-now": "^2.1.0", - "qs": "~6.5.2", - "safe-buffer": "^5.1.2", - "tough-cookie": "~2.5.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.3.2" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/request-promise-core": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.4.tgz", - "integrity": "sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw==", - "dev": true, - "dependencies": { - "lodash": "^4.17.19" - }, - "engines": { - "node": ">=0.10.0" - }, - "peerDependencies": { - "request": "^2.34" - } - }, - "node_modules/request-promise-native": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.9.tgz", - "integrity": "sha512-wcW+sIUiWnKgNY0dqCpOZkUbF/I+YPi+f09JZIDa39Ec+q82CpSYniDp+ISgTTbKmnpJWASeJBPZmoxH84wt3g==", - "deprecated": "request-promise-native has been deprecated because it extends the now deprecated request package, see https://github.com/request/request/issues/3142", - "dev": true, - "dependencies": { - "request-promise-core": "1.1.4", - "stealthy-require": "^1.1.1", - "tough-cookie": "^2.3.3" - }, - "engines": { - "node": ">=0.12.0" - }, - "peerDependencies": { - "request": "^2.34" - } - }, - "node_modules/request/node_modules/form-data": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", - "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", - "dev": true, - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.6", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 0.12" - } - }, - "node_modules/request/node_modules/qs": { - "version": "6.5.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", - "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", - "dev": true, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/request/node_modules/uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", - "dev": true, - "bin": { - "uuid": "bin/uuid" - } - }, "node_modules/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==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -6819,20 +7010,16 @@ "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, "engines": { "node": ">=0.10.0" } }, - "node_modules/require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true - }, "node_modules/resolve": { "version": "1.17.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", + "dev": true, "dependencies": { "path-parse": "^1.0.6" }, @@ -6845,6 +7032,7 @@ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", "integrity": "sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw==", "dev": true, + "peer": true, "engines": { "node": ">=4" } @@ -6872,6 +7060,7 @@ "version": "2.7.1", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, "dependencies": { "glob": "^7.1.3" }, @@ -6883,6 +7072,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "dev": true, "dependencies": { "hash-base": "^3.0.0", "inherits": "^2.0.1" @@ -6892,40 +7082,19 @@ "version": "2.2.7", "resolved": "https://registry.npmjs.org/rlp/-/rlp-2.2.7.tgz", "integrity": "sha512-d5gdPmgQ0Z+AklL2NVXr/IoSjNZFfTVvQWzL/AM2AOcSzYP2xjlb0AC8YyCLc41MSNf6P6QVtjgPdmVtzb+4lQ==", + "dev": true, "dependencies": { - "bn.js": "^5.2.0" - }, - "bin": { - "rlp": "bin/rlp" - } - }, - "node_modules/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, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "queue-microtask": "^1.2.2" + "bn.js": "^5.2.0" + }, + "bin": { + "rlp": "bin/rlp" } }, - "node_modules/run-parallel-limit": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/run-parallel-limit/-/run-parallel-limit-1.1.0.tgz", - "integrity": "sha512-jJA7irRNM91jaKc3Hcl1npHsFLOXOoTkPCUL1JEa1R82O2miplXXRaGdjW/KM/98YQWDhJLiSs793CnXfblJUw==", + "node_modules/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, "funding": [ { "type": "github", @@ -6944,19 +7113,29 @@ "queue-microtask": "^1.2.2" } }, - "node_modules/rustbn.js": { + "node_modules/rust-verkle-wasm": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/rust-verkle-wasm/-/rust-verkle-wasm-0.0.1.tgz", + "integrity": "sha512-BN6fiTsxcd2dCECz/cHtGTt9cdLJR925nh7iAuRcj8ymKw7OOaPmCneQZ7JePOJ/ia27TjEL91VdOi88Yf+mcA==", + "dev": true + }, + "node_modules/rustbn-wasm": { "version": "0.2.0", - "resolved": "https://registry.npmjs.org/rustbn.js/-/rustbn.js-0.2.0.tgz", - "integrity": "sha512-4VlvkRUuCJvr2J6Y0ImW7NvTCriMi7ErOAqWk1y69vAdoNIzCF3yPmgeNzx+RQTLEDFq5sHfscn1MwHxP9hNfA==" + "resolved": "https://registry.npmjs.org/rustbn-wasm/-/rustbn-wasm-0.2.0.tgz", + "integrity": "sha512-FThvYFNTqrEKGqXuseeg0zR7yROh/6U1617mCHF68OVqrN1tNKRN7Tdwy4WayPVsCmmK+eMxtIZX1qL6JxTkMg==", + "dev": true, + "dependencies": { + "@scure/base": "^1.1.1" + } }, "node_modules/safe-array-concat": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.0.tgz", - "integrity": "sha512-9dVEFruWIsnie89yym+xWTAYASdpw3CJV7Li/6zBewGf9z2i1j31rP6jnY0pHEO4QZh6N0K11bFjWmdR8UGdPQ==", + "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, "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.0", + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4", "has-symbols": "^1.0.3", "isarray": "^2.0.5" }, @@ -6977,6 +7156,7 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, "funding": [ { "type": "github", @@ -6993,15 +7173,18 @@ ] }, "node_modules/safe-regex-test": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", - "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "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, "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", "is-regex": "^1.1.4" }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -7009,7 +7192,8 @@ "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==", + "dev": true }, "node_modules/sc-istanbul": { "version": "0.4.6", @@ -7045,12 +7229,6 @@ "sprintf-js": "~1.0.2" } }, - "node_modules/sc-istanbul/node_modules/async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha512-nSVgobk4rv61R9PUSDtYt7mPVB2olxNR5RWJcAsH676/ef11bUZwvu7+RGYrYauVdDPcO519v68wRhXQtxsV9w==", - "dev": true - }, "node_modules/sc-istanbul/node_modules/glob": { "version": "5.0.15", "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", @@ -7123,12 +7301,14 @@ "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==", + "dev": true }, "node_modules/secp256k1": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/secp256k1/-/secp256k1-4.0.3.tgz", "integrity": "sha512-NLZVf+ROMxwtEj3Xa562qgv2BK5e2WNmXPiOdVIPLgs6lyTzMvBq0aWTYMI5XCP9jZMVKOcqZLw/Wc4vDkuxhA==", + "dev": true, "hasInstallScript": true, "dependencies": { "elliptic": "^6.5.4", @@ -7143,6 +7323,7 @@ "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, "bin": { "semver": "bin/semver.js" } @@ -7151,30 +7332,60 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", + "dev": true, "dependencies": { "randombytes": "^2.1.0" } }, - "node_modules/set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", - "dev": true + "node_modules/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==", + "dev": true, + "dependencies": { + "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" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/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, + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "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 }, "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==", + "dev": true }, "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, "dependencies": { "inherits": "^2.0.1", "safe-buffer": "^5.0.1" @@ -7188,6 +7399,7 @@ "resolved": "https://registry.npmjs.org/sha1/-/sha1-1.1.1.tgz", "integrity": "sha512-dZBS6OrMjtgVkopB1Gmo4RQCDKiZsqcpAQpkV/aaj+FCrCg8r4I4qMkDPQjBgLIxlmu9k4nUbWq6ohXahOneYA==", "dev": true, + "peer": true, "dependencies": { "charenc": ">= 0.0.1", "crypt": ">= 0.0.1" @@ -7214,13 +7426,18 @@ } }, "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==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "dev": true, "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -7232,6 +7449,13 @@ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "dev": true }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true, + "peer": true + }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -7246,6 +7470,7 @@ "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", "dev": true, + "peer": true, "dependencies": { "ansi-styles": "^4.0.0", "astral-regex": "^2.0.0", @@ -7258,39 +7483,6 @@ "url": "https://github.com/chalk/slice-ansi?sponsor=1" } }, - "node_modules/slice-ansi/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/slice-ansi/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==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/slice-ansi/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==", - "dev": true - }, "node_modules/solc": { "version": "0.8.17", "resolved": "https://registry.npmjs.org/solc/-/solc-0.8.17.tgz", @@ -7322,22 +7514,24 @@ } }, "node_modules/solidity-ast": { - "version": "0.4.49", - "resolved": "https://registry.npmjs.org/solidity-ast/-/solidity-ast-0.4.49.tgz", - "integrity": "sha512-Pr5sCAj1SFqzwFZw1HPKSq0PehlQNdM8GwKyAVYh2DOn7/cCK8LUKD1HeHnKtTgBW7hi9h4nnnan7hpAg5RhWQ==", - "dev": true + "version": "0.4.56", + "resolved": "https://registry.npmjs.org/solidity-ast/-/solidity-ast-0.4.56.tgz", + "integrity": "sha512-HgmsA/Gfklm/M8GFbCX/J1qkVH0spXHgALCNZ8fA8x5X+MFdn/8CP2gr5OVyXjXw6RZTPC/Sxl2RUDQOXyNMeA==", + "dev": true, + "dependencies": { + "array.prototype.findlast": "^1.2.2" + } }, "node_modules/solidity-coverage": { - "version": "0.8.5", - "resolved": "https://registry.npmjs.org/solidity-coverage/-/solidity-coverage-0.8.5.tgz", - "integrity": "sha512-6C6N6OV2O8FQA0FWA95FdzVH+L16HU94iFgg5wAFZ29UpLFkgNI/DRR2HotG1bC0F4gAc/OMs2BJI44Q/DYlKQ==", + "version": "0.8.11", + "resolved": "https://registry.npmjs.org/solidity-coverage/-/solidity-coverage-0.8.11.tgz", + "integrity": "sha512-yy0Yk+olovBbXn0Me8BWULmmv7A69ZKkP5aTOJGOO8u61Tu2zS989erfjtFlUjDnfWtxRAVkd8BsQD704yLWHw==", "dev": true, "dependencies": { "@ethersproject/abi": "^5.0.9", - "@solidity-parser/parser": "^0.16.0", + "@solidity-parser/parser": "^0.18.0", "chalk": "^2.4.2", "death": "^1.1.0", - "detect-port": "^1.3.0", "difflib": "^0.2.4", "fs-extra": "^8.1.0", "ghost-testrpc": "^0.0.2", @@ -7345,7 +7539,7 @@ "globby": "^10.0.1", "jsonschema": "^1.2.4", "lodash": "^4.17.15", - "mocha": "10.2.0", + "mocha": "^10.2.0", "node-emoji": "^1.10.0", "pify": "^4.0.1", "recursive-readdir": "^2.2.2", @@ -7362,12 +7556,21 @@ } }, "node_modules/solidity-coverage/node_modules/@solidity-parser/parser": { - "version": "0.16.2", - "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.16.2.tgz", - "integrity": "sha512-PI9NfoA3P8XK2VBkK5oIfRgKDsicwDZfkVq9ZTBCQYGOP1N2owgY2dyLGyU5/J/hQs8KRk55kdmvTLjy3Mu3vg==", + "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 + }, + "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, "dependencies": { - "antlr4ts": "^0.5.0-alpha.4" + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" } }, "node_modules/solidity-coverage/node_modules/chalk": { @@ -7384,6 +7587,30 @@ "node": ">=4" } }, + "node_modules/solidity-coverage/node_modules/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, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/solidity-coverage/node_modules/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 + }, + "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, + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/solidity-coverage/node_modules/fs-extra": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", @@ -7398,22 +7625,28 @@ "node": ">=6 <7 || >=8" } }, - "node_modules/solidity-coverage/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==", + "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, - "dependencies": { - "yallist": "^4.0.0" - }, "engines": { - "node": ">=10" + "node": ">=4" + } + }, + "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, + "optionalDependencies": { + "graceful-fs": "^4.1.6" } }, "node_modules/solidity-coverage/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==", + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", "dev": true, "dependencies": { "lru-cache": "^6.0.0" @@ -7437,16 +7670,19 @@ "node": ">=4" } }, - "node_modules/solidity-coverage/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true + "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, + "engines": { + "node": ">= 4.0.0" + } }, "node_modules/solidity-docgen": { - "version": "0.6.0-beta.35", - "resolved": "https://registry.npmjs.org/solidity-docgen/-/solidity-docgen-0.6.0-beta.35.tgz", - "integrity": "sha512-9QdwK1THk/MWIdq1PEW/6dvtND0pUqpFTsbKwwU9YQIMYuRhH1lek9SsgnsGGYtdJ0VTrXXcVT30q20a8Y610A==", + "version": "0.6.0-beta.36", + "resolved": "https://registry.npmjs.org/solidity-docgen/-/solidity-docgen-0.6.0-beta.36.tgz", + "integrity": "sha512-f/I5G2iJgU1h0XrrjRD0hHMr7C10u276vYvm//rw1TzFcYQ4xTOyAoi9oNAHRU0JU4mY9eTuxdVc2zahdMuhaQ==", "dev": true, "dependencies": { "handlebars": "^4.7.7", @@ -7473,6 +7709,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==", + "dev": true, "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" @@ -7482,51 +7719,32 @@ "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, "engines": { "node": ">=0.10.0" } }, - "node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true - }, - "node_modules/sshpk": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.17.0.tgz", - "integrity": "sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==", + "node_modules/split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", "dev": true, + "peer": true, "dependencies": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - }, - "bin": { - "sshpk-conv": "bin/sshpk-conv", - "sshpk-sign": "bin/sshpk-sign", - "sshpk-verify": "bin/sshpk-verify" - }, - "engines": { - "node": ">=0.10.0" + "readable-stream": "^3.0.0" } }, - "node_modules/sshpk/node_modules/tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", "dev": true }, "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==", + "dev": true, "dependencies": { "type-fest": "^0.7.1" }, @@ -7538,6 +7756,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==", + "dev": true, "engines": { "node": ">=8" } @@ -7546,31 +7765,16 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/stealthy-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz", - "integrity": "sha512-ZnWpYnYugiOVEY5GkcuJK1io5V8QmNYChG62gSit9pQVGErXtrKuPC55ITaVSukmMta5qpMU7vqLt2Lnni4f/g==", "dev": true, "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/streamsearch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", - "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", - "engines": { - "node": ">=10.0.0" + "node": ">= 0.8" } }, "node_modules/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==", + "dev": true, "dependencies": { "safe-buffer": "~5.2.0" } @@ -7585,6 +7789,7 @@ "version": "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, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -7595,14 +7800,15 @@ } }, "node_modules/string.prototype.trim": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz", - "integrity": "sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==", + "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, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.0", + "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -7612,28 +7818,31 @@ } }, "node_modules/string.prototype.trimend": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", - "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==", + "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, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/string.prototype.trimstart": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz", - "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==", + "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, "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -7643,6 +7852,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, "dependencies": { "ansi-regex": "^5.0.1" }, @@ -7654,6 +7864,7 @@ "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, "dependencies": { "is-hex-prefixed": "1.0.0" }, @@ -7666,6 +7877,7 @@ "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, "engines": { "node": ">=8" }, @@ -7677,6 +7889,7 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, "dependencies": { "has-flag": "^4.0.0" }, @@ -7684,19 +7897,12 @@ "node": ">=8" } }, - "node_modules/supports-color/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/sync-request": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/sync-request/-/sync-request-6.1.0.tgz", "integrity": "sha512-8fjNkrNlNCrVc/av+Jn+xxqfCjYaBoHqCsDz6mt030UMxJGr+GSfCV1dQt2gRtlL63+VPidwDVLr7V2OcTSdRw==", "dev": true, + "peer": true, "dependencies": { "http-response-object": "^3.0.1", "sync-rpc": "^1.2.1", @@ -7711,15 +7917,17 @@ "resolved": "https://registry.npmjs.org/sync-rpc/-/sync-rpc-1.3.6.tgz", "integrity": "sha512-J8jTXuZzRlvU7HemDgHi3pGnh/rkoqR/OZSjhTyyZrEkkYQbk7Z33AXp37mkPfPpfdOuj7Ex3H/TJM1z48uPQw==", "dev": true, + "peer": true, "dependencies": { "get-port": "^3.1.0" } }, "node_modules/table": { - "version": "6.8.1", - "resolved": "https://registry.npmjs.org/table/-/table-6.8.1.tgz", - "integrity": "sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA==", + "version": "6.8.2", + "resolved": "https://registry.npmjs.org/table/-/table-6.8.2.tgz", + "integrity": "sha512-w2sfv80nrAh2VCbqR5AK27wswXhqcck2AhfnNW76beQXskGZ1V12GwS//yYVa3d3fcvAip2OUnbDAjW2k3v9fA==", "dev": true, + "peer": true, "dependencies": { "ajv": "^8.0.1", "lodash.truncate": "^4.4.2", @@ -7748,49 +7956,28 @@ }, "node_modules/table-layout/node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/table-layout/node_modules/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, - "engines": { - "node": ">=8" - } - }, - "node_modules/table/node_modules/ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.2.tgz", + "integrity": "sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg==", + "dev": true, + "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", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true + "node_modules/table-layout/node_modules/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, + "engines": { + "node": ">=8" + } }, "node_modules/then-request": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/then-request/-/then-request-6.0.2.tgz", "integrity": "sha512-3ZBiG7JvP3wbDzA9iNY5zJQcHL4jn/0BWtXIkagfz7QgOL/LqjCEOBQuJNZfu0XYnv5JhKh+cDxCPM4ILrqruA==", "dev": true, + "peer": true, "dependencies": { "@types/concat-stream": "^1.6.0", "@types/form-data": "0.0.33", @@ -7812,13 +7999,15 @@ "version": "8.10.66", "resolved": "https://registry.npmjs.org/@types/node/-/node-8.10.66.tgz", "integrity": "sha512-tktOkFUA4kXx2hhhrB8bIFb5TbwzS4uOhKEmwiD+NoiL0qtP2OQ9mFldbgD4dV1djrlBYP6eBuQZiWjuHUpqFw==", - "dev": true + "dev": true, + "peer": true }, "node_modules/then-request/node_modules/form-data": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz", "integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==", "dev": true, + "peer": true, "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.6", @@ -7828,10 +8017,21 @@ "node": ">= 0.12" } }, + "node_modules/through2": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", + "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", + "dev": true, + "peer": true, + "dependencies": { + "readable-stream": "3" + } + }, "node_modules/tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, "dependencies": { "os-tmpdir": "~1.0.2" }, @@ -7843,6 +8043,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==", + "dev": true, "dependencies": { "is-number": "^7.0.0" }, @@ -7854,21 +8055,9 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", - "engines": { - "node": ">=0.6" - } - }, - "node_modules/tough-cookie": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", - "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", "dev": true, - "dependencies": { - "psl": "^1.1.28", - "punycode": "^2.1.1" - }, "engines": { - "node": ">=0.8" + "node": ">=0.6" } }, "node_modules/tr46": { @@ -7902,10 +8091,10 @@ } }, "node_modules/ts-node": { - "version": "10.9.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", - "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", - "devOptional": true, + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", + "dev": true, "dependencies": { "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", @@ -7948,7 +8137,7 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "devOptional": true, + "dev": true, "engines": { "node": ">=0.3.1" } @@ -7956,34 +8145,26 @@ "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==", + "dev": true }, "node_modules/tsort": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/tsort/-/tsort-0.0.1.tgz", - "integrity": "sha512-Tyrf5mxF8Ofs1tNoxA13lFeZ2Zrbd6cKbuH3V+MQ5sb6DtBj5FjrXVsRWT8YvNAQTqNoz66dz1WsbigI22aEnw==" - }, - "node_modules/tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", - "dev": true, - "dependencies": { - "safe-buffer": "^5.0.1" - }, - "engines": { - "node": "*" - } + "integrity": "sha512-Tyrf5mxF8Ofs1tNoxA13lFeZ2Zrbd6cKbuH3V+MQ5sb6DtBj5FjrXVsRWT8YvNAQTqNoz66dz1WsbigI22aEnw==", + "dev": true }, "node_modules/tweetnacl": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", - "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==" + "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==", + "dev": true }, "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-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw==", + "dev": true }, "node_modules/type-check": { "version": "0.3.2", @@ -8002,6 +8183,7 @@ "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", "dev": true, + "peer": true, "engines": { "node": ">=4" } @@ -8010,6 +8192,7 @@ "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==", + "dev": true, "engines": { "node": ">=10" }, @@ -8018,9 +8201,9 @@ } }, "node_modules/typechain": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/typechain/-/typechain-8.2.0.tgz", - "integrity": "sha512-tZqhqjxJ9xAS/Lh32jccTjMkpx7sTdUVVHAy5Bf0TIer5QFNYXotiX74oCvoVYjyxUKDK3MXHtMFzMyD3kE+jg==", + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/typechain/-/typechain-8.3.2.tgz", + "integrity": "sha512-x/sQYr5w9K7yv3es7jo4KTX05CLxOf7TRWwoHlrjRh8H82G64g+k7VuWPJlgMo6qrjfCulOdfBjiaDtmhFYD/Q==", "dev": true, "dependencies": { "@types/prettier": "^2.1.1", @@ -8041,6 +8224,20 @@ "typescript": ">=4.3.0" } }, + "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, + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, "node_modules/typechain/node_modules/glob": { "version": "7.1.7", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", @@ -8061,6 +8258,15 @@ "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, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, "node_modules/typechain/node_modules/mkdirp": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", @@ -8073,17 +8279,60 @@ "node": ">=10" } }, + "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, + "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==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.13" + }, + "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==", + "dev": true, + "dependencies": { + "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" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/typed-array-byte-offset": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz", - "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", + "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", "dev": true, "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", "for-each": "^0.3.3", - "has-proto": "^1.0.1", - "is-typed-array": "^1.1.10" + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" }, "engines": { "node": ">= 0.4" @@ -8093,14 +8342,20 @@ } }, "node_modules/typed-array-length": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", - "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", + "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", "dev": true, "dependencies": { - "call-bind": "^1.0.2", + "call-bind": "^1.0.7", "for-each": "^0.3.3", - "is-typed-array": "^1.1.9" + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -8110,19 +8365,20 @@ "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", - "dev": true + "dev": true, + "peer": true }, "node_modules/typescript": { - "version": "4.9.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", - "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", - "devOptional": true, + "version": "5.4.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.3.tgz", + "integrity": "sha512-KrPd3PKaCLr78MalgiwJnA25Nm8HAmdwN3mYUYZgG/wizIo9EainNVQI9/yDavtVFRN2h3k8uf3GLHuhDMgEHg==", + "dev": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" }, "engines": { - "node": ">=4.2.0" + "node": ">=14.17" } }, "node_modules/typical": { @@ -8163,16 +8419,23 @@ } }, "node_modules/undici": { - "version": "5.22.1", - "resolved": "https://registry.npmjs.org/undici/-/undici-5.22.1.tgz", - "integrity": "sha512-Ji2IJhFXZY0x/0tVBXeQwgPlLWw13GVzpsWPQ3rV50IFMMof2I55PZZxtm4P6iNq+L5znYN9nSTAq0ZyE6lSJw==", + "version": "5.28.3", + "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.3.tgz", + "integrity": "sha512-3ItfzbrhDlINjaP0duwnNsKpDQk3acHI3gVJ1z4fmwMK31k5G9OVIAMLSIaP6w4FaGkaAkN6zaQO9LUvZ1t7VA==", + "dev": true, "dependencies": { - "busboy": "^1.6.0" + "@fastify/busboy": "^2.0.0" }, "engines": { "node": ">=14.0" } }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + }, "node_modules/unfetch": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/unfetch/-/unfetch-4.2.0.tgz", @@ -8180,17 +8443,19 @@ "dev": true }, "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==", + "dev": true, "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==", + "dev": true, "engines": { "node": ">= 0.8" } @@ -8200,6 +8465,7 @@ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, + "peer": true, "dependencies": { "punycode": "^2.1.0" } @@ -8213,12 +8479,14 @@ "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==", + "dev": true }, "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==", + "dev": true, "bin": { "uuid": "dist/bin/uuid" } @@ -8227,31 +8495,18 @@ "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==", - "devOptional": true - }, - "node_modules/verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", - "dev": true, - "engines": [ - "node >=0.6.0" - ], - "dependencies": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } + "dev": true }, "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, "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", @@ -8261,6 +8516,42 @@ "node": ">=8.0.0" } }, + "node_modules/web3-utils/node_modules/@noble/curves": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.3.0.tgz", + "integrity": "sha512-t01iSXPuN+Eqzb4eBX0S5oubSqXbK/xXa1Ne18Hj8f9pStxztHCE2gfboSp/dZRLSqfuLpRK2nDXDK+W9puocA==", + "dev": true, + "dependencies": { + "@noble/hashes": "1.3.3" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/web3-utils/node_modules/@noble/hashes": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.3.tgz", + "integrity": "sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA==", + "dev": true, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/web3-utils/node_modules/ethereum-cryptography": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.1.3.tgz", + "integrity": "sha512-BlwbIL7/P45W8FGW2r7LGuvoEZ+7PWsniMvQ4p5s2xCyw9tmaDlpfsN9HjAucbF+t/qpVHwZUisgfK24TCW8aA==", + "dev": true, + "dependencies": { + "@noble/curves": "1.3.0", + "@noble/hashes": "1.3.3", + "@scure/bip32": "1.3.3", + "@scure/bip39": "1.2.2" + } + }, "node_modules/webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", @@ -8305,24 +8596,17 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/which-module": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", - "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", - "dev": true - }, "node_modules/which-typed-array": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.10.tgz", - "integrity": "sha512-uxoA5vLUfRPdjCuJ1h5LlYdmTLbYfums398v3WLkM+i/Wltl2/XyZpQWKbN++ck5L64SR/grOHqtXCUKmlZPNA==", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", + "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", "dev": true, "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", "for-each": "^0.3.3", "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0", - "is-typed-array": "^1.1.10" + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -8331,62 +8615,22 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/wide-align": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", - "dev": true, - "dependencies": { - "string-width": "^1.0.2 || 2" - } - }, - "node_modules/wide-align/node_modules/ansi-regex": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", - "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/wide-align/node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/wide-align/node_modules/string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "dependencies": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/wide-align/node_modules/strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==", + "node_modules/widest-line": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", + "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", "dev": true, "dependencies": { - "ansi-regex": "^3.0.0" + "string-width": "^4.0.0" }, "engines": { - "node": ">=4" + "node": ">=8" } }, "node_modules/word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", "dev": true, "engines": { "node": ">=0.10.0" @@ -8423,12 +8667,14 @@ "node_modules/workerpool": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", - "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==" + "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", + "dev": true }, "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==", + "dev": true, "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -8441,47 +8687,19 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/wrap-ansi/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, "node_modules/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==", + "dev": true }, "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.5.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", + "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", + "dev": true, "engines": { - "node": ">=8.3.0" + "node": ">=10.0.0" }, "peerDependencies": { "bufferutil": "^4.0.1", @@ -8496,32 +8714,26 @@ } } }, - "node_modules/xmlhttprequest": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz", - "integrity": "sha512-58Im/U0mlVBLM38NdZjHyhuMtCqa61469k2YP/AaPbvCoV9aQGUpbJBj1QRm2ytRiVQBD/fsw7L2bJGDVQswBA==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, "engines": { "node": ">=10" } }, "node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true }, "node_modules/yargs": { "version": "16.2.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, "dependencies": { "cliui": "^7.0.2", "escalade": "^3.1.1", @@ -8539,6 +8751,7 @@ "version": "20.2.4", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz", "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==", + "dev": true, "engines": { "node": ">=10" } @@ -8547,6 +8760,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", + "dev": true, "dependencies": { "camelcase": "^6.0.0", "decamelize": "^4.0.0", @@ -8561,7 +8775,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "devOptional": true, + "dev": true, "engines": { "node": ">=6" } @@ -8570,6 +8784,7 @@ "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, "engines": { "node": ">=10" }, diff --git a/package.json b/package.json index 63e419ad..ae61ed83 100644 --- a/package.json +++ b/package.json @@ -5,57 +5,56 @@ "main": "index.js", "scripts": { "compile": "npx hardhat compile", + "test": "npx hardhat test", "coverage": "export SOLIDITY_COVERAGE=true && npx hardhat coverage", "docs-publish": "npx hardhat docgen && cd docs/website && npm i && npm run publish-gh-pages", "docs-start": "npx hardhat docgen && cd docs/website && npm i && npm start", "flat": "bash scripts/make_flat.sh", "solidity-docgen": "rm -rf docs/docs/api* && npm i && npx hardhat docgen --exclude interfaces,libs,ERC677BridgeTokenRewardable.sol . contracts docs && node docs/website/sidebars-fix.js", "generate-uml": "sol2uml ./contracts -o docs/classDiagram.svg", +<<<<<<< HEAD "test": "npx hardhat test", "testOnTestnet": "export CONTRACTS_NO_UPGRADE_PROXY=true && ./node_modules/.bin/truffle test --network testNet test/KeyGenHistory.js test/mockContracts/BlockRewardHbbftMock.sol test/mockContracts/RandomHbbftMock.sol test/mockContracts/ValidatorSetHbbftMock.sol test/mockContracts/StakingHbbftMock.sol", "getFunctionSignatures": "node scripts/getFunctionSignatures.js", "typechain": "npx typechain --target ethers-v5 --out-dir src/types 'artifacts/contracts/**/!(*.dbg).json'" +======= + "clean": "rm -rf artifacts/ cache/ coverage/ typechain/ typechain-types/ src/ coverage.json" +>>>>>>> dmd/dev }, "repository": { "type": "git", - "url": "git+https://github.com/poanetwork/posdao-contracts.git" + "url": "git+https://github.com/DMDcoin/diamond-contracts-core.git" }, "author": "thomashaller@gmx.at", "bugs": { - "url": "https://github.com/poanetwork/posdao-contracts/issues" + "url": "https://github.com/DMDcoin/diamond-contracts-core/issues" }, - "homepage": "https://github.com/poanetwork/posdao-contracts#readme", + "homepage": "https://github.com/DMDcoin/diamond-contracts-core#readme", "devDependencies": { - "@nomicfoundation/hardhat-chai-matchers": "^1.0.2", - "@nomicfoundation/hardhat-network-helpers": "^1.0.3", - "@nomicfoundation/hardhat-toolbox": "^2.0.2", - "@nomiclabs/hardhat-ethers": "^2.0.2", - "@nomiclabs/hardhat-etherscan": "^3.1.0", - "@openzeppelin/contracts": "^4.9.2", - "@openzeppelin/contracts-upgradeable": "^4.9.2", - "@openzeppelin/hardhat-upgrades": "^1.28.0", - "@typechain/ethers-v5": "^10.1.0", - "@typechain/hardhat": "^6.1.3", + "@nomicfoundation/hardhat-ethers": "^3.0.5", + "@nomicfoundation/hardhat-toolbox": "^5.0.0", + "@openzeppelin/contracts": "^4.9.6", + "@openzeppelin/contracts-upgradeable": "^4.9.6", + "@openzeppelin/hardhat-upgrades": "^3.0.5", + "@typechain/ethers-v6": "^0.5.1", + "@typechain/hardhat": "^9.1.0", "@types/chai": "^4.3.3", - "@types/fs-extra": "^9.0.13", + "@types/fs-extra": "^11.0.4", "@types/lodash": "^4.14.186", - "@types/mocha": "^9.1.1", - "@types/node": "^18.11.2", - "chai-bn": "^0.3.1", + "@types/mocha": "^10.0.6", + "@types/node": "^20.12.2", "dotenv": "^16.0.2", - "ethers": "^5.6.9", - "hardhat": "2.12.2", + "ethers": "^6.11.1", + "hardhat": "^2.20.1", "hardhat-contract-sizer": "^2.6.1", - "hardhat-gas-reporter": "^1.0.8", + "hardhat-tracer": "^2.8.2", "lodash": "^4.17.21", "solc": "0.8.17", "solidity-coverage": "^0.8.5", "solidity-docgen": "^0.6.0-beta.29", "ts-node": "^10.9.1", "typechain": "^8.1.0", - "typescript": "^4.8.4" + "typescript": "^5.4.3" }, - "dependencies": { - "hardhat-tracer": "^1.3.0" - } + "prettier": "./.prettierrc.json" } diff --git a/slither.config.json b/slither.config.json index 4afe1385..ca76789c 100644 --- a/slither.config.json +++ b/slither.config.json @@ -1,9 +1,9 @@ { - "detectors_to_exclude": "naming-convention, solc-version, assembly, similar-names, too-many-digits, calls-loop", + "detectors_to_exclude": "naming-convention, solc-version, assembly, similar-names, too-many-digits, calls-loop, timestamp", "solc_disable_warnings": false, "exclude_informational": true, "exclude_low": false, "exclude_medium": false, "exclude_high": false, - "filter_paths": "mockContracts" + "filter_paths": "mockContracts|openzeppelin" } diff --git a/tasks/make_spec.ts b/tasks/make_spec.ts index db7e27fd..016e97d9 100644 --- a/tasks/make_spec.ts +++ b/tasks/make_spec.ts @@ -1,6 +1,5 @@ import fs from 'fs'; import path from 'path'; -import "@nomiclabs/hardhat-ethers"; import { task } from "hardhat/config"; import { InitialContractsConfiguration, NetworkConfiguration } from './types'; diff --git a/tasks/types.ts b/tasks/types.ts index 7a2b6253..7390d310 100644 --- a/tasks/types.ts +++ b/tasks/types.ts @@ -1,18 +1,18 @@ import fs from 'fs'; import fp from 'lodash/fp'; -import { BigNumber, ethers } from "ethers"; +import { ethers } from "ethers"; import { HardhatRuntimeEnvironment } from "hardhat/types"; import { getInitializerData } from '@openzeppelin/hardhat-upgrades/dist/utils'; export class StakingParams { public _initialStakingAddresses?: string[]; - public _delegatorMinStake?: BigNumber; - public _candidateMinStake?: BigNumber; - public _maxStake?: BigNumber; - public _stakingFixedEpochDuration?: BigNumber; - public _stakingTransitionTimeframeLength?: BigNumber; - public _stakingWithdrawDisallowPeriod?: BigNumber; + public _delegatorMinStake?: bigint; + public _candidateMinStake?: bigint; + public _maxStake?: bigint; + public _stakingFixedEpochDuration?: bigint; + public _stakingTransitionTimeframeLength?: bigint; + public _stakingWithdrawDisallowPeriod?: bigint; constructor(init: Partial) { Object.assign(this, init); @@ -31,8 +31,8 @@ export class NetworkConfiguration { public initialStakingAddresses?: string[]; public permittedAddresses?: string[]; - public parts?: Array; - public acks: any; + public parts: Array = []; + public acks: Array> = []; public minimumBlockTime?: number; public maximumBlockTime?: number; @@ -85,9 +85,9 @@ export class NetworkConfiguration { publicKeys[i] = publicKeys[i].trim(); } - const newParts: Buffer[] = []; + const newParts: string[] = []; initData.parts.forEach((x: string) => { - newParts.push(Buffer.from(x)); + newParts.push( '0x' + x); }); instance.publicKeys = fp.flatMap((x: string) => [x.substring(0, 66), '0x' + x.substring(66, 130)])(publicKeys); @@ -97,7 +97,18 @@ export class NetworkConfiguration { instance.permittedAddresses = [instance.owner]; instance.parts = newParts; - instance.acks = initData.acks; + let newAcks : Array> = []; + + // initData.acks + initData.acks.forEach((acksValidator: Array) => { + let acks : Array = []; + acksValidator.forEach((ack: string) => { + acks.push( '0x' + ack); + }); + newAcks.push(acks); + }); + + instance.acks = newAcks; const stakingEpochDuration = process.env.STAKING_EPOCH_DURATION; const stakeWithdrawDisallowPeriod = process.env.STAKE_WITHDRAW_DISALLOW_PERIOD; @@ -106,14 +117,15 @@ export class NetworkConfiguration { const stakingMinStakeForDelegatorString = process.env.STAKING_MIN_STAKE_FOR_DELEGATOR; const validatorInactivityThresholdString = process.env.VALIDATOR_INACTIVITY_THRESHOLD; - let stakingMinStakeForValidator = ethers.utils.parseEther('1'); + + let stakingMinStakeForValidator = ethers.parseEther('1'); if (stakingMinStakeForValidatorString) { - stakingMinStakeForValidator = ethers.utils.parseEther(stakingMinStakeForValidatorString); + stakingMinStakeForValidator = ethers.parseEther(stakingMinStakeForValidatorString); } - let stakingMinStakeForDelegator = ethers.utils.parseEther('1'); + let stakingMinStakeForDelegator = ethers.parseEther('1'); if (stakingMinStakeForDelegatorString) { - stakingMinStakeForDelegator = ethers.utils.parseEther(stakingMinStakeForDelegatorString); + stakingMinStakeForDelegator = ethers.parseEther(stakingMinStakeForDelegatorString); } instance.validatorInactivityThreshold = 365 * 86400 // 1year @@ -121,16 +133,17 @@ export class NetworkConfiguration { instance.validatorInactivityThreshold = parseInt(validatorInactivityThresholdString); } - let stakingMaxStakeForValidator = ethers.utils.parseEther('50000'); + let stakingMaxStakeForValidator = ethers.parseEther('50000'); + instance.stakingParams = new StakingParams({ _initialStakingAddresses: instance.initialStakingAddresses, _delegatorMinStake: stakingMinStakeForDelegator, _candidateMinStake: stakingMinStakeForValidator, _maxStake: stakingMaxStakeForValidator, - _stakingFixedEpochDuration: BigNumber.from(stakingEpochDuration), - _stakingTransitionTimeframeLength: BigNumber.from(stakingTransitionWindowLength), - _stakingWithdrawDisallowPeriod: BigNumber.from(stakeWithdrawDisallowPeriod), + _stakingFixedEpochDuration: BigInt(stakingEpochDuration!), + _stakingTransitionTimeframeLength: BigInt(stakingTransitionWindowLength!), + _stakingWithdrawDisallowPeriod: BigInt(stakeWithdrawDisallowPeriod!), }); return instance; @@ -154,7 +167,7 @@ export class SpecialContract { async compileContract(hre: HardhatRuntimeEnvironment, args: any[]) { const factory = await hre.ethers.getContractFactory(this.name!); - const tx = factory.getDeployTransaction(...args); + const tx = await factory.getDeployTransaction(...args); this.bytecode = tx.data!.toString(); } @@ -205,7 +218,7 @@ export class CoreContract { const contractFactory = await hre.ethers.getContractFactory(this.name!); const initializerData = getInitializerData(contractFactory.interface, args, 'initialize') - const tx = proxyFactory.getDeployTransaction(logicAddress, adminAddress, initializerData); + const tx = await proxyFactory.getDeployTransaction(logicAddress, adminAddress, initializerData); this.proxyBytecode = tx.data!.toString(); } @@ -217,7 +230,7 @@ export class CoreContract { } toSpecAccount(useUpgradeProxy: boolean, initialBalance: number) { - let spec = {}; + let spec : { [id: string] : any; } = {}; if (useUpgradeProxy) { spec[this.implementationAddress!] = { @@ -241,7 +254,7 @@ export class CoreContract { } export class InitialContractsConfiguration { - public core: CoreContract[]; + public core: CoreContract[] = []; public admin?: SpecialContract; public registry?: SpecialContract; @@ -271,7 +284,8 @@ export class InitialContractsConfiguration { getAddress(name: string): string | undefined { const found = this.core.find(obj => obj.name === name); - return found ? found.proxyAddress : ethers.constants.AddressZero; + + return found ? found.proxyAddress : ethers.ZeroAddress; } getContractInitializerArgs( diff --git a/test/BlockRewardHbbft.ts b/test/BlockRewardHbbft.ts index 36c28611..500bfd80 100644 --- a/test/BlockRewardHbbft.ts +++ b/test/BlockRewardHbbft.ts @@ -1,86 +1,90 @@ import { ethers, network, upgrades } from "hardhat"; - +import { expect } from "chai"; +import { HardhatEthersSigner } from "@nomicfoundation/hardhat-ethers/signers"; import * as helpers from "@nomicfoundation/hardhat-network-helpers"; +import * as _ from "lodash"; +import fp from "lodash/fp"; import { BlockRewardHbbftMock, - RandomHbbft, ValidatorSetHbbftMock, StakingHbbftMock, - KeyGenHistory, - ConnectivityTrackerHbbftMock } from "../src/types"; -import fp from 'lodash/fp'; -import { BigNumber } from "ethers"; -import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers"; - - -require('chai') - .use(require('chai-as-promised')) - .use(require('chai-bn')(BigNumber)) - .should(); - -//smart contracts -let blockRewardHbbft: BlockRewardHbbftMock; -let randomHbbft: RandomHbbft; -let validatorSetHbbft: ValidatorSetHbbftMock; -let stakingHbbft: StakingHbbftMock; -let keyGenHistory: KeyGenHistory; -let connectivityTracker: ConnectivityTrackerHbbftMock; - -//addresses -let owner: SignerWithAddress; -let accounts: SignerWithAddress[]; -let initialValidatorsPubKeys; -let initialValidatorsIpAddresses; -let validators; - -//vars -let candidateMinStake: BigNumber; -let delegatorMinStake: BigNumber; -let stakingEpoch; -let nativeRewardUndistributed = BigNumber.from(0); - -//consts +import { getNValidatorsPartNAcks } from "./testhelpers/data"; + // one epoch in 1 day. -const STAKING_FIXED_EPOCH_DURATION = BigNumber.from(86400); +const STAKING_FIXED_EPOCH_DURATION = 86400n; // the transition time window is 1 hour. -const STAKING_TRANSITION_WINDOW_LENGTH = BigNumber.from(3600); +const STAKING_TRANSITION_WINDOW_LENGTH = 3600n; -//const STAKING_EPOCH_DURATION = BigNumber.from(120954 + 2); +const STAKE_WITHDRAW_DISALLOW_PERIOD = 2n; // one less than EPOCH DURATION, therefore it meets the conditions. +const MIN_STAKE = ethers.parseEther('1'); +const MAX_STAKE = ethers.parseEther('100000'); -const KEY_GEN_DURATION = BigNumber.from(2); // we assume that there is a fixed duration in blocks, in reality it varies. -const STAKE_WITHDRAW_DISALLOW_PERIOD = 2; // one less than EPOCH DURATION, therefore it meets the conditions. -const MIN_STAKE = BigNumber.from(ethers.utils.parseEther('1')); -const MAX_STAKE = BigNumber.from(ethers.utils.parseEther('100000')); +const SystemAccountAddress = '0xffffFFFfFFffffffffffffffFfFFFfffFFFfFFfE'; +const GovernanceAddress = '0xDA0da0da0Da0Da0Da0DA00DA0da0da0DA0DA0dA0'; -const SystemAddress = '0xffffFFFfFFffffffffffffffFfFFFfffFFFfFFfE'; +const addToDeltaPotValue = ethers.parseEther('60'); +const validatorInactivityThreshold = 365n * 86400n // 1 year describe('BlockRewardHbbft', () => { - it('network started', async () => { - [owner, ...accounts] = await ethers.getSigners(); + let owner: HardhatEthersSigner; + let accounts: HardhatEthersSigner[]; + let initialValidators: string[]; + let initialStakingAddresses: string[]; + let initialValidatorsPubKeys; + let initialValidatorsIpAddresses; + let validators; + + let candidateMinStake: bigint; + let delegatorMinStake: bigint; + let nativeRewardUndistributed = 0n; + let blockRewardHbbft: BlockRewardHbbftMock; + let validatorSetHbbft: ValidatorSetHbbftMock; + let stakingHbbft: StakingHbbftMock; + + let stubAddress: string; + + before(async () => { + [owner, ...accounts] = await ethers.getSigners(); const accountAddresses = accounts.map(item => item.address); - const initialValidators = accountAddresses.slice(1, 3 + 1); // accounts[1...3] - const initialStakingAddresses = accountAddresses.slice(4, 6 + 1); // accounts[4...6] - const stubAddress = accounts[7].address; - initialStakingAddresses.length.should.be.equal(3); - initialStakingAddresses[0].should.not.be.equal('0x0000000000000000000000000000000000000000'); - initialStakingAddresses[1].should.not.be.equal('0x0000000000000000000000000000000000000000'); - initialStakingAddresses[2].should.not.be.equal('0x0000000000000000000000000000000000000000'); + stubAddress = accounts[7].address; + + initialValidators = accountAddresses.slice(1, 3 + 1); // accounts[1...3] + initialStakingAddresses = accountAddresses.slice(4, 6 + 1); // accounts[4...6] - const validatorInactivityThreshold = 365 * 86400 // 1 year + expect(initialStakingAddresses).to.be.lengthOf(3); + expect(initialStakingAddresses[0]).to.not.be.equal(ethers.ZeroAddress); + expect(initialStakingAddresses[1]).to.not.be.equal(ethers.ZeroAddress); + expect(initialStakingAddresses[2]).to.not.be.equal(ethers.ZeroAddress); + + const { + blockRewardContract, + validatorSetContract, + stakingContract, + } = await helpers.loadFixture(deployContractsFixture); + + blockRewardHbbft = blockRewardContract; + validatorSetHbbft = validatorSetContract; + stakingHbbft = stakingContract; + + candidateMinStake = await stakingHbbft.candidateMinStake(); + delegatorMinStake = await stakingHbbft.delegatorMinStake(); + }); + + async function deployContractsFixture() { + const { parts, acks } = getNValidatorsPartNAcks(initialValidators.length); const ConnectivityTrackerFactory = await ethers.getContractFactory("ConnectivityTrackerHbbftMock"); - connectivityTracker = await upgrades.deployProxy(ConnectivityTrackerFactory) as ConnectivityTrackerHbbftMock; - await connectivityTracker.deployed(); + const connectivityTrackerContract = await ConnectivityTrackerFactory.deploy(); + await connectivityTrackerContract.waitForDeployment(); - // Deploy ValidatorSet contract const ValidatorSetFactory = await ethers.getContractFactory("ValidatorSetHbbftMock"); - validatorSetHbbft = await upgrades.deployProxy( + const validatorSetHbbftProxy = await upgrades.deployProxy( ValidatorSetFactory, [ owner.address, @@ -93,49 +97,94 @@ describe('BlockRewardHbbft', () => { initialStakingAddresses, // _initialStakingAddresses ], { initializer: 'initialize' } - ) as ValidatorSetHbbftMock; + ); - await validatorSetHbbft.deployed(); + await validatorSetHbbftProxy.waitForDeployment(); - // Deploy BlockRewardHbbft contract - const BlockRewardHbbftFactory = await ethers.getContractFactory("BlockRewardHbbftMock"); - blockRewardHbbft = await upgrades.deployProxy( - BlockRewardHbbftFactory, + const RandomHbbftFactory = await ethers.getContractFactory("RandomHbbft"); + const randomHbbftProxy = await upgrades.deployProxy( + RandomHbbftFactory, + [ + owner.address, + await validatorSetHbbftProxy.getAddress() + ], + { initializer: 'initialize' }, + ); + + await randomHbbftProxy.waitForDeployment(); + + const KeyGenFactory = await ethers.getContractFactory("KeyGenHistory"); + const keyGenHistoryProxy = await upgrades.deployProxy( + KeyGenFactory, [ owner.address, - validatorSetHbbft.address, - connectivityTracker.address + await validatorSetHbbftProxy.getAddress(), + initialValidators, + parts, + acks ], { initializer: 'initialize' } - ) as BlockRewardHbbftMock; + ); - await blockRewardHbbft.deployed(); + await keyGenHistoryProxy.waitForDeployment(); - // Deploy BlockRewardHbbft contract - const RandomHbbftFactory = await ethers.getContractFactory("RandomHbbft"); - randomHbbft = await upgrades.deployProxy( - RandomHbbftFactory, + const CertifierFactory = await ethers.getContractFactory("CertifierHbbft"); + const certifierProxy = await upgrades.deployProxy( + CertifierFactory, + [ + [owner.address], + await validatorSetHbbftProxy.getAddress(), + owner.address + ], + { initializer: 'initialize' } + ); + + await certifierProxy.waitForDeployment(); + + const TxPermissionFactory = await ethers.getContractFactory("TxPermissionHbbft"); + const txPermissionProxy = await upgrades.deployProxy( + TxPermissionFactory, + [ + [owner.address], + await certifierProxy.getAddress(), + await validatorSetHbbftProxy.getAddress(), + await keyGenHistoryProxy.getAddress(), + stubAddress, + owner.address + ], + { initializer: 'initialize' } + ); + + await txPermissionProxy.waitForDeployment(); + + const BlockRewardHbbftFactory = await ethers.getContractFactory("BlockRewardHbbftMock"); + const blockRewardHbbftProxy = await upgrades.deployProxy( + BlockRewardHbbftFactory, [ owner.address, - validatorSetHbbft.address + await validatorSetHbbftProxy.getAddress(), + await connectivityTrackerContract.getAddress(), ], { initializer: 'initialize' } - ) as RandomHbbft; + ); - await randomHbbft.deployed(); + await blockRewardHbbftProxy.waitForDeployment(); // The following private keys belong to the accounts 1-3, fixed by using the "--mnemonic" option when starting ganache. // const initialValidatorsPrivKeys = ["0x272b8400a202c08e23641b53368d603e5fec5c13ea2f438bce291f7be63a02a7", "0xa8ea110ffc8fe68a069c8a460ad6b9698b09e21ad5503285f633b3ad79076cf7", "0x5da461ff1378256f69cb9a9d0a8b370c97c460acbe88f5d897cb17209f891ffc"]; // Public keys corresponding to the three private keys above. initialValidatorsPubKeys = fp.flatMap((x: string) => [x.substring(0, 66), '0x' + x.substring(66, 130)]) - (['0x52be8f332b0404dff35dd0b2ba44993a9d3dc8e770b9ce19a849dff948f1e14c57e7c8219d522c1a4cce775adbee5330f222520f0afdabfdb4a4501ceeb8dcee', + ([ + '0x52be8f332b0404dff35dd0b2ba44993a9d3dc8e770b9ce19a849dff948f1e14c57e7c8219d522c1a4cce775adbee5330f222520f0afdabfdb4a4501ceeb8dcee', '0x99edf3f524a6f73e7f5d561d0030fc6bcc3e4bd33971715617de7791e12d9bdf6258fa65b74e7161bbbf7ab36161260f56f68336a6f65599dc37e7f2e397f845', - '0xa255fd7ad199f0ee814ee00cce44ef2b1fa1b52eead5d8013ed85eade03034ae4c246658946c2e1d7ded96394a1247fb4d093c32474317ae388e8d25692a0f56']); + '0xa255fd7ad199f0ee814ee00cce44ef2b1fa1b52eead5d8013ed85eade03034ae4c246658946c2e1d7ded96394a1247fb4d093c32474317ae388e8d25692a0f56' + ]); + // The IP addresses are irrelevant for these unit test, just initialize them to 0. - initialValidatorsIpAddresses = ['0x00000000000000000000000000000000', '0x00000000000000000000000000000000', '0x00000000000000000000000000000000']; + initialValidatorsIpAddresses = Array(initialValidators.length).fill(ethers.zeroPadBytes("0x00", 16)); let structure = { - _validatorSetContract: validatorSetHbbft.address, + _validatorSetContract: await validatorSetHbbftProxy.getAddress(), _initialStakingAddresses: initialStakingAddresses, _delegatorMinStake: MIN_STAKE, _candidateMinStake: MIN_STAKE, @@ -146,7 +195,7 @@ describe('BlockRewardHbbft', () => { }; const StakingHbbftFactory = await ethers.getContractFactory("StakingHbbftMock"); - stakingHbbft = await upgrades.deployProxy( + const stakingHbbftProxy = await upgrades.deployProxy( StakingHbbftFactory, [ owner.address, @@ -155,89 +204,461 @@ describe('BlockRewardHbbft', () => { initialValidatorsIpAddresses // _internetAddresses ], { initializer: 'initialize' } + ); + + await stakingHbbftProxy.waitForDeployment(); + + const validatorSetContract = ValidatorSetFactory.attach( + await validatorSetHbbftProxy.getAddress() + ) as ValidatorSetHbbftMock; + + const stakingContract = StakingHbbftFactory.attach( + await stakingHbbftProxy.getAddress() ) as StakingHbbftMock; - await stakingHbbft.deployed(); + const blockRewardContract = BlockRewardHbbftFactory.attach( + await blockRewardHbbftProxy.getAddress() + ) as BlockRewardHbbftMock - candidateMinStake = await stakingHbbft.candidateMinStake(); - delegatorMinStake = await stakingHbbft.delegatorMinStake(); + await validatorSetContract.setBlockRewardContract(await blockRewardContract.getAddress()); + await validatorSetContract.setRandomContract(await randomHbbftProxy.getAddress()); + await validatorSetContract.setStakingContract(await stakingContract.getAddress()); + await validatorSetContract.setKeyGenHistoryContract(await keyGenHistoryProxy.getAddress()); - const parts = - [[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 181, 129, 31, 84, 186, 242, 5, 151, 59, 35, 196, 140, 106, 29, 40, 112, 142, 156, 132, 158, 47, 223, 253, 185, 227, 249, 190, 96, 5, 99, 239, 213, 127, 29, 136, 115, 71, 164, 202, 44, 6, 171, 131, 251, 147, 159, 54, 49, 1, 0, 0, 0, 0, 0, 0, 0, 153, 0, 0, 0, 0, 0, 0, 0, 4, 177, 133, 61, 18, 58, 222, 74, 65, 5, 126, 253, 181, 113, 165, 43, 141, 56, 226, 132, 208, 218, 197, 119, 179, 128, 30, 162, 251, 23, 33, 73, 38, 120, 246, 223, 233, 11, 104, 60, 154, 241, 182, 147, 219, 81, 45, 134, 239, 69, 169, 198, 188, 152, 95, 254, 170, 108, 60, 166, 107, 254, 204, 195, 170, 234, 154, 134, 26, 91, 9, 139, 174, 178, 248, 60, 65, 196, 218, 46, 163, 218, 72, 1, 98, 12, 109, 186, 152, 148, 159, 121, 254, 34, 112, 51, 70, 121, 51, 167, 35, 240, 5, 134, 197, 125, 252, 3, 213, 84, 70, 176, 160, 36, 73, 140, 104, 92, 117, 184, 80, 26, 240, 106, 230, 241, 26, 79, 46, 241, 195, 20, 106, 12, 186, 49, 254, 168, 233, 25, 179, 96, 62, 104, 118, 153, 95, 53, 127, 160, 237, 246, 41], - [0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 181, 129, 31, 84, 186, 242, 5, 151, 59, 35, 196, 140, 106, 29, 40, 112, 142, 156, 132, 158, 47, 223, 253, 185, 227, 249, 190, 96, 5, 99, 239, 213, 127, 29, 136, 115, 71, 164, 202, 44, 6, 171, 131, 251, 147, 159, 54, 49, 1, 0, 0, 0, 0, 0, 0, 0, 153, 0, 0, 0, 0, 0, 0, 0, 4, 177, 133, 61, 18, 58, 222, 74, 65, 5, 126, 253, 181, 113, 165, 43, 141, 56, 226, 132, 208, 218, 197, 119, 179, 128, 30, 162, 251, 23, 33, 73, 38, 120, 246, 223, 233, 11, 104, 60, 154, 241, 182, 147, 219, 81, 45, 134, 239, 69, 169, 198, 188, 152, 95, 254, 170, 108, 60, 166, 107, 254, 204, 195, 170, 234, 154, 134, 26, 91, 9, 139, 174, 178, 248, 60, 65, 196, 218, 46, 163, 218, 72, 1, 98, 12, 109, 186, 152, 148, 159, 121, 254, 34, 112, 51, 70, 121, 51, 167, 35, 240, 5, 134, 197, 125, 252, 3, 213, 84, 70, 176, 160, 36, 73, 140, 104, 92, 117, 184, 80, 26, 240, 106, 230, 241, 26, 79, 46, 241, 195, 20, 106, 12, 186, 49, 254, 168, 233, 25, 179, 96, 62, 104, 118, 153, 95, 53, 127, 160, 237, 246, 41], - [0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 181, 129, 31, 84, 186, 242, 5, 151, 59, 35, 196, 140, 106, 29, 40, 112, 142, 156, 132, 158, 47, 223, 253, 185, 227, 249, 190, 96, 5, 99, 239, 213, 127, 29, 136, 115, 71, 164, 202, 44, 6, 171, 131, 251, 147, 159, 54, 49, 1, 0, 0, 0, 0, 0, 0, 0, 153, 0, 0, 0, 0, 0, 0, 0, 4, 177, 133, 61, 18, 58, 222, 74, 65, 5, 126, 253, 181, 113, 165, 43, 141, 56, 226, 132, 208, 218, 197, 119, 179, 128, 30, 162, 251, 23, 33, 73, 38, 120, 246, 223, 233, 11, 104, 60, 154, 241, 182, 147, 219, 81, 45, 134, 239, 69, 169, 198, 188, 152, 95, 254, 170, 108, 60, 166, 107, 254, 204, 195, 170, 234, 154, 134, 26, 91, 9, 139, 174, 178, 248, 60, 65, 196, 218, 46, 163, 218, 72, 1, 98, 12, 109, 186, 152, 148, 159, 121, 254, 34, 112, 51, 70, 121, 51, 167, 35, 240, 5, 134, 197, 125, 252, 3, 213, 84, 70, 176, 160, 36, 73, 140, 104, 92, 117, 184, 80, 26, 240, 106, 230, 241, 26, 79, 46, 241, 195, 20, 106, 12, 186, 49, 254, 168, 233, 25, 179, 96, 62, 104, 118, 153, 95, 53, 127, 160, 237, 246, 41]]; + return { blockRewardContract, validatorSetContract, stakingContract, connectivityTrackerContract }; + } - const acks = - [[[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 145, 0, 0, 0, 0, 0, 0, 0, 4, 239, 1, 112, 13, 13, 251, 103, 186, 212, 78, 44, 47, 250, 221, 84, 118, 88, 7, 64, 206, 186, 11, 2, 8, 204, 140, 106, 179, 52, 251, 237, 19, 53, 74, 187, 217, 134, 94, 66, 68, 89, 42, 85, 207, 155, 220, 101, 223, 51, 199, 37, 38, 203, 132, 13, 77, 78, 114, 53, 219, 114, 93, 21, 25, 164, 12, 43, 252, 160, 16, 23, 111, 79, 230, 121, 95, 223, 174, 211, 172, 231, 0, 52, 25, 49, 152, 79, 128, 39, 117, 216, 85, 201, 237, 242, 151, 219, 149, 214, 77, 233, 145, 47, 10, 184, 175, 162, 174, 237, 177, 131, 45, 126, 231, 32, 147, 227, 170, 125, 133, 36, 123, 164, 232, 129, 135, 196, 136, 186, 45, 73, 226, 179, 169, 147, 42, 41, 140, 202, 191, 12, 73, 146, 2]], - [[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 145, 0, 0, 0, 0, 0, 0, 0, 4, 239, 1, 112, 13, 13, 251, 103, 186, 212, 78, 44, 47, 250, 221, 84, 118, 88, 7, 64, 206, 186, 11, 2, 8, 204, 140, 106, 179, 52, 251, 237, 19, 53, 74, 187, 217, 134, 94, 66, 68, 89, 42, 85, 207, 155, 220, 101, 223, 51, 199, 37, 38, 203, 132, 13, 77, 78, 114, 53, 219, 114, 93, 21, 25, 164, 12, 43, 252, 160, 16, 23, 111, 79, 230, 121, 95, 223, 174, 211, 172, 231, 0, 52, 25, 49, 152, 79, 128, 39, 117, 216, 85, 201, 237, 242, 151, 219, 149, 214, 77, 233, 145, 47, 10, 184, 175, 162, 174, 237, 177, 131, 45, 126, 231, 32, 147, 227, 170, 125, 133, 36, 123, 164, 232, 129, 135, 196, 136, 186, 45, 73, 226, 179, 169, 147, 42, 41, 140, 202, 191, 12, 73, 146, 2]], - [[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 145, 0, 0, 0, 0, 0, 0, 0, 4, 239, 1, 112, 13, 13, 251, 103, 186, 212, 78, 44, 47, 250, 221, 84, 118, 88, 7, 64, 206, 186, 11, 2, 8, 204, 140, 106, 179, 52, 251, 237, 19, 53, 74, 187, 217, 134, 94, 66, 68, 89, 42, 85, 207, 155, 220, 101, 223, 51, 199, 37, 38, 203, 132, 13, 77, 78, 114, 53, 219, 114, 93, 21, 25, 164, 12, 43, 252, 160, 16, 23, 111, 79, 230, 121, 95, 223, 174, 211, 172, 231, 0, 52, 25, 49, 152, 79, 128, 39, 117, 216, 85, 201, 237, 242, 151, 219, 149, 214, 77, 233, 145, 47, 10, 184, 175, 162, 174, 237, 177, 131, 45, 126, 231, 32, 147, 227, 170, 125, 133, 36, 123, 164, 232, 129, 135, 196, 136, 186, 45, 73, 226, 179, 169, 147, 42, 41, 140, 202, 191, 12, 73, 146, 2]]]; + async function impersonateAcc(address: string) { + await helpers.impersonateAccount(address); + await owner.sendTransaction({ + to: address, + value: ethers.parseEther('10'), + }); - const KeyGenFactory = await ethers.getContractFactory("KeyGenHistory"); - keyGenHistory = await upgrades.deployProxy( - KeyGenFactory, - [ - owner.address, - validatorSetHbbft.address, - initialValidators, - parts, - acks - ], - { initializer: 'initialize' } - ) as KeyGenHistory; + return await ethers.getSigner(address); + } + + async function callReward(_blockReward: BlockRewardHbbftMock, isEpochEndBlock: boolean) { + // console.log('getting validators...'); + // note: this call used to crash because of a internal problem with a previous call of evm_mine and evm_increase_time https://github.com/DMDcoin/diamond-contracts-core/issues/13 + // const validators = await validatorSetHbbft.getValidators(); + // console.log('got validators:', validators); + const systemSigner = await impersonateAcc(SystemAccountAddress); + + await _blockReward.connect(systemSigner).reward(isEpochEndBlock); + + await helpers.stopImpersonatingAccount(SystemAccountAddress); + } + + async function getCurrentGovernancePotValue(): Promise { + const governnancePotAddress = await blockRewardHbbft.governancePotAddress(); + expect(governnancePotAddress).to.not.equal(ethers.ZeroAddress); + + return await ethers.provider.getBalance(governnancePotAddress); + } + + // time travels forward to the beginning of the next transition, + // and simulate a block mining (calling reward()) + async function timeTravelToTransition(_staking: StakingHbbftMock, _blockReward: BlockRewardHbbftMock) { + let startTimeOfNextPhaseTransition = await _staking.startTimeOfNextPhaseTransition(); + + await helpers.time.increaseTo(startTimeOfNextPhaseTransition); + await callReward(_blockReward, false); + } + + async function timeTravelToEndEpoch(_staking: StakingHbbftMock, _blockReward: BlockRewardHbbftMock) { + const endTimeOfCurrentEpoch = await _staking.stakingFixedEpochEndTime(); + + await helpers.time.increaseTo(endTimeOfCurrentEpoch); + await callReward(_blockReward, true); + } + + async function finishEpochPrelim( + _staking: StakingHbbftMock, + _blockReward: BlockRewardHbbftMock, + _percentage: bigint + ) { + const stakingFixedEpochEndTime = await _staking.stakingFixedEpochEndTime(); + const stakingEpochStartTime = await _staking.stakingEpochStartTime(); + + const epochDuration = (stakingFixedEpochEndTime - stakingEpochStartTime) * _percentage / 100n + 1n; + const endTimeOfCurrentEpoch = stakingEpochStartTime + epochDuration; + + await helpers.time.increaseTo(endTimeOfCurrentEpoch); + await callReward(_blockReward, true); + } + + async function announceAvailability(pool: string) { + const blockNumber = await ethers.provider.getBlockNumber() + const block = await ethers.provider.getBlock(blockNumber); + + const asEncoded = validatorSetHbbft.interface.encodeFunctionData( + "announceAvailability", + [blockNumber, block!.hash!] + ); + + // we know now, that this call is allowed. + // so we can execute it. + await (await ethers.getSigner(pool)).sendTransaction({ + to: await validatorSetHbbft.getAddress(), + data: asEncoded + }); + } + + async function getValidatorStake(validatorAddr: string) { + const stakingAddr = await validatorSetHbbft.stakingByMiningAddress(validatorAddr); + return await stakingHbbft.stakeAmount(stakingAddr, stakingAddr); + } + + async function mine() { + let expectedEpochDuration = (await stakingHbbft + .stakingFixedEpochEndTime()) - (await stakingHbbft.stakingEpochStartTime()); + let blocktime = expectedEpochDuration * 5n / 100n + 1n; //5% of the epoch + // let blocksPerEpoch = 60 * 60 * 12 / blocktime; + + await helpers.time.increase(blocktime); + + if ((await validatorSetHbbft.getPendingValidators()).length > 0) { + const currentValidators = await validatorSetHbbft.getValidators(); + const maxValidators = await validatorSetHbbft.maxValidators(); + + const initialGovernancePotBalance = await getCurrentGovernancePotValue(); + let deltaPotValue = await blockRewardHbbft.deltaPot(); + let reinsertPotValue = await blockRewardHbbft.reinsertPot(); + let _epochPercentage = await blockRewardHbbft.epochPercentage(); + + const stakeBeforeReward = await getValidatorStake(currentValidators.at(-1)!); + + await callReward(blockRewardHbbft, true); + + const currentGovernancePotBalance = await getCurrentGovernancePotValue(); + const governancePotIncrease = currentGovernancePotBalance - initialGovernancePotBalance; + + const deltaPotShare = deltaPotValue * BigInt(currentValidators.length) * _epochPercentage / 6000n / maxValidators / 100n; + const reinsertPotShare = reinsertPotValue * BigInt(currentValidators.length) * _epochPercentage / 6000n / maxValidators / 100n; + const nativeRewardUndistributed = await blockRewardHbbft.nativeRewardUndistributed(); + + const totalReward = deltaPotShare + reinsertPotShare + nativeRewardUndistributed; + const expectedDAOShare = totalReward / 10n; + + // we expect 1 wei difference, since the reward combination from 2 pots results in that. + //expectedDAOShare.sub(governancePotIncrease).should.to.be.bignumber.lte(BigNumber.from('1')); + expect(governancePotIncrease).to.be.closeTo(expectedDAOShare, expectedDAOShare / 10000n); + + //since there are a lot of delegators, we need to calc it on a basis that pays out the validator min reward. + let minValidatorSharePercent = 100n; + //staking address of the validator + let stakingAddress = await validatorSetHbbft.stakingByMiningAddress(currentValidators[currentValidators.length - 1]) + ///first 4 validators have delegators so they receive less DMD + if ((await stakingHbbft.poolDelegators(stakingAddress)).length) { + minValidatorSharePercent = 30n; + } + + const expectedValidatorReward = (totalReward - expectedDAOShare) / BigInt(currentValidators.length) * minValidatorSharePercent / 100n; + const stakeAfterReward = await getValidatorStake(currentValidators.at(-1)!); + const actualValidatorReward = stakeAfterReward - stakeBeforeReward; + + expect(actualValidatorReward).to.be.closeTo(expectedValidatorReward, expectedValidatorReward / 10000n); + } else { + await callReward(blockRewardHbbft, false); + } + } + + describe('initialize', async () => { + it('should fail if owner = address(0)', async () => { + const BlockRewardHbbftFactory = await ethers.getContractFactory("BlockRewardHbbft"); + await expect(upgrades.deployProxy( + BlockRewardHbbftFactory, + [ + ethers.ZeroAddress, + stubAddress, + stubAddress + ], + { initializer: 'initialize' } + )).to.be.revertedWith("Owner address must not be 0"); + }); + + it('should fail if ValidatorSet = address(0)', async () => { + const BlockRewardHbbftFactory = await ethers.getContractFactory("BlockRewardHbbft"); + await expect(upgrades.deployProxy( + BlockRewardHbbftFactory, + [ + stubAddress, + ethers.ZeroAddress, + stubAddress + ], + { initializer: 'initialize' } + )).to.be.revertedWith("ValidatorSet must not be 0"); + }); + + it('should fail if ConnectivityTracker = address(0)', async () => { + const BlockRewardHbbftFactory = await ethers.getContractFactory("BlockRewardHbbft"); + await expect(upgrades.deployProxy( + BlockRewardHbbftFactory, + [ + stubAddress, + stubAddress, + ethers.ZeroAddress + ], + { initializer: 'initialize' } + )).to.be.revertedWith("ConnectivityTracker must not be 0"); + }); + + it('should fail on double initialization', async () => { + const BlockRewardHbbftFactory = await ethers.getContractFactory("BlockRewardHbbft"); + const blockReward = await upgrades.deployProxy( + BlockRewardHbbftFactory, + [ + stubAddress, + stubAddress, + stubAddress, + ], + { initializer: 'initialize' } + ); + + await blockReward.waitForDeployment(); + + await expect(blockReward.initialize( + stubAddress, + stubAddress, + stubAddress, + )).to.be.revertedWith("Initializable: contract is already initialized"); + }); + }); + + describe('setdeltaPotPayoutFraction', async () => { + it('should restrict calling to contract owner', async () => { + const caller = accounts[5]; + + await expect(blockRewardHbbft.connect(caller).setdeltaPotPayoutFraction(1)) + .to.be.revertedWith("Ownable: caller is not the owner"); + }); + + it('should not allow zero payout fraction', async () => { + await expect(blockRewardHbbft.setdeltaPotPayoutFraction(0)) + .to.be.revertedWith("Payout fraction must not be 0"); + }); + + it('should set delta pot payout fraction and emit event', async () => { + const previousValue = await blockRewardHbbft.deltaPotPayoutFraction(); + const newValue = 10; + + await expect(blockRewardHbbft.setdeltaPotPayoutFraction(newValue)) + .to.emit(blockRewardHbbft, "SetDeltaPotPayoutFraction") + .withArgs(newValue); + expect(await blockRewardHbbft.deltaPotPayoutFraction()).to.be.equal(newValue); + + expect(await blockRewardHbbft.setdeltaPotPayoutFraction(previousValue)); + expect(await blockRewardHbbft.deltaPotPayoutFraction()).to.be.equal(previousValue); + }); + }); + + describe('setReinsertPotPayoutFraction', async () => { + it('should restrict calling to contract owner', async () => { + const caller = accounts[5]; + + await expect(blockRewardHbbft.connect(caller).setReinsertPotPayoutFraction(1)) + .to.be.revertedWith("Ownable: caller is not the owner"); + }); + + it('should not allow zero payout fraction', async () => { + await expect(blockRewardHbbft.setReinsertPotPayoutFraction(0)) + .to.be.revertedWith("Payout fraction must not be 0"); + }); + + it('should set reinsert pot payout fraction and emit event', async () => { + const previousValue = await blockRewardHbbft.reinsertPotPayoutFraction(); + const newValue = 10; - await keyGenHistory.deployed(); + await expect(blockRewardHbbft.setReinsertPotPayoutFraction(newValue)) + .to.emit(blockRewardHbbft, "SetReinsertPotPayoutFraction") + .withArgs(newValue); + expect(await blockRewardHbbft.reinsertPotPayoutFraction()).to.be.equal(newValue); - await validatorSetHbbft.setBlockRewardContract(blockRewardHbbft.address); - await validatorSetHbbft.setRandomContract(randomHbbft.address); - await validatorSetHbbft.setStakingContract(stakingHbbft.address); - await validatorSetHbbft.setKeyGenHistoryContract(keyGenHistory.address); + expect(await blockRewardHbbft.setReinsertPotPayoutFraction(previousValue)); + expect(await blockRewardHbbft.reinsertPotPayoutFraction()).to.be.equal(previousValue); + }); + }); + + describe('setConnectivityTracker', async () => { + it('should restrict calling to contract owner', async () => { + const caller = accounts[5]; + + await expect(blockRewardHbbft.connect(caller).setConnectivityTracker(ethers.ZeroAddress)) + .to.be.revertedWith("Ownable: caller is not the owner"); + }); + + it('should revert set zero address', async () => { + await expect(blockRewardHbbft.setConnectivityTracker(ethers.ZeroAddress)) + .to.be.revertedWith("ConnectivityTracker must not be 0"); + }); + + it('should set connectivity tracker address and emit event', async () => { + const previousValue = await blockRewardHbbft.connectivityTracker(); + const newValue = accounts[7]; + + await expect(blockRewardHbbft.setConnectivityTracker(newValue)) + .to.emit(blockRewardHbbft, "SetConnectivityTracker") + .withArgs(newValue); + expect(await blockRewardHbbft.connectivityTracker()).to.be.equal(newValue); + + expect(await blockRewardHbbft.setConnectivityTracker(previousValue)); + expect(await blockRewardHbbft.connectivityTracker()).to.be.equal(previousValue); + }); + }); + + it('should get governance address', async () => { + expect(await blockRewardHbbft.getGovernanceAddress()).to.be.equal(GovernanceAddress); + }); + + describe('reward', async () => { + it('should restrict calling reward only to system address', async () => { + const { blockRewardContract } = await helpers.loadFixture(deployContractsFixture); + + const caller = accounts[5]; + + await expect(blockRewardContract.connect(caller).reward(false)).to.be.reverted; + }); + + it('should revert for zero validators', async () => { + const { + blockRewardContract, + validatorSetContract, + stakingContract + } = await helpers.loadFixture(deployContractsFixture); + + await validatorSetContract.forceFinalizeNewValidators(); + + const validatorSetSigner = await impersonateAcc(await validatorSetContract.getAddress()); + await stakingContract.connect(validatorSetSigner).incrementStakingEpoch(); + await helpers.stopImpersonatingAccount(validatorSetSigner.address); + + expect(await validatorSetContract.getValidators()).to.be.empty; + + const systemSigner = await impersonateAcc(SystemAccountAddress); + await expect(blockRewardContract.connect(systemSigner).reward(true)) + .to.be.revertedWith("Empty Validator list"); + await helpers.stopImpersonatingAccount(SystemAccountAddress); + }); + + it('should not reward banned validators', async () => { + const { + blockRewardContract, + validatorSetContract, + stakingContract, + } = await helpers.loadFixture(deployContractsFixture); + + for (const _staking of initialStakingAddresses) { + const pool = await ethers.getSigner(_staking); + + await stakingContract.connect(pool).stake(pool.address, { value: candidateMinStake }); + expect(await stakingContract.stakeAmountTotal(pool.address)).to.be.eq(candidateMinStake); + } + + await callReward(blockRewardContract, true); + await callReward(blockRewardContract, true); + + const fixedEpochEndTime = await stakingHbbft.stakingFixedEpochEndTime(); + await helpers.time.increaseTo(fixedEpochEndTime + 1n); + await helpers.mine(1); + + const deltaPotValue = ethers.parseEther('10'); + await blockRewardContract.addToDeltaPot({ value: deltaPotValue }); + expect(await blockRewardContract.deltaPot()).to.be.eq(deltaPotValue); + + const now = (await ethers.provider.getBlock('latest'))!.timestamp; + + for (const validator of initialValidators) { + await validatorSetContract.setBannedUntil(validator, now + 3600); + expect(await validatorSetContract.isValidatorBanned(validator)).to.be.true; + } + + const systemSigner = await impersonateAcc(SystemAccountAddress); + await expect(blockRewardContract.connect(systemSigner).reward(true)) + .to.emit(blockRewardContract, "CoinsRewarded") + .withArgs(0n); + await helpers.stopImpersonatingAccount(SystemAccountAddress); + }); + + it('should save epochs in which validator was awarded', async () => { + const { + blockRewardContract, + stakingContract, + } = await helpers.loadFixture(deployContractsFixture); + + for (const _staking of initialStakingAddresses) { + const pool = await ethers.getSigner(_staking); + + await stakingContract.connect(pool).stake(pool.address, { value: candidateMinStake }); + expect(await stakingContract.stakeAmountTotal(pool.address)).to.be.eq(candidateMinStake); + } + + for (const _validator of initialValidators) { + expect(await blockRewardContract.epochsPoolGotRewardFor(_validator)).to.be.empty; + } + + await callReward(blockRewardContract, true); + + const deltaPotValue = ethers.parseEther('10'); + await blockRewardContract.addToDeltaPot({ value: deltaPotValue }); + expect(await blockRewardContract.deltaPot()).to.be.eq(deltaPotValue); + + const expectedEpochsCount = 10; + let passedEpochs = new Array(); + + for (let i = 0; i < expectedEpochsCount; ++i) { + const fixedEpochEndTime = await stakingHbbft.stakingFixedEpochEndTime(); + await helpers.time.increaseTo(fixedEpochEndTime + 1n); + await helpers.mine(1); + + const epochNumber = await stakingContract.stakingEpoch(); + + passedEpochs.push(epochNumber); + await callReward(blockRewardContract, true); + } + + expect(passedEpochs).to.be.lengthOf(expectedEpochsCount); + + for (const _validator of initialValidators) { + const poolRewardedEpochs = await blockRewardContract.epochsPoolGotRewardFor(_validator); + + expect(poolRewardedEpochs).to.be.lengthOf(expectedEpochsCount); + expect(poolRewardedEpochs).to.deep.equal(passedEpochs); + } + }); }); it('staking epoch #0 finished', async () => { + expect(await stakingHbbft.stakingEpoch()).to.equal(0n); - let stakingEpoch = await stakingHbbft.stakingEpoch(); - stakingEpoch.should.be.equal(BigNumber.from(0)); // we are now in the Phase 1: Regular Block Creation //means: just a normal and boring block. - await callReward(false); + await callReward(blockRewardHbbft, false); //boring, thing happened, we still should have zero pendingValidors. - let pendingValidators = await validatorSetHbbft.getPendingValidators(); - pendingValidators.length.should.be.equal(0); + expect(await validatorSetHbbft.getPendingValidators()).to.be.empty; //lets spin up the time until the beginning of the Transition phase. - await timeTravelToTransition(); - await timeTravelToEndEpoch(); + await timeTravelToTransition(stakingHbbft, blockRewardHbbft); + await timeTravelToEndEpoch(stakingHbbft, blockRewardHbbft); // that was the end of epoch 0, // we should be in epoch 1 now. - stakingEpoch = await stakingHbbft.stakingEpoch(); - stakingEpoch.should.be.equal(BigNumber.from(1)); + expect(await stakingHbbft.stakingEpoch()).to.be.equal(1n); // since noone stacked after all, pending validators should still be 0 - pendingValidators = await validatorSetHbbft.getPendingValidators(); - pendingValidators.length.should.be.equal(0); - - (await blockRewardHbbft.nativeRewardUndistributed()).should.be.equal(nativeRewardUndistributed); + expect(await validatorSetHbbft.getPendingValidators()).to.be.empty; + expect(await blockRewardHbbft.nativeRewardUndistributed()).to.be.equal(nativeRewardUndistributed); }); it('staking epoch #1 started', async () => { - (await stakingHbbft.stakingEpoch()).should.be.equal(BigNumber.from(1)); - //const stakingEpochStartBlock = await stakingHbbft.stakingEpochStartBlock(); - //stakingEpochStartBlock.should.be.equal(STAKING_EPOCH_START_BLOCK.add(STAKING_FIXED_EPOCH_DURATION).add(KEY_GEN_DURATION)); - - - const currentValudators = await validatorSetHbbft.getValidators(); - currentValudators.length.should.be.equal(3); - - //Docs: The pendingValidators set returned by the ValidatorSet contract is empty in this phase,. - const pendingValidators = await validatorSetHbbft.getPendingValidators(); - pendingValidators.length.should.be.equal(0); - - const pools = await stakingHbbft.getPoolsToBeElected(); - pools.length.should.be.equal(0); + expect(await stakingHbbft.stakingEpoch()).to.be.equal(1n); + expect(await validatorSetHbbft.getValidators()).to.be.lengthOf(3); + // Docs: The pendingValidators set returned by the ValidatorSet contract is empty in this phase,. + expect(await validatorSetHbbft.getPendingValidators()).to.be.empty; + expect(await stakingHbbft.getPoolsToBeElected()).to.be.empty; }); it('validators and their delegators place stakes during the epoch #1', async () => { @@ -245,483 +666,361 @@ describe('BlockRewardHbbft', () => { for (let i = 0; i < validators.length; i++) { const stakingAddress = await validatorSetHbbft.stakingByMiningAddress(validators[i]); + // Validator places stake on themselves - await stakingHbbft.connect(ethers.provider.getSigner(stakingAddress)).stake(stakingAddress, { value: candidateMinStake }); + await stakingHbbft.connect(await ethers.provider.getSigner(stakingAddress)).stake( + stakingAddress, + { value: candidateMinStake } + ); + const delegatorsLength = 3; const delegators = accounts.slice(11 + i * delegatorsLength, 11 + i * delegatorsLength + delegatorsLength); for (let j = 0; j < delegators.length; j++) { // Delegator places stake on the validator - await stakingHbbft.connect(delegators[j]).stake(stakingAddress, { value: delegatorMinStake }); + await stakingHbbft.connect(delegators[j]).stake( + stakingAddress, + { value: delegatorMinStake } + ); } } }); it('staking epoch #1 finished', async () => { - - const stakingEpoch = await stakingHbbft.stakingEpoch(); - stakingEpoch.should.be.equal(BigNumber.from(1)); + expect(await stakingHbbft.stakingEpoch()).to.equal(1n); // const stakingEpochStartBlock = await stakingHbbft.stakingEpochStartBlock(); // stakingEpochStartBlock.should.be.equal(STAKING_EPOCH_START_BLOCK.add(STAKING_EPOCH_DURATION)); - (await validatorSetHbbft.getPendingValidators()).length.should.be.equal(0); + expect(await validatorSetHbbft.getPendingValidators()).to.be.empty; // we have staked just before, now there should be 3 pools. - const pools = await stakingHbbft.getPoolsToBeElected(); - pools.length.should.be.equal(3); + expect(await stakingHbbft.getPoolsToBeElected()).to.be.lengthOf(3); //lets spin up the time until the beginning of the Transition phase. - await timeTravelToTransition(); + await timeTravelToTransition(stakingHbbft, blockRewardHbbft); let pendingValidators = await validatorSetHbbft.getPendingValidators(); - sortedEqual(pendingValidators, [ - accounts[1].address, - accounts[2].address, - accounts[3].address - ]); + + expect( + _.isEqual(_.sortBy(pendingValidators), _.sortBy([ + accounts[1].address, + accounts[2].address, + accounts[3].address + ])) + ).to.be.true; // now we are in phase 2. // Nodes are now responsible for creating a key together. // they have a timeframe for this (see ) // since we are now in phase 2 of the same epoch. - (await stakingHbbft.stakingEpoch()).should.be.equal('1'); - (await blockRewardHbbft.nativeRewardUndistributed()).should.be.equal(nativeRewardUndistributed); + expect(await stakingHbbft.stakingEpoch()).to.equal(1n); + expect(await blockRewardHbbft.nativeRewardUndistributed()).to.equal(nativeRewardUndistributed); - await timeTravelToEndEpoch(); + await timeTravelToEndEpoch(stakingHbbft, blockRewardHbbft); - //since the endEpoch happened, we should be in the epoch 2 now. const nextStakingEpoch = await stakingHbbft.stakingEpoch(); - nextStakingEpoch.should.be.equal('2'); + //since the endEpoch happened, we should be in the epoch 2 now. + expect(nextStakingEpoch).to.equal(2n); // pending validators get deleted after being finalized - (await validatorSetHbbft.getPendingValidators()).length.should.be.equal(0); + expect(await validatorSetHbbft.getPendingValidators()).to.be.empty; validators = await validatorSetHbbft.getValidators(); - sortedEqual(validators, [ - accounts[1].address, - accounts[2].address, - accounts[3].address - ]); + expect( + _.isEqual(_.sortBy(validators), _.sortBy([ + accounts[1].address, + accounts[2].address, + accounts[3].address + ])) + ).to.be.true; for (let i = 0; i < validators.length; i++) { + const stakingAddress = await validatorSetHbbft.stakingByMiningAddress(validators[i]); - (await blockRewardHbbft.snapshotPoolValidatorStakeAmount(nextStakingEpoch, validators[i])).should.be.equal( - candidateMinStake - ); - (await blockRewardHbbft.snapshotPoolTotalStakeAmount(nextStakingEpoch, validators[i])).should.be.equal( - candidateMinStake.add(delegatorMinStake.mul(BigNumber.from(3))) - ); + expect( + await stakingHbbft.snapshotPoolValidatorStakeAmount(nextStakingEpoch, stakingAddress) + ).to.equal(candidateMinStake); + + expect( + await stakingHbbft.snapshotPoolTotalStakeAmount(nextStakingEpoch, stakingAddress) + ).to.equal(candidateMinStake + delegatorMinStake * 3n); } }); - const addToDeltaPotValue = BigNumber.from(ethers.utils.parseEther('60')); - it('DMD Pots: filling delta pot', async () => { - - const stakingEpoch = await stakingHbbft.stakingEpoch(); - stakingEpoch.should.be.equal(BigNumber.from(2)); + expect(await stakingHbbft.stakingEpoch()).to.equal(2n); //checking preconditions. // get the current address pof the governance pot. + expect(await ethers.provider.getBalance(await blockRewardHbbft.getAddress())).to.equal(0n); - const blockRewardBalance = await ethers.provider.getBalance(blockRewardHbbft.address); - blockRewardBalance.should.be.equal('0'); - - (await blockRewardHbbft.deltaPot()).should.be.equal(BigNumber.from('0')); - (await blockRewardHbbft.reinsertPot()).should.be.equal(BigNumber.from('0')); + expect(await blockRewardHbbft.deltaPot()).to.equal(0n); + expect(await blockRewardHbbft.reinsertPot()).to.equal(0n); await blockRewardHbbft.addToDeltaPot({ value: addToDeltaPotValue }); - (await blockRewardHbbft.deltaPot()).should.be.equal(addToDeltaPotValue); + expect(await blockRewardHbbft.deltaPot()).to.equal(addToDeltaPotValue); }); - - it('DMD Pots: governance and validators got correct share.', async () => { + it('DMD Pots: governance pot got correct share.', async () => { const maxValidators = await validatorSetHbbft.maxValidators(); const currentValidators = await validatorSetHbbft.getValidators(); - currentValidators.length.should.be.equal(3); - const initialGovernancePotBalance = await getCurrentGovernancePotValue(); - stakingEpoch = await stakingHbbft.stakingEpoch(); - - await timeTravelToTransition(); - await timeTravelToEndEpoch(); - - const currentGovernancePotBalance = await getCurrentGovernancePotValue(); - const governancePotIncrease = currentGovernancePotBalance.sub(initialGovernancePotBalance); - const totalReward = addToDeltaPotValue.div(BigNumber.from('6000')).mul(BigNumber.from(currentValidators.length)).div(maxValidators); - const expectedDAOShare = totalReward.div(BigNumber.from('10')); + expect(currentValidators).to.be.lengthOf(3); - governancePotIncrease.should.to.be.equal(expectedDAOShare); + const initialGovernancePotBalance = await getCurrentGovernancePotValue(); - //since there are a lot of delegators, we need to calc it on a basis that pays out the validator min reward. - const minValidatorSharePercent = await blockRewardHbbft.VALIDATOR_MIN_REWARD_PERCENT(); + await timeTravelToTransition(stakingHbbft, blockRewardHbbft); + await timeTravelToEndEpoch(stakingHbbft, blockRewardHbbft); - const expectedValidatorReward = totalReward.sub(expectedDAOShare).div(BigNumber.from(currentValidators.length)).mul(minValidatorSharePercent).div(BigNumber.from('100')); - const actualValidatorReward = await blockRewardHbbft.getValidatorReward(stakingEpoch, currentValidators[1]); + const currentGovernancePotBalance = await getCurrentGovernancePotValue(); + const governancePotIncrease = currentGovernancePotBalance - initialGovernancePotBalance; - actualValidatorReward.should.be.equal(expectedValidatorReward); + const totalReward = addToDeltaPotValue / 6000n * BigInt(currentValidators.length) / maxValidators; + const expectedDAOShare = totalReward / 10n; + expect(governancePotIncrease).to.equal(expectedDAOShare); }); it('DMD Pots: reinsert pot works as expected.', async () => { const maxValidators = await validatorSetHbbft.maxValidators(); const currentValidators = await validatorSetHbbft.getValidators(); + //refilling the delta pot. const deltaPotCurrentValue = await blockRewardHbbft.deltaPot() - const fillUpMissing = addToDeltaPotValue.sub(deltaPotCurrentValue); + const fillUpMissing = addToDeltaPotValue - deltaPotCurrentValue; await blockRewardHbbft.addToDeltaPot({ value: fillUpMissing }); - (await blockRewardHbbft.deltaPot()).should.be.equal(addToDeltaPotValue); + expect(await blockRewardHbbft.deltaPot()).to.be.equal(addToDeltaPotValue); - const addedToReinsertPot = BigNumber.from(ethers.utils.parseEther('60')); + const addedToReinsertPot = ethers.parseEther('60'); await blockRewardHbbft.addToReinsertPot({ value: addedToReinsertPot }); - const reinsertPotAfterAdd = await blockRewardHbbft.reinsertPot(); - reinsertPotAfterAdd.should.be.equal(addedToReinsertPot); - - stakingEpoch = await stakingHbbft.stakingEpoch(); + expect(await blockRewardHbbft.reinsertPot()).to.be.equal(addedToReinsertPot); const initialGovernancePotBalance = await getCurrentGovernancePotValue(); - await timeTravelToTransition(); - await timeTravelToEndEpoch(); + await timeTravelToTransition(stakingHbbft, blockRewardHbbft); + await timeTravelToEndEpoch(stakingHbbft, blockRewardHbbft); const currentGovernancePotBalance = await getCurrentGovernancePotValue(); - const governancePotIncrease = currentGovernancePotBalance.sub(initialGovernancePotBalance); + const governancePotIncrease = currentGovernancePotBalance - initialGovernancePotBalance; - const totalReward = addToDeltaPotValue.div(BigNumber.from('6000')).add(addedToReinsertPot.div(BigNumber.from('6000'))).mul(BigNumber.from(currentValidators.length)).div(maxValidators); + const totalReward = (addToDeltaPotValue + addedToReinsertPot) / 6000n * BigInt(currentValidators.length) / maxValidators; - const expectedDAOShare = totalReward.div(BigNumber.from('10')); + const expectedDAOShare = totalReward / 10n; // we expect 1 wei difference, since the reward combination from 2 pots results in that. //expectedDAOShare.sub(governancePotIncrease).should.to.be.bignumber.lte(BigNumber.from('1')); - governancePotIncrease.should.to.be.equal(expectedDAOShare); - - //since there are a lot of delegators, we need to calc it on a basis that pays out the validator min reward. - const minValidatorSharePercent = await blockRewardHbbft.VALIDATOR_MIN_REWARD_PERCENT(); - const expectedValidatorReward = totalReward.sub(expectedDAOShare).div(BigNumber.from(currentValidators.length)).mul(minValidatorSharePercent).div(BigNumber.from('100')); - const actualValidatorReward = await blockRewardHbbft.getValidatorReward(stakingEpoch, currentValidators[1]); - - actualValidatorReward.should.be.equal(expectedValidatorReward); + expect(governancePotIncrease).to.be.equal(expectedDAOShare); }); it('transfers to reward contract works with 100k gas and fills reinsert pot', async () => { + const fillUpValue = ethers.parseEther('1'); - const fillUpValue = BigNumber.from(ethers.utils.parseEther('1')); - - const balanceBefore = BigNumber.from(await ethers.provider.getBalance(blockRewardHbbft.address)); - const reinsertPotBefore = BigNumber.from(await blockRewardHbbft.reinsertPot()); - + const balanceBefore = await ethers.provider.getBalance(await blockRewardHbbft.getAddress()); + const reinsertPotBefore = await blockRewardHbbft.reinsertPot(); let fillUpTx = { - to: blockRewardHbbft.address, + to: await blockRewardHbbft.getAddress(), value: fillUpValue, - gasLimit: '100000', - gasPrice: ethers.utils.parseUnits('100', 9) //in some configurations the default gasPrice is used here, it uses 0 instead.. + gasLimit: 100000n, + gasPrice: ethers.parseUnits('100', 9) //in some configurations the default gasPrice is used here, it uses 0 instead.. }; - //blockRewardHbbft.address await accounts[0].sendTransaction(fillUpTx); - const balanceAfter = BigNumber.from(await ethers.provider.getBalance(blockRewardHbbft.address)); - const reinsertPotAfter = BigNumber.from(await blockRewardHbbft.reinsertPot()); + const balanceAfter = await ethers.provider.getBalance(await blockRewardHbbft.getAddress()); + const reinsertPotAfter = await blockRewardHbbft.reinsertPot(); - balanceAfter.should.be.equal(balanceBefore.add(fillUpValue)); - reinsertPotAfter.should.be.equal(reinsertPotBefore.add(fillUpValue)); + expect(balanceAfter).to.equal(balanceBefore + fillUpValue); + expect(reinsertPotAfter).to.equal(reinsertPotBefore + fillUpValue); }); it('reduces the reward if the epoch was shorter than expected', async () => { const currentValidators = await validatorSetHbbft.getValidators(); const maxValidators = await validatorSetHbbft.maxValidators(); - stakingEpoch = await stakingHbbft.stakingEpoch(); + + const stakeBeforeReward = await getValidatorStake(currentValidators[1]); const initialGovernancePotBalance = await getCurrentGovernancePotValue(); - let _epochPercentage = BigNumber.from(30); - await finishEpochPrelim(_epochPercentage); + let _epochPercentage = 30n; + await finishEpochPrelim(stakingHbbft, blockRewardHbbft, _epochPercentage); const currentGovernancePotBalance = await getCurrentGovernancePotValue(); - const governancePotIncrease = currentGovernancePotBalance.sub(initialGovernancePotBalance); + const governancePotIncrease = currentGovernancePotBalance - initialGovernancePotBalance; let deltaPotValue = await blockRewardHbbft.deltaPot(); let reinsertPotValue = await blockRewardHbbft.reinsertPot(); - const deltaPotShare = deltaPotValue.mul(BigNumber.from(currentValidators.length)).mul(_epochPercentage).div(BigNumber.from('6000')).div(maxValidators).div(100); - const reinsertPotShare = reinsertPotValue.mul(BigNumber.from(currentValidators.length)).mul(_epochPercentage).div(BigNumber.from('6000')).div(maxValidators).div(100); + const deltaPotShare = deltaPotValue * BigInt(currentValidators.length) * _epochPercentage / 6000n / maxValidators / 100n; + const reinsertPotShare = reinsertPotValue * BigInt(currentValidators.length) * _epochPercentage / 6000n / maxValidators / 100n; const nativeRewardUndistributed = await blockRewardHbbft.nativeRewardUndistributed(); - const totalReward = deltaPotShare.add(reinsertPotShare).add(nativeRewardUndistributed); - const expectedDAOShare = totalReward.div(BigNumber.from('10')); + const totalReward = deltaPotShare + reinsertPotShare + nativeRewardUndistributed; + const expectedDAOShare = totalReward / 10n; // we expect 1 wei difference, since the reward combination from 2 pots results in that. //expectedDAOShare.sub(governancePotIncrease).should.to.be.bignumber.lte(BigNumber.from('1')); - governancePotIncrease.should.to.be.closeTo(expectedDAOShare, expectedDAOShare.div(100000)); + expect(governancePotIncrease).to.be.closeTo(expectedDAOShare, expectedDAOShare / 100000n); //since there are a lot of delegators, we need to calc it on a basis that pays out the validator min reward. const minValidatorSharePercent = await blockRewardHbbft.VALIDATOR_MIN_REWARD_PERCENT(); - const expectedValidatorReward = totalReward.sub(expectedDAOShare).div(BigNumber.from(currentValidators.length)).mul(minValidatorSharePercent).div(BigNumber.from('100')); - const actualValidatorReward = await blockRewardHbbft.getValidatorReward(stakingEpoch, currentValidators[1]); + const expectedValidatorReward = (totalReward - expectedDAOShare) / BigInt(currentValidators.length) * minValidatorSharePercent / 100n; - actualValidatorReward.should.be.closeTo(expectedValidatorReward, expectedValidatorReward.div(100000)); - }) + const stakeAfterReward = await getValidatorStake(currentValidators[1]); + const actualValidatorReward = stakeAfterReward - stakeBeforeReward; + + expect(actualValidatorReward).to.be.closeTo(expectedValidatorReward, expectedValidatorReward / 100000n); + }); it('gives full reward if the epoch was longer than expected', async () => { const currentValidators = await validatorSetHbbft.getValidators(); const maxValidators = await validatorSetHbbft.maxValidators(); - stakingEpoch = await stakingHbbft.stakingEpoch(); + + const stakeBeforeReward = await getValidatorStake(currentValidators[1]); const initialGovernancePotBalance = await getCurrentGovernancePotValue(); - let _epochPercentage = BigNumber.from(120); - await finishEpochPrelim(_epochPercentage); + let _epochPercentage = 120n; + await finishEpochPrelim(stakingHbbft, blockRewardHbbft, _epochPercentage); const currentGovernancePotBalance = await getCurrentGovernancePotValue(); - const governancePotIncrease = currentGovernancePotBalance.sub(initialGovernancePotBalance); + const governancePotIncrease = currentGovernancePotBalance - initialGovernancePotBalance; let deltaPotValue = await blockRewardHbbft.deltaPot(); let reinsertPotValue = await blockRewardHbbft.reinsertPot(); - const deltaPotShare = deltaPotValue.mul(BigNumber.from(currentValidators.length)).div(BigNumber.from('6000')).div(maxValidators); - const reinsertPotShare = reinsertPotValue.mul(BigNumber.from(currentValidators.length)).div(BigNumber.from('6000')).div(maxValidators); + const deltaPotShare = deltaPotValue * BigInt(currentValidators.length) / 6000n / maxValidators; + const reinsertPotShare = reinsertPotValue * BigInt(currentValidators.length) / 6000n / maxValidators; const nativeRewardUndistributed = await blockRewardHbbft.nativeRewardUndistributed(); - const totalReward = deltaPotShare.add(reinsertPotShare).add(nativeRewardUndistributed); - const expectedDAOShare = totalReward.div(BigNumber.from('10')); + const totalReward = deltaPotShare + reinsertPotShare + nativeRewardUndistributed; + const expectedDAOShare = totalReward / 10n; // we expect 1 wei difference, since the reward combination from 2 pots results in that. //expectedDAOShare.sub(governancePotIncrease).should.to.be.bignumber.lte(BigNumber.from('1')); - governancePotIncrease.should.to.be.closeTo(expectedDAOShare, expectedDAOShare.div(10000)); + expect(governancePotIncrease).to.be.closeTo(expectedDAOShare, expectedDAOShare / 10000n); //since there are a lot of delegators, we need to calc it on a basis that pays out the validator min reward. const minValidatorSharePercent = await blockRewardHbbft.VALIDATOR_MIN_REWARD_PERCENT(); - const expectedValidatorReward = totalReward.sub(expectedDAOShare).div(BigNumber.from(currentValidators.length)).mul(minValidatorSharePercent).div(BigNumber.from('100')); - const actualValidatorReward = await blockRewardHbbft.getValidatorReward(stakingEpoch, currentValidators[1]); + const expectedValidatorReward = (totalReward - expectedDAOShare) / BigInt(currentValidators.length) * minValidatorSharePercent / 100n; - actualValidatorReward.should.be.closeTo(expectedValidatorReward, expectedValidatorReward.div(10000)); - }) + const stakeAfterReward = await getValidatorStake(currentValidators[1]); + const actualValidatorReward = stakeAfterReward - stakeBeforeReward; - it("epochsToClaimRewardFrom should return correct values", async () => { - const miningAddress = (await validatorSetHbbft.getValidators())[0]; //mining address - const stakingAddress = await validatorSetHbbft.stakingByMiningAddress(miningAddress); //stakingaddress - (await blockRewardHbbft.epochsToClaimRewardFrom(stakingAddress, stakingAddress))[0].should.be.eq(2); - (await blockRewardHbbft.epochsToClaimRewardFrom(stakingAddress, accounts[11].address))[0].should.be.eq(2); - }) - - it("validatorRewardPercent should return correct values", async () => { - const miningAddress = (await validatorSetHbbft.getValidators())[2]; //mining address - const stakingAddress = await validatorSetHbbft.stakingByMiningAddress(miningAddress); //stakingaddress - //percentage of a validator with delegators should be equal 30% - (await blockRewardHbbft.validatorRewardPercent(stakingAddress)).should.be.equal(300000); - }) + expect(actualValidatorReward).to.be.closeTo(expectedValidatorReward, expectedValidatorReward / 10000n); + }); it("should end epoch earlier if notified", async () => { - (await blockRewardHbbft.setConnectivityTracker(owner.address)).should.not.be.reverted; + expect(await blockRewardHbbft.setConnectivityTracker(owner.address)).to.not.be.reverted; - (await blockRewardHbbft.earlyEpochEnd()).should.be.false; - (await blockRewardHbbft.connect(owner).notifyEarlyEpochEnd()).should.not.be.reverted; - (await blockRewardHbbft.earlyEpochEnd()).should.be.true; + expect(await blockRewardHbbft.earlyEpochEnd()).to.be.false; + expect(await blockRewardHbbft.connect(owner).notifyEarlyEpochEnd()).to.not.be.reverted; + expect(await blockRewardHbbft.earlyEpochEnd()).to.be.true; - await blockRewardHbbft.setSystemAddress(owner.address); - (await blockRewardHbbft.connect(owner).reward(false)).should.emit( + const systemSigner = await impersonateAcc(SystemAccountAddress); + + expect(await blockRewardHbbft.connect(systemSigner).reward(false)).to.emit( blockRewardHbbft, "CoinsRewarded" ); - await blockRewardHbbft.setSystemAddress(SystemAddress); + await helpers.stopImpersonatingAccount(SystemAccountAddress); }); it("should not end epoch earlier if not notified", async () => { - (await blockRewardHbbft.earlyEpochEnd()).should.be.false; + expect(await blockRewardHbbft.earlyEpochEnd()).to.be.false; + + const systemSigner = await impersonateAcc(SystemAccountAddress); - await blockRewardHbbft.setSystemAddress(owner.address); - (await blockRewardHbbft.connect(owner).reward(false)).should.not.emit( + expect(await blockRewardHbbft.connect(systemSigner).reward(false)).to.not.emit( blockRewardHbbft, "CoinsRewarded" ); - await blockRewardHbbft.setSystemAddress(SystemAddress); + await helpers.stopImpersonatingAccount(SystemAccountAddress); }); it("should restrict calling notifyEarlyEpochEnd to connectivity tracker contract only", async () => { const allowedCaller = accounts[10]; const caller = accounts[11]; - (await blockRewardHbbft.setConnectivityTracker(allowedCaller.address)).should.not.be.reverted; - (await blockRewardHbbft.connectivityTracker()).should.be.equal(allowedCaller.address); + expect(await blockRewardHbbft.setConnectivityTracker(allowedCaller.address)).to.not.be.reverted; + expect(await blockRewardHbbft.connectivityTracker()).to.be.equal(allowedCaller.address); - await (blockRewardHbbft.connect(caller).notifyEarlyEpochEnd()).should.be.reverted; - (await blockRewardHbbft.connect(allowedCaller).notifyEarlyEpochEnd()).should.not.be.reverted; + await expect(blockRewardHbbft.connect(caller).notifyEarlyEpochEnd()).to.be.reverted; + expect(await blockRewardHbbft.connect(allowedCaller).notifyEarlyEpochEnd()).to.not.be.reverted; }); - describe("Upscaling tests", async () => { - it("Add multiple validator pools and upscale if needed.", async () => { - const accountAddresses = accounts.map(item => item.address); - const additionalValidators = accountAddresses.slice(7, 52 + 1); // accounts[7...32] - const additionalStakingAddresses = accountAddresses.slice(53, 99 + 1); // accounts[33...59] - - additionalValidators.length.should.be.equal(46); - additionalStakingAddresses.length.should.be.equal(46); + it("upscaling: add multiple validator pools and upscale if needed.", async () => { + const accountAddresses = accounts.map(item => item.address); + const additionalValidators = accountAddresses.slice(7, 52 + 1); // accounts[7...32] + const additionalStakingAddresses = accountAddresses.slice(53, 99 + 1); // accounts[33...59] - await network.provider.send("evm_setIntervalMining", [8]); + expect(additionalValidators).to.be.lengthOf(46); + expect(additionalStakingAddresses).to.be.lengthOf(46); - for (let i = 0; i < additionalValidators.length; i++) { - let stakingAddress = await ethers.getSigner(additionalStakingAddresses[i]); - let miningAddress = await ethers.getSigner(additionalValidators[i]); + await network.provider.send("evm_setIntervalMining", [8]); - await stakingHbbft.connect(stakingAddress).addPool(miningAddress.address, '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - '0x00000000000000000000000000000000', { value: MIN_STAKE }); - await announceAvailability(miningAddress.address); - await mine(); + for (let i = 0; i < additionalValidators.length; i++) { + let stakingAddress = await ethers.getSigner(additionalStakingAddresses[i]); + let miningAddress = await ethers.getSigner(additionalValidators[i]); - let toBeElected = (await stakingHbbft.getPoolsToBeElected()).length; - let pendingValidators = (await validatorSetHbbft.getPendingValidators()).length - if (toBeElected > 4 && toBeElected <= 19 && pendingValidators == 0) { - (await validatorSetHbbft.getValidatorCountSweetSpot((await stakingHbbft.getPoolsToBeElected()).length)).should.be.equal((await validatorSetHbbft.getValidators()).length); - } - } + await stakingHbbft.connect(stakingAddress).addPool( + miningAddress.address, + ethers.zeroPadBytes("0x00", 64), + ethers.zeroPadBytes("0x00", 16), + { value: MIN_STAKE } + ); + await announceAvailability(miningAddress.address); + await mine(); - await timeTravelToTransition(); - await timeTravelToEndEpoch(); - // after epoch was finalized successfully, validator set length is healthy - (await validatorSetHbbft.getValidators()).length.should.be.eq(25); - (await stakingHbbft.getPoolsToBeElected()).length.should.be.eq(49); - }) - - it("banning validator up to 16", async () => { - await validatorSetHbbft.setSystemAddress(owner.address); - while ((await validatorSetHbbft.getValidators()).length > 16) { - await mine(); - await validatorSetHbbft.connect(owner).removeMaliciousValidators([(await validatorSetHbbft.getValidators())[13]]); + let toBeElected = (await stakingHbbft.getPoolsToBeElected()).length; + let pendingValidators = (await validatorSetHbbft.getPendingValidators()).length + if (toBeElected > 4 && toBeElected <= 19 && pendingValidators == 0) { + expect(await validatorSetHbbft.getValidatorCountSweetSpot((await stakingHbbft.getPoolsToBeElected()).length)) + .to.be.equal((await validatorSetHbbft.getValidators()).length); } - (await validatorSetHbbft.getValidators()).length.should.be.eq(16); - }) - it("mining twice shouldn't change pending validator set", async () => { - await callReward(false); - (await validatorSetHbbft.getPendingValidators()).length.should.be.eq(25); - let pendingValidators = await validatorSetHbbft.getPendingValidators(); - await callReward(false); - sortedEqual(pendingValidators, await validatorSetHbbft.getPendingValidators()); - }) - it("set is scaled to 25", async () => { - await mine(); - (await validatorSetHbbft.getValidators()).length.should.be.eq(25); - (await validatorSetHbbft.getPendingValidators()).length.should.be.eq(0); - await network.provider.send("evm_setIntervalMining", [0]); - }) - }) -}); + } -function sortedEqual(arr1: T[], arr2: T[]): void { - [...arr1].sort().should.be.deep.equal([...arr2].sort()); -} - -// async function callFinalizeChange() { -// await validatorSetHbbft.setSystemAddress(owner); -// await validatorSetHbbft.finalizeChange({from: owner}); -// await validatorSetHbbft.setSystemAddress(SystemAddress); -// } - -async function getCurrentGovernancePotValue() { - const governnancePotAddress = await blockRewardHbbft.governancePotAddress(); - (BigNumber.from(governnancePotAddress)).should.be.gt(BigNumber.from(0)); - const result = BigNumber.from(await ethers.provider.getBalance(governnancePotAddress)); - return result; -} - - -async function callReward(isEpochEndBlock: boolean) { - // console.log('getting validators...'); - // note: this call used to crash because of a internal problem with a previous call of evm_mine and evm_increase_time https://github.com/DMDcoin/hbbft-posdao-contracts/issues/13 - // const validators = await validatorSetHbbft.getValidators(); - // console.log('got validators:', validators); - await blockRewardHbbft.setSystemAddress(owner.address); - await blockRewardHbbft.connect(owner).reward(isEpochEndBlock); - await blockRewardHbbft.setSystemAddress(SystemAddress); -} - -// time travels forward to the beginning of the next transition, -// and simulate a block mining (calling reward()) -async function timeTravelToTransition() { - let startTimeOfNextPhaseTransition = await stakingHbbft.startTimeOfNextPhaseTransition(); - - await helpers.time.increaseTo(startTimeOfNextPhaseTransition); - await callReward(false); -} - -async function timeTravelToEndEpoch() { - const endTimeOfCurrentEpoch = await stakingHbbft.stakingFixedEpochEndTime(); - - await helpers.time.increaseTo(endTimeOfCurrentEpoch); - await callReward(true); -} - -async function finishEpochPrelim(_percentage: BigNumber) { - const epochDuration = (await stakingHbbft.stakingFixedEpochEndTime()).sub((await stakingHbbft.stakingEpochStartTime())).mul(_percentage).div(100).add(1); - const endTimeOfCurrentEpoch = (await stakingHbbft.stakingEpochStartTime()).add(epochDuration); - - await helpers.time.increaseTo(endTimeOfCurrentEpoch.toNumber()); - await callReward(true); -} - -async function announceAvailability(pool: string) { - const blockNumber = await ethers.provider.getBlockNumber() - const block = await ethers.provider.getBlock(blockNumber); - const asEncoded = validatorSetHbbft.interface.encodeFunctionData("announceAvailability", [blockNumber, block.hash]); - - // we know now, that this call is allowed. - // so we can execute it. - await (await ethers.getSigner(pool)).sendTransaction({ to: validatorSetHbbft.address, data: asEncoded }); -} - -async function mine() { - let expectedEpochDuration = (await stakingHbbft - .stakingFixedEpochEndTime()).sub(await stakingHbbft.stakingEpochStartTime()); - let blocktime = expectedEpochDuration.mul(5).div(100).add(1); //5% of the epoch - // let blocksPerEpoch = 60 * 60 * 12 / blocktime; - - await helpers.time.increase(blocktime.toNumber()); - - if ((await validatorSetHbbft.getPendingValidators()).length > 0) { - const currentValidators = await validatorSetHbbft.getValidators(); - const maxValidators = await validatorSetHbbft.maxValidators(); - stakingEpoch = await stakingHbbft.stakingEpoch(); + await timeTravelToTransition(stakingHbbft, blockRewardHbbft); + await timeTravelToEndEpoch(stakingHbbft, blockRewardHbbft); - const initialGovernancePotBalance = await getCurrentGovernancePotValue(); - let deltaPotValue = await blockRewardHbbft.deltaPot(); - let reinsertPotValue = await blockRewardHbbft.reinsertPot(); - let _epochPercentage = await blockRewardHbbft.epochPercentage(); + // after epoch was finalized successfully, validator set length is healthy + expect(await validatorSetHbbft.getValidators()).to.be.lengthOf(25); + expect(await stakingHbbft.getPoolsToBeElected()).to.be.lengthOf(49); + }) - await callReward(true); + it("upscaling: banning validator up to 16", async () => { + await validatorSetHbbft.setSystemAddress(owner.address); - const currentGovernancePotBalance = await getCurrentGovernancePotValue(); - const governancePotIncrease = currentGovernancePotBalance.sub(initialGovernancePotBalance); + while ((await validatorSetHbbft.getValidators()).length > 16) { + await mine(); + await validatorSetHbbft.connect(owner).removeMaliciousValidators([(await validatorSetHbbft.getValidators())[13]]); + } + expect(await validatorSetHbbft.getValidators()).to.be.lengthOf(16); + }); - const deltaPotShare = deltaPotValue.mul(BigNumber.from(currentValidators.length)).mul(_epochPercentage).div(BigNumber.from('6000')).div(maxValidators).div(100); - const reinsertPotShare = reinsertPotValue.mul(BigNumber.from(currentValidators.length)).mul(_epochPercentage).div(BigNumber.from('6000')).div(maxValidators).div(100); - const nativeRewardUndistributed = await blockRewardHbbft.nativeRewardUndistributed(); + it("upscaling: mining twice shouldn't change pending validator set", async () => { + await callReward(blockRewardHbbft, false); + expect(await validatorSetHbbft.getPendingValidators()).to.be.lengthOf(25); + let pendingValidators = await validatorSetHbbft.getPendingValidators(); - const totalReward = deltaPotShare.add(reinsertPotShare).add(nativeRewardUndistributed); - const expectedDAOShare = totalReward.div(BigNumber.from('10')); + await callReward(blockRewardHbbft, false); - // we expect 1 wei difference, since the reward combination from 2 pots results in that. - //expectedDAOShare.sub(governancePotIncrease).should.to.be.bignumber.lte(BigNumber.from('1')); - governancePotIncrease.should.to.be.closeTo(expectedDAOShare, expectedDAOShare.div(10000)); + expect( + _.isEqual(_.sortBy(pendingValidators), _.sortBy(await validatorSetHbbft.getPendingValidators())) + ).to.be.true; + }); - //since there are a lot of delegators, we need to calc it on a basis that pays out the validator min reward. - let minValidatorSharePercent = 100; - //staking address of the validator - let stakingAddress = await validatorSetHbbft.stakingByMiningAddress(currentValidators[currentValidators.length - 1]) - ///first 4 validators have delegators so they receive less DMD - if ((await stakingHbbft.poolDelegators(stakingAddress)).length) { - minValidatorSharePercent = 30; - } + it("upscaling: set is scaled to 25", async () => { + await mine(); - const expectedValidatorReward = totalReward.sub(expectedDAOShare).div(BigNumber.from(currentValidators.length)).mul(minValidatorSharePercent).div(BigNumber.from('100')); - const actualValidatorReward = await blockRewardHbbft.getValidatorReward(stakingEpoch, currentValidators[currentValidators.length - 1]); + expect(await validatorSetHbbft.getValidators()).to.be.lengthOf(25); + expect(await validatorSetHbbft.getPendingValidators()).to.be.empty; - actualValidatorReward.should.be.closeTo(expectedValidatorReward, expectedValidatorReward.div(10000)); - } else { - await callReward(false); - } -} + await network.provider.send("evm_setIntervalMining", [0]); + }); +}); diff --git a/test/CertifierHbbft.ts b/test/CertifierHbbft.ts index b2bba96e..19198bb0 100644 --- a/test/CertifierHbbft.ts +++ b/test/CertifierHbbft.ts @@ -1,15 +1,15 @@ import { ethers, upgrades } from "hardhat"; -import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers"; import { expect } from "chai"; -import * as helpers from "@nomicfoundation/hardhat-network-helpers"; +import { HardhatEthersSigner } from "@nomicfoundation/hardhat-ethers/signers"; +import { loadFixture } from "@nomicfoundation/hardhat-network-helpers"; import { CertifierHbbft, ValidatorSetHbbftMock } from "../src/types"; const validatorInactivityThreshold = 365 * 86400 // 1 year describe('CertifierHbbft contract', () => { - let accounts: SignerWithAddress[]; - let owner: SignerWithAddress; + let accounts: HardhatEthersSigner[]; + let owner: HardhatEthersSigner; let initialValidators: string[]; let initialStakingAddresses: string[]; @@ -19,9 +19,9 @@ describe('CertifierHbbft contract', () => { async function deployContracts() { const stubAddress = accounts[1].address; - const ValidatorSetFactory = await ethers.getContractFactory("ValidatorSetHbbftMock"); - const validatorSetHbbft = await upgrades.deployProxy( - ValidatorSetFactory, + const validatorSetFactory = await ethers.getContractFactory("ValidatorSetHbbftMock"); + const validatorSetHbbftProxy = await upgrades.deployProxy( + validatorSetFactory, [ owner.address, stubAddress, // _blockRewardContract @@ -33,27 +33,33 @@ describe('CertifierHbbft contract', () => { initialStakingAddresses, // _initialStakingAddresses ], { initializer: 'initialize' } - ) as ValidatorSetHbbftMock; + ); - await validatorSetHbbft.deployed(); + await validatorSetHbbftProxy.waitForDeployment(); - const CertifierFactory = await ethers.getContractFactory("CertifierHbbft"); - const certifier = await upgrades.deployProxy( - CertifierFactory, + const certifierFactory = await ethers.getContractFactory("CertifierHbbft"); + const certifierProxy = await upgrades.deployProxy( + certifierFactory, [ [owner.address], - validatorSetHbbft.address, + await validatorSetHbbftProxy.getAddress(), owner.address ], { initializer: 'initialize' } - ) as CertifierHbbft; + ); + + await certifierProxy.waitForDeployment(); + + const validatorSetHbbft = validatorSetFactory.attach( + await validatorSetHbbftProxy.getAddress() + ) as ValidatorSetHbbftMock; - await certifier.deployed(); + const certifier = certifierFactory.attach(await certifierProxy.getAddress()) as CertifierHbbft; return { certifier, validatorSetHbbft }; } - before(async function() { + before(async function () { [owner, ...accounts] = await ethers.getSigners(); accountAddresses = accounts.map(item => item.address); @@ -68,7 +74,7 @@ describe('CertifierHbbft contract', () => { contractFactory, [ [], - ethers.constants.AddressZero, + ethers.ZeroAddress, owner.address ], { initializer: 'initialize' } @@ -82,7 +88,7 @@ describe('CertifierHbbft contract', () => { [ [], accounts[1].address, - ethers.constants.AddressZero + ethers.ZeroAddress ], { initializer: 'initialize' } )).to.be.revertedWith('Owner address must not be 0'); @@ -100,7 +106,7 @@ describe('CertifierHbbft contract', () => { { initializer: 'initialize' } ); - expect(await contract.deployed()); + expect(await contract.waitForDeployment()); await expect(contract.initialize( [], @@ -111,8 +117,8 @@ describe('CertifierHbbft contract', () => { }); describe('certification', async () => { - it('should restrict calling certify to contract owner', async function() { - const { certifier } = await helpers.loadFixture(deployContracts); + it('should restrict calling certify to contract owner', async function () { + const { certifier } = await loadFixture(deployContracts); const caller = accounts[5]; @@ -120,8 +126,8 @@ describe('CertifierHbbft contract', () => { .to.be.revertedWith('Ownable: caller is not the owner'); }); - it('should restrict calling revoke to contract owner', async function() { - const { certifier } = await helpers.loadFixture(deployContracts); + it('should restrict calling revoke to contract owner', async function () { + const { certifier } = await loadFixture(deployContracts); const caller = accounts[5]; @@ -129,8 +135,8 @@ describe('CertifierHbbft contract', () => { .to.be.revertedWith('Ownable: caller is not the owner'); }); - it("should sertify address", async function() { - const { certifier } = await helpers.loadFixture(deployContracts); + it("should sertify address", async function () { + const { certifier } = await loadFixture(deployContracts); const who = accounts[4]; await expect(certifier.connect(owner).certify(who.address)) @@ -141,8 +147,8 @@ describe('CertifierHbbft contract', () => { expect(await certifier.certified(who.address)).to.be.true; }); - it("should revoke cerification", async function() { - const { certifier } = await helpers.loadFixture(deployContracts); + it("should revoke cerification", async function () { + const { certifier } = await loadFixture(deployContracts); const who = accounts[6]; await expect(certifier.connect(owner).certify(who.address)) @@ -155,12 +161,12 @@ describe('CertifierHbbft contract', () => { .to.emit(certifier, "Revoked") .withArgs(who.address); - expect(await certifier.certifiedExplicitly(who.address)).to.be.false; - expect(await certifier.certified(who.address)).to.be.false; + expect(await certifier.certifiedExplicitly(who.address)).to.be.false; + expect(await certifier.certified(who.address)).to.be.false; }); - it("validator account should be certified by default", async function() { - const { certifier } = await helpers.loadFixture(deployContracts); + it("validator account should be certified by default", async function () { + const { certifier } = await loadFixture(deployContracts); expect(await certifier.certifiedExplicitly(initialValidators[0])).to.be.false; expect(await certifier.certified(initialValidators[0])).to.be.true; diff --git a/test/ConnectivityTrackerHbbft.ts b/test/ConnectivityTrackerHbbft.ts index 43e7517a..6f82a577 100644 --- a/test/ConnectivityTrackerHbbft.ts +++ b/test/ConnectivityTrackerHbbft.ts @@ -1,7 +1,6 @@ import { ethers, upgrades } from "hardhat"; import { expect } from "chai"; -import { BigNumber } from "ethers"; -import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers"; +import { HardhatEthersSigner } from "@nomicfoundation/hardhat-ethers/signers"; import * as helpers from "@nomicfoundation/hardhat-network-helpers"; import fp from "lodash/fp"; @@ -10,21 +9,21 @@ import { ValidatorSetHbbftMock, StakingHbbftMock, BlockRewardHbbftMock, - KeyGenHistory, } from "../src/types"; -import { keccak256 } from "ethers/lib/utils"; + +import { getNValidatorsPartNAcks } from "./testhelpers/data"; describe('ConnectivityTrackerHbbft', () => { const validatorInactivityThreshold = 86400 // 1 day const minReportAgeBlocks = 10; - let accounts: SignerWithAddress[]; - let owner: SignerWithAddress; + let accounts: HardhatEthersSigner[]; + let owner: HardhatEthersSigner; let addresses: string[] - let initialValidators: SignerWithAddress[]; - let initialStakingAccounts: SignerWithAddress[]; + let initialValidators: HardhatEthersSigner[]; + let initialStakingAccounts: HardhatEthersSigner[]; - let nonValidators: SignerWithAddress[]; + let nonValidators: HardhatEthersSigner[]; before(async () => { accounts = await ethers.getSigners(); @@ -42,33 +41,11 @@ describe('ConnectivityTrackerHbbft', () => { const validatorAddresses = initialValidators.map(x => x.address); const stakingAddresses = initialStakingAccounts.map(x => x.address); - const parts = Array(initialValidators.length).fill([ - 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 181, 129, 31, 84, 186, 242, 5, 151, 59, 35, 196, - 140, 106, 29, 40, 112, 142, 156, 132, 158, 47, 223, 253, 185, 227, 249, 190, 96, 5, 99, 239, 213, - 127, 29, 136, 115, 71, 164, 202, 44, 6, 171, 131, 251, 147, 159, 54, 49, 1, 0, 0, 0, 0, 0, 0, 0, - 153, 0, 0, 0, 0, 0, 0, 0, 4, 177, 133, 61, 18, 58, 222, 74, 65, 5, 126, 253, 181, 113, 165, 43, - 141, 56, 226, 132, 208, 218, 197, 119, 179, 128, 30, 162, 251, 23, 33, 73, 38, 120, 246, 223, 233, - 11, 104, 60, 154, 241, 182, 147, 219, 81, 45, 134, 239, 69, 169, 198, 188, 152, 95, 254, 170, 108, - 60, 166, 107, 254, 204, 195, 170, 234, 154, 134, 26, 91, 9, 139, 174, 178, 248, 60, 65, 196, 218, - 46, 163, 218, 72, 1, 98, 12, 109, 186, 152, 148, 159, 121, 254, 34, 112, 51, 70, 121, 51, 167, 35, - 240, 5, 134, 197, 125, 252, 3, 213, 84, 70, 176, 160, 36, 73, 140, 104, 92, 117, 184, 80, 26, 240, - 106, 230, 241, 26, 79, 46, 241, 195, 20, 106, 12, 186, 49, 254, 168, 233, 25, 179, 96, 62, 104, 118, - 153, 95, 53, 127, 160, 237, 246, 41 - ]); - const acks = Array(initialValidators.length).fill([ - [0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 145, 0, 0, 0, 0, 0, 0, 0, 4, 239, 1, 112, 13, 13, 251, - 103, 186, 212, 78, 44, 47, 250, 221, 84, 118, 88, 7, 64, 206, 186, 11, 2, 8, 204, 140, 106, 179, - 52, 251, 237, 19, 53, 74, 187, 217, 134, 94, 66, 68, 89, 42, 85, 207, 155, 220, 101, 223, 51, 199, - 37, 38, 203, 132, 13, 77, 78, 114, 53, 219, 114, 93, 21, 25, 164, 12, 43, 252, 160, 16, 23, 111, - 79, 230, 121, 95, 223, 174, 211, 172, 231, 0, 52, 25, 49, 152, 79, 128, 39, 117, 216, 85, 201, 237, - 242, 151, 219, 149, 214, 77, 233, 145, 47, 10, 184, 175, 162, 174, 237, 177, 131, 45, 126, 231, 32, - 147, 227, 170, 125, 133, 36, 123, 164, 232, 129, 135, 196, 136, 186, 45, 73, 226, 179, 169, 147, 42, - 41, 140, 202, 191, 12, 73, 146, 2] - ]); - - const ValidatorSetFactory = await ethers.getContractFactory("ValidatorSetHbbftMock"); - const validatorSetHbbft = await upgrades.deployProxy( - ValidatorSetFactory, + const { parts, acks } = getNValidatorsPartNAcks(initialValidators.length); + + const validatorSetFactory = await ethers.getContractFactory("ValidatorSetHbbftMock"); + const validatorSetHbbftProxy = await upgrades.deployProxy( + validatorSetFactory, [ owner.address, stubAddress, // _blockRewardContract @@ -80,48 +57,48 @@ describe('ConnectivityTrackerHbbft', () => { stakingAddresses, // _initialStakingAddresses ], { initializer: 'initialize' } - ) as ValidatorSetHbbftMock; + ); - await validatorSetHbbft.deployed(); + await validatorSetHbbftProxy.waitForDeployment(); - const KeyGenFactory = await ethers.getContractFactory("KeyGenHistory"); + const keyGenFactoryFactory = await ethers.getContractFactory("KeyGenHistory"); const keyGenHistory = await upgrades.deployProxy( - KeyGenFactory, + keyGenFactoryFactory, [ owner.address, - validatorSetHbbft.address, + await validatorSetHbbftProxy.getAddress(), validatorAddresses, parts, acks ], { initializer: 'initialize' } - ) as KeyGenHistory; + ); let stakingParams = { - _validatorSetContract: validatorSetHbbft.address, + _validatorSetContract: await validatorSetHbbftProxy.getAddress(), _initialStakingAddresses: stakingAddresses, - _delegatorMinStake: ethers.utils.parseEther('1'), - _candidateMinStake: ethers.utils.parseEther('10'), - _maxStake: ethers.utils.parseEther('100'), - _stakingFixedEpochDuration: BigNumber.from(86400), - _stakingTransitionTimeframeLength: BigNumber.from(3600), - _stakingWithdrawDisallowPeriod: BigNumber.from(1) + _delegatorMinStake: ethers.parseEther('1'), + _candidateMinStake: ethers.parseEther('10'), + _maxStake: ethers.parseEther('100'), + _stakingFixedEpochDuration: 86400n, + _stakingTransitionTimeframeLength: 3600n, + _stakingWithdrawDisallowPeriod: 1n }; let initialValidatorsPubKeys: string[] = []; let initialValidatorsIpAddresses: string[] = []; for (let i = 0; i < stakingAddresses.length; i++) { - initialValidatorsPubKeys.push(ethers.Wallet.createRandom().publicKey); - initialValidatorsIpAddresses.push('0x00000000000000000000000000000000'); + initialValidatorsPubKeys.push(ethers.Wallet.createRandom().signingKey.publicKey); + initialValidatorsIpAddresses.push(ethers.zeroPadBytes("0x00", 16)); } let initialValidatorsPubKeysSplit = fp.flatMap((x: string) => [x.substring(0, 66), '0x' + x.substring(66, 130)]) (initialValidatorsPubKeys); - const StakingHbbftFactory = await ethers.getContractFactory("StakingHbbftMock"); - const stakingHbbft = await upgrades.deployProxy( - StakingHbbftFactory, + const stakingHbbftFactory = await ethers.getContractFactory("StakingHbbftMock"); + const stakingHbbftProxy = await upgrades.deployProxy( + stakingHbbftFactory, [ owner.address, stakingParams, @@ -130,41 +107,58 @@ describe('ConnectivityTrackerHbbft', () => { ], { initializer: 'initialize' } - ) as StakingHbbftMock; + ); - await stakingHbbft.deployed(); + await stakingHbbftProxy.waitForDeployment(); - const BlockRewardHbbftFactory = await ethers.getContractFactory("BlockRewardHbbftMock"); - const blockRewardHbbft = await upgrades.deployProxy( - BlockRewardHbbftFactory, + const blockRewardHbbftFactory = await ethers.getContractFactory("BlockRewardHbbftMock"); + const blockRewardHbbftProxy = await upgrades.deployProxy( + blockRewardHbbftFactory, [ owner.address, - validatorSetHbbft.address, + await validatorSetHbbftProxy.getAddress(), stubAddress ], { initializer: 'initialize' } - ) as BlockRewardHbbftMock; + ); - await blockRewardHbbft.deployed(); + await blockRewardHbbftProxy.waitForDeployment(); - const ConnectivityTrackerFactory = await ethers.getContractFactory("ConnectivityTrackerHbbft"); - const connectivityTracker = await upgrades.deployProxy( - ConnectivityTrackerFactory, + const connectivityTrackerFactory = await ethers.getContractFactory("ConnectivityTrackerHbbft"); + const connectivityTrackerProxy = await upgrades.deployProxy( + connectivityTrackerFactory, [ owner.address, - validatorSetHbbft.address, - stakingHbbft.address, - blockRewardHbbft.address, + await validatorSetHbbftProxy.getAddress(), + await stakingHbbftProxy.getAddress(), + await blockRewardHbbftProxy.getAddress(), minReportAgeBlocks, ], { initializer: 'initialize' } + ); + + await connectivityTrackerProxy.waitForDeployment(); + + const validatorSetHbbft = validatorSetFactory.attach( + await validatorSetHbbftProxy.getAddress() + ) as ValidatorSetHbbftMock; + + const stakingHbbft = stakingHbbftFactory.attach( + await stakingHbbftProxy.getAddress() + ) as StakingHbbftMock; + + const blockRewardHbbft = blockRewardHbbftFactory.attach( + await blockRewardHbbftProxy.getAddress() + ) as BlockRewardHbbftMock; + + const connectivityTracker = connectivityTrackerFactory.attach( + await connectivityTrackerProxy.getAddress() ) as ConnectivityTrackerHbbft; - await connectivityTracker.deployed(); - await blockRewardHbbft.setConnectivityTracker(connectivityTracker.address); - await validatorSetHbbft.setStakingContract(stakingHbbft.address); - await validatorSetHbbft.setBlockRewardContract(blockRewardHbbft.address); - await validatorSetHbbft.setKeyGenHistoryContract(keyGenHistory.address); + await blockRewardHbbft.setConnectivityTracker(await connectivityTracker.getAddress()); + await validatorSetHbbft.setStakingContract(await stakingHbbft.getAddress()); + await validatorSetHbbft.setBlockRewardContract(await blockRewardHbbft.getAddress()); + await validatorSetHbbft.setKeyGenHistoryContract(await keyGenHistory.getAddress()); return { connectivityTracker, validatorSetHbbft, stakingHbbft, blockRewardHbbft }; } @@ -174,7 +168,7 @@ describe('ConnectivityTrackerHbbft', () => { await owner.sendTransaction({ to: caller, - value: ethers.utils.parseEther('10'), + value: ethers.parseEther('10'), }); const latest = await helpers.time.latest(); @@ -193,7 +187,7 @@ describe('ConnectivityTrackerHbbft', () => { await expect(upgrades.deployProxy( ConnectivityTrackerFactory, [ - ethers.constants.AddressZero, + ethers.ZeroAddress, stubAddress, stubAddress, stubAddress, @@ -211,7 +205,7 @@ describe('ConnectivityTrackerHbbft', () => { ConnectivityTrackerFactory, [ owner.address, - ethers.constants.AddressZero, + ethers.ZeroAddress, stubAddress, stubAddress, minReportAgeBlocks @@ -229,7 +223,7 @@ describe('ConnectivityTrackerHbbft', () => { [ owner.address, stubAddress, - ethers.constants.AddressZero, + ethers.ZeroAddress, stubAddress, minReportAgeBlocks ], @@ -247,7 +241,7 @@ describe('ConnectivityTrackerHbbft', () => { owner.address, stubAddress, stubAddress, - ethers.constants.AddressZero, + ethers.ZeroAddress, minReportAgeBlocks ], { initializer: 'initialize' } @@ -270,7 +264,7 @@ describe('ConnectivityTrackerHbbft', () => { { initializer: 'initialize' } ); - expect(await contract.deployed()); + expect(await contract.waitForDeployment()); await expect(contract.initialize( owner.address, @@ -337,8 +331,8 @@ describe('ConnectivityTrackerHbbft', () => { await expect( connectivityTracker.connect(caller).reportMissingConnectivity( initialValidators[0].address, - latestBlock.number, - latestBlock.hash + latestBlock!.number, + latestBlock!.hash! ) ).to.be.revertedWithCustomError(connectivityTracker, "OnlyValidator"); }); @@ -350,8 +344,8 @@ describe('ConnectivityTrackerHbbft', () => { await expect( connectivityTracker.connect(initialValidators[0]).reportMissingConnectivity( initialValidators[1].address, - latestBlock.number + 5, - latestBlock.hash + latestBlock!.number + 5, + latestBlock!.hash! ) ).to.be.revertedWithCustomError(connectivityTracker, "InvalidBlock"); }); @@ -363,8 +357,8 @@ describe('ConnectivityTrackerHbbft', () => { await expect( connectivityTracker.connect(initialValidators[0]).reportMissingConnectivity( initialValidators[1].address, - latestBlock.number, - keccak256(ethers.utils.toUtf8Bytes(latestBlock.hash)) + latestBlock!.number, + ethers.keccak256(ethers.toUtf8Bytes(latestBlock!.hash!)) ) ).to.be.revertedWithCustomError(connectivityTracker, "InvalidBlock"); }); @@ -372,14 +366,14 @@ describe('ConnectivityTrackerHbbft', () => { it("should revert too early report", async () => { const { connectivityTracker, validatorSetHbbft, stakingHbbft } = await helpers.loadFixture(deployContracts); - await setStakingEpochStartTime(validatorSetHbbft.address, stakingHbbft); + await setStakingEpochStartTime(await validatorSetHbbft.getAddress(), stakingHbbft); const latestBlock = await ethers.provider.getBlock("latest"); await expect( connectivityTracker.connect(initialValidators[0]).reportMissingConnectivity( initialValidators[1].address, - latestBlock.number, - latestBlock.hash + latestBlock!.number, + latestBlock!.hash! ) ).to.be.revertedWithCustomError(connectivityTracker, "ReportTooEarly"); }); @@ -389,21 +383,21 @@ describe('ConnectivityTrackerHbbft', () => { const reporter = initialValidators[0]; const validator = initialValidators[1]; - await setStakingEpochStartTime(validatorSetHbbft.address, stakingHbbft); + await setStakingEpochStartTime(await validatorSetHbbft.getAddress(), stakingHbbft); await helpers.mine(minReportAgeBlocks + 1); const latestBlock = await ethers.provider.getBlock("latest"); expect(await connectivityTracker.connect(reporter).reportMissingConnectivity( validator.address, - latestBlock.number, - latestBlock.hash + latestBlock!.number, + latestBlock!.hash! )); await expect(connectivityTracker.connect(reporter).reportMissingConnectivity( validator.address, - latestBlock.number, - latestBlock.hash + latestBlock!.number, + latestBlock!.hash! )).to.be.revertedWithCustomError(connectivityTracker, "AlreadyReported") .withArgs(reporter.address, validator.address); }); @@ -417,14 +411,14 @@ describe('ConnectivityTrackerHbbft', () => { expect(await connectivityTracker.connect(reporter).reportMissingConnectivity( validator.address, - latestBlock.number, - latestBlock.hash + latestBlock!.number, + latestBlock!.hash! )); await expect(connectivityTracker.connect(validator).reportMissingConnectivity( reporter.address, - latestBlock.number, - latestBlock.hash + latestBlock!.number, + latestBlock!.hash! )).to.be.revertedWithCustomError(connectivityTracker, "CannotReportByFlaggedValidator") .withArgs(validator.address); }); @@ -439,14 +433,14 @@ describe('ConnectivityTrackerHbbft', () => { await expect( connectivityTracker.connect(reporter).reportMissingConnectivity( validator.address, - latestBlock.number, - latestBlock.hash + latestBlock!.number, + latestBlock!.hash! ) ).to.emit(connectivityTracker, "ReportMissingConnectivity") .withArgs( reporter.address, validator.address, - latestBlock.number + latestBlock!.number ); }); @@ -465,13 +459,13 @@ describe('ConnectivityTrackerHbbft', () => { expect(await connectivityTracker.connect(initialValidators[0]).reportMissingConnectivity( validator.address, - latestBlock.number, - latestBlock.hash + latestBlock!.number, + latestBlock!.hash! )); expect(await connectivityTracker.getFlaggedValidators()).to.include(validator.address); expect(await connectivityTracker.getValidatorConnectivityScore(currentEpoch, validator.address)) - .to.equal(previousScore.add(1)); + .to.equal(previousScore + 1n); }); it("should increase validator score with each report", async () => { @@ -486,13 +480,13 @@ describe('ConnectivityTrackerHbbft', () => { for (let i = 1; i < initialValidators.length; ++i) { expect(await connectivityTracker.connect(initialValidators[i]).reportMissingConnectivity( validator.address, - latestBlock.number, - latestBlock.hash + latestBlock!.number, + latestBlock!.hash! )); expect( await connectivityTracker.getValidatorConnectivityScore(epoch, validator.address) - ).to.equal(initialScore.add(i)) + ).to.equal(initialScore + BigInt(i)) } expect(await connectivityTracker.getValidatorConnectivityScore(epoch, validator.address)) @@ -517,8 +511,8 @@ describe('ConnectivityTrackerHbbft', () => { for (let j = 0; j < badValidators.length - 1; ++j) { expect(await connectivityTracker.connect(goodValidators[i]).reportMissingConnectivity( badValidators[j].address, - latestBlock.number, - latestBlock.hash + latestBlock!.number, + latestBlock!.hash! )); } } @@ -528,8 +522,8 @@ describe('ConnectivityTrackerHbbft', () => { const lastValidatorToReport = goodValidators[goodValidators.length - 1]; await expect(connectivityTracker.connect(lastValidatorToReport).reportMissingConnectivity( badValidators[badValidators.length - 1].address, - latestBlock.number, - latestBlock.hash + latestBlock!.number, + latestBlock!.hash! )).to.emit(connectivityTracker, "NotifyEarlyEpochEnd") .withArgs(epoch, lastBlock + 1); @@ -547,8 +541,8 @@ describe('ConnectivityTrackerHbbft', () => { await expect( connectivityTracker.connect(caller).reportReconnect( initialValidators[0].address, - latestBlock.number, - latestBlock.hash + latestBlock!.number, + latestBlock!.hash! ) ).to.be.revertedWithCustomError(connectivityTracker, "OnlyValidator"); }); @@ -561,8 +555,8 @@ describe('ConnectivityTrackerHbbft', () => { await expect( connectivityTracker.connect(initialValidators[0]).reportReconnect( initialValidators[1].address, - latestBlock.number + 5, - latestBlock.hash + latestBlock!.number + 5, + latestBlock!.hash! ) ).to.be.revertedWithCustomError(connectivityTracker, "InvalidBlock"); }); @@ -575,8 +569,8 @@ describe('ConnectivityTrackerHbbft', () => { await expect( connectivityTracker.connect(initialValidators[0]).reportReconnect( initialValidators[1].address, - latestBlock.number, - keccak256(ethers.utils.toUtf8Bytes(latestBlock.hash)) + latestBlock!.number, + ethers.keccak256(ethers.toUtf8Bytes(latestBlock!.hash!)) ) ).to.be.revertedWithCustomError(connectivityTracker, "InvalidBlock"); }); @@ -584,14 +578,14 @@ describe('ConnectivityTrackerHbbft', () => { it("should revert too early report", async () => { const { connectivityTracker, validatorSetHbbft, stakingHbbft } = await helpers.loadFixture(deployContracts); - await setStakingEpochStartTime(validatorSetHbbft.address, stakingHbbft); + await setStakingEpochStartTime(await validatorSetHbbft.getAddress(), stakingHbbft); const latestBlock = await ethers.provider.getBlock("latest"); await expect( connectivityTracker.connect(initialValidators[0]).reportReconnect( initialValidators[1].address, - latestBlock.number, - latestBlock.hash + latestBlock!.number, + latestBlock!.hash! ) ).to.be.revertedWithCustomError(connectivityTracker, "ReportTooEarly"); }); @@ -605,8 +599,8 @@ describe('ConnectivityTrackerHbbft', () => { await expect( connectivityTracker.connect(reporter).reportReconnect( validator.address, - latestBlock.number, - latestBlock.hash + latestBlock!.number, + latestBlock!.hash! ) ).to.be.revertedWithCustomError(connectivityTracker, "UnknownReconnectReporter") .withArgs(reporter.address, validator.address); @@ -619,21 +613,21 @@ describe('ConnectivityTrackerHbbft', () => { const reporter = initialValidators[0]; const validator = initialValidators[1]; - await setStakingEpochStartTime(validatorSetHbbft.address, stakingHbbft); + await setStakingEpochStartTime(await validatorSetHbbft.getAddress(), stakingHbbft); await helpers.mine(minReportAgeBlocks + 1); let latestBlock = await ethers.provider.getBlock("latest"); expect(await connectivityTracker.connect(reporter).reportMissingConnectivity( validator.address, - latestBlock.number, - latestBlock.hash + latestBlock!.number, + latestBlock!.hash! )); await expect(connectivityTracker.connect(validator).reportReconnect( validator.address, - latestBlock.number, - latestBlock.hash + latestBlock!.number, + latestBlock!.hash! )).to.be.revertedWithCustomError(connectivityTracker, "CannotReportByFlaggedValidator") .withArgs(validator.address); }); @@ -643,29 +637,29 @@ describe('ConnectivityTrackerHbbft', () => { const reporter = initialValidators[0]; const validator = initialValidators[1]; - await setStakingEpochStartTime(validatorSetHbbft.address, stakingHbbft); + await setStakingEpochStartTime(await validatorSetHbbft.getAddress(), stakingHbbft); await helpers.mine(minReportAgeBlocks + 1); let latestBlock = await ethers.provider.getBlock("latest"); expect(await connectivityTracker.connect(reporter).reportMissingConnectivity( validator.address, - latestBlock.number, - latestBlock.hash + latestBlock!.number, + latestBlock!.hash! )); latestBlock = await ethers.provider.getBlock("latest"); await expect( connectivityTracker.connect(reporter).reportReconnect( validator.address, - latestBlock.number, - latestBlock.hash + latestBlock!.number, + latestBlock!.hash! ) ).to.be.emit(connectivityTracker, "ReportReconnect") .withArgs( reporter.address, validator.address, - latestBlock.number + latestBlock!.number ); }); @@ -677,8 +671,8 @@ describe('ConnectivityTrackerHbbft', () => { expect(await connectivityTracker.connect(initialValidators[0]).reportMissingConnectivity( validator.address, - latestBlock.number, - latestBlock.hash + latestBlock!.number, + latestBlock!.hash! )); expect(await connectivityTracker.getFlaggedValidators()).to.include(validator.address); @@ -686,8 +680,8 @@ describe('ConnectivityTrackerHbbft', () => { expect(await connectivityTracker.connect(caller).reportReconnect( validator.address, - latestBlock.number, - latestBlock.hash + latestBlock!.number, + latestBlock!.hash! )); expect(await connectivityTracker.getFlaggedValidators()).to.not.include(validator.address); @@ -701,8 +695,8 @@ describe('ConnectivityTrackerHbbft', () => { for (const reporter of [initialValidators[0], initialValidators[1]]) { expect(await connectivityTracker.connect(reporter).reportMissingConnectivity( validator.address, - latestBlock.number, - latestBlock.hash + latestBlock!.number, + latestBlock!.hash! )); } @@ -712,13 +706,13 @@ describe('ConnectivityTrackerHbbft', () => { expect(await connectivityTracker.connect(initialValidators[0]).reportReconnect( validator.address, - latestBlock.number, - latestBlock.hash + latestBlock!.number, + latestBlock!.hash! )); const currentScore = await connectivityTracker.getValidatorConnectivityScore(epoch, validator.address); - expect(currentScore).to.equal(previousScore.sub(1)); + expect(currentScore).to.equal(previousScore - 1n); }); }); }); diff --git a/test/KeyGenHistory.ts b/test/KeyGenHistory.ts index 222a37c3..7cc66449 100644 --- a/test/KeyGenHistory.ts +++ b/test/KeyGenHistory.ts @@ -1,5 +1,6 @@ import { ethers, upgrades } from "hardhat"; - +import { expect } from "chai"; +import { HardhatEthersSigner } from "@nomicfoundation/hardhat-ethers/signers"; import * as helpers from "@nomicfoundation/hardhat-network-helpers"; import { @@ -9,224 +10,373 @@ import { StakingHbbftMock, KeyGenHistory, TxPermissionHbbft, - CertifierHbbft, - ConnectivityTrackerHbbftMock + CertifierHbbft } from "../src/types"; -import { BigNumber } from "ethers"; -import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers"; + +import { getTestPartNAcks } from './testhelpers/data'; import { Permission } from "./testhelpers/Permission"; -import { expect } from "chai"; -const testdata = require('./testhelpers/data'); +const logOutput = false; -require('chai') - .use(require('chai-as-promised')) - .use(require('chai-bn')(BigNumber)) - .should(); +const candidateMinStake = ethers.parseEther('2'); +const delegatorMinStake = ethers.parseEther('1'); +const maxStake = ethers.parseEther('100000'); -const logOutput = false; +// one epoch in 1000 seconds. +const stakingEpochDuration = 1000n; + +// the transition time window is 100 seconds. +const stakingTransitionwindowLength = 100n; +const stakingWithdrawDisallowPeriod = 100n; -//smart contracts -let blockRewardHbbft: BlockRewardHbbftMock; -let randomHbbft: RandomHbbft; -let validatorSetHbbft: ValidatorSetHbbftMock; -let stakingHbbft: StakingHbbftMock; -let keyGenHistory: KeyGenHistory; -let txPermission: TxPermissionHbbft; -let certifier: CertifierHbbft; -let connectivityTracker: ConnectivityTrackerHbbftMock; - -let keyGenHistoryPermission: Permission; - -//addresses -let owner: SignerWithAddress; -let accounts: SignerWithAddress[]; -let accountAddresses: string[]; -let miningAddresses: string[]; -let stakingAddresses: string[]; -let initializingMiningAddresses: string[]; -let initializingStakingAddresses: string[]; - -//consts -let candidateMinStake = BigNumber.from(ethers.utils.parseEther('2')); -let delegatorMinStake = BigNumber.from(ethers.utils.parseEther('1')); -let maxStake = BigNumber.from(ethers.utils.parseEther('100000')); +const validatorInactivityThreshold = 365n * 86400n // 1 year + +const SystemAccountAddress = '0xffffFFFfFFffffffffffffffFfFFFfffFFFfFFfE'; describe('KeyGenHistory', () => { - describe('Deployment', async () => { - //this info does not match the mininAccounts, but thats not a problem for this tests. - let publicKeys = [ - '0x1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1', - '0x1BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB1', - '0x2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA2', - '0x2BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB2', - '0x3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3', - '0x3BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB3' - ]; + let owner: HardhatEthersSigner; + let accounts: HardhatEthersSigner[]; + let accountAddresses: string[]; + let miningAddresses: string[]; + let stakingAddresses: string[]; + let initializingMiningAddresses: string[]; + let initializingStakingAddresses: string[]; + let stubAddress: string; + + let keyGenHistory: KeyGenHistory; + let txPermission: TxPermissionHbbft; + let validatorSetHbbft: ValidatorSetHbbftMock; + let stakingHbbft: StakingHbbftMock; + let blockRewardHbbft: BlockRewardHbbftMock; + let randomHbbft: RandomHbbft; + let certifier: CertifierHbbft; + let keyGenHistoryPermission: Permission; + + //this info does not match the mininAccounts, but thats not a problem for this tests. + let publicKeys = [ + '0x1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1', + '0x1BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB1', + '0x2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA2', + '0x2BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB2', + '0x3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3', + '0x3BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB3' + ]; + + + let initialValidatorsIpAddresses = [ + '0x10100000000000000000000000000000', + '0x20200000000000000000000000000000', + '0x30300000000000000000000000000000']; + + const { parts, acks } = getTestPartNAcks(); + + async function impersonateSystemAcc() { + await helpers.impersonateAccount(SystemAccountAddress); + + await owner.sendTransaction({ + to: SystemAccountAddress, + value: ethers.parseEther('10'), + }); + return await ethers.getSigner(SystemAccountAddress); + } - let initialValidatorsIpAddresses = [ - '0x10100000000000000000000000000000', - '0x20200000000000000000000000000000', - '0x30300000000000000000000000000000']; + async function printValidatorState(info: string) { + if (!logOutput) { + return; + } + + const validators = await validatorSetHbbft.getValidators(); + const pendingValidators = await validatorSetHbbft.getPendingValidators(); + + //Note: toBeElected are Pool (staking) addresses, and not Mining adresses. + // all other adresses are mining adresses. + const toBeElected = await stakingHbbft.getPoolsToBeElected(); + const pools = await stakingHbbft.getPools(); + const poolsInactive = await stakingHbbft.getPoolsInactive(); + const epoch = await stakingHbbft.stakingEpoch(); + + console.log(info + ' epoch : ', epoch); + console.log(info + ' pending :', pendingValidators); + console.log(info + ' validators:', validators); + console.log(info + ' pools: ', pools); + console.log(info + ' inactive pools: ', poolsInactive); + console.log(info + ' pools toBeElected: ', toBeElected); + } - const { parts, acks } = testdata.getTestPartNAcks(); + // checks if a validator is able to write parts for free + // and executes it. + // NOTE: It does not really send the transaction with 0 gas price, + // because that would only work if the network nodes would already + // run on the test contracts deployed here. + async function writePart(upcommingEpochNumber: string, round: string, parts: any, from: string) { + await keyGenHistoryPermission.callFunction('writePart', from, [upcommingEpochNumber, round, parts]); + } - // one epoch in 1000 seconds. - const stakingEpochDuration = BigNumber.from(1000); + async function writeAcks(upcommingEpochNumber: string, round: string, parts: any, from: string) { + await keyGenHistoryPermission.callFunction('writeAcks', from, [upcommingEpochNumber, round, parts]); + } - // the transition time window is 100 seconds. - const stakingTransitionwindowLength = BigNumber.from(100); + async function announceAvailability(pool: string) { + const blockNumber = await ethers.provider.getBlockNumber() + const block = await ethers.provider.getBlock(blockNumber); + const asEncoded = validatorSetHbbft.interface.encodeFunctionData( + "announceAvailability", + [blockNumber, block!.hash!] + ); + if (logOutput) { + console.log('calling: announceAvailability'); + console.log('pool: ', pool) + console.log('ecodedCall: ', asEncoded); + } + + const allowedTxType = await txPermission.allowedTxTypes(pool, await validatorSetHbbft.getAddress(), '0x0' /* value */, '0x0' /* gas price */, asEncoded); + + //console.log(allowedTxType.typesMask.toString()); + // don't ask to cache this result. + expect(allowedTxType.cache).to.be.false; + + /// 0x01 - basic transaction (e.g. ether transferring to user wallet); + /// 0x02 - contract call; + /// 0x04 - contract creation; + /// 0x08 - private transaction. + + expect(allowedTxType.typesMask).to.be.equal(2n, 'Transaction should be allowed according to TxPermission Contract.'); + + // we know now, that this call is allowed. + // so we can execute it. + await (await ethers.getSigner(pool)).sendTransaction({ to: await validatorSetHbbft.getAddress(), data: asEncoded }); + } - const stakingWithdrawDisallowPeriod = BigNumber.from(100); + async function callReward(isEpochEndBlock: boolean) { + // console.log('getting validators...'); + // note: this call used to crash because of a internal problem with a previous call of evm_mine and evm_increase_time https://github.com/DMDcoin/hbbft-posdao-contracts/issues/13 + // console.log('got validators:', validators); + const systemSigner = await impersonateSystemAcc(); - const validatorInactivityThreshold = 365 * 86400 // 1 year + await blockRewardHbbft.connect(systemSigner).reward(isEpochEndBlock); - it('Deploy Contracts', async () => { - [owner, ...accounts] = await ethers.getSigners(); - const stubAddress = owner.address; + await helpers.stopImpersonatingAccount(SystemAccountAddress); + } - accountAddresses = accounts.map(item => item.address); + // time travels forward to the beginning of the next transition, + // and simulate a block mining (calling reward()) + async function timeTravelToTransition() { + let currentTimestamp = await helpers.time.latest(); + let startTimeOfNextPhaseTransition = await stakingHbbft.startTimeOfNextPhaseTransition(); - miningAddresses = accountAddresses.slice(11, 20); - stakingAddresses = accountAddresses.slice(21, 30); + if (logOutput) { + console.log(`timetraveling from ${currentTimestamp} to ${startTimeOfNextPhaseTransition}`); + } - initializingMiningAddresses = miningAddresses.slice(0, 3); - initializingStakingAddresses = stakingAddresses.slice(0, 3); + await helpers.time.increaseTo(startTimeOfNextPhaseTransition); + await callReward(false); + } - if (logOutput) { - console.log('initial Mining Addresses', initializingMiningAddresses); - console.log('initial Staking Addresses', initializingStakingAddresses); - } + async function timeTravelToEndEpoch() { + // todo: mimic the behavor of the nodes here: + // if The Validators managed to write the correct number + // of Acks and Parts, we are happy and set a "true" + // if not, we send a "false" + // note: the Nodes they DO check if the ACKS and PARTS + // make it possible to generate a treshold key here, + // but within the tests, we just mimic this behavior. + const callResult = await keyGenHistory.getNumberOfKeyFragmentsWritten(); - const ConnectivityTrackerFactory = await ethers.getContractFactory("ConnectivityTrackerHbbftMock"); - connectivityTracker = await upgrades.deployProxy(ConnectivityTrackerFactory) as ConnectivityTrackerHbbftMock; - await connectivityTracker.deployed(); + const numberOfParts = callResult[0]; + const numberOfAcks = callResult[1]; - // Deploy ValidatorSet contract - const ValidatorSetFactory = await ethers.getContractFactory("ValidatorSetHbbftMock"); - validatorSetHbbft = await upgrades.deployProxy( - ValidatorSetFactory, - [ - owner.address, - stubAddress, // _blockRewardContract - stubAddress, // _randomContract - stubAddress, // _stakingContract - stubAddress, // _keyGenHistoryContract - validatorInactivityThreshold, // _validatorInactivityThreshold - initializingMiningAddresses, // _initialMiningAddresses - initializingStakingAddresses, // _initialStakingAddresses - ], - { initializer: 'initialize' } - ) as ValidatorSetHbbftMock; + const pendingValidators = await validatorSetHbbft.getPendingValidators(); + const numberOfPendingValidators = BigInt(pendingValidators.length); + let callRewardParameter = (numberOfParts === numberOfPendingValidators && numberOfAcks === numberOfPendingValidators); - // Deploy BlockRewardHbbft contract - const BlockRewardHbbftFactory = await ethers.getContractFactory("BlockRewardHbbftMock"); - blockRewardHbbft = await upgrades.deployProxy( - BlockRewardHbbftFactory, - [ - owner.address, - validatorSetHbbft.address, - connectivityTracker.address - ], - { initializer: 'initialize' } - ) as BlockRewardHbbftMock; + const endTimeOfCurrentEpoch = await stakingHbbft.stakingFixedEpochEndTime(); - // Deploy BlockRewardHbbft contract - const RandomHbbftFactory = await ethers.getContractFactory("RandomHbbft"); - randomHbbft = await upgrades.deployProxy( - RandomHbbftFactory, - [ - owner.address, - validatorSetHbbft.address - ], - { initializer: 'initialize' } - ) as RandomHbbft; - - const stakingParams = { - _validatorSetContract: validatorSetHbbft.address, - _initialStakingAddresses: initializingStakingAddresses, - _delegatorMinStake: delegatorMinStake, - _candidateMinStake: candidateMinStake, - _maxStake: maxStake, - _stakingFixedEpochDuration: stakingEpochDuration, - _stakingTransitionTimeframeLength: stakingTransitionwindowLength, - _stakingWithdrawDisallowPeriod: stakingWithdrawDisallowPeriod - }; - - // Deploy BlockRewardHbbft contract - const StakingHbbftFactory = await ethers.getContractFactory("StakingHbbftMock"); - stakingHbbft = await upgrades.deployProxy( - StakingHbbftFactory, - [ - owner.address, - stakingParams, - publicKeys, - initialValidatorsIpAddresses - ], - { initializer: 'initialize' } - ) as StakingHbbftMock; + await helpers.time.increaseTo(endTimeOfCurrentEpoch); + await callReward(callRewardParameter); + } - const KeyGenFactory = await ethers.getContractFactory("KeyGenHistory"); - keyGenHistory = await upgrades.deployProxy( - KeyGenFactory, - [ - owner.address, - validatorSetHbbft.address, - initializingMiningAddresses, - parts, - acks - ], - { initializer: 'initialize' } - ) as KeyGenHistory; + before(async function () { + [owner, ...accounts] = await ethers.getSigners(); + stubAddress = owner.address; - // Deploy Certifier contract - const CertifierFactory = await ethers.getContractFactory("CertifierHbbft"); - certifier = await upgrades.deployProxy( - CertifierFactory, - [ - [owner.address], - validatorSetHbbft.address, - owner.address - ], - { initializer: 'initialize' } - ) as CertifierHbbft; + accountAddresses = accounts.map(item => item.address); - // Deploy TxPermission contract - const TxPermissionFactory = await ethers.getContractFactory("TxPermissionHbbft"); - txPermission = await upgrades.deployProxy( - TxPermissionFactory, - [ - [owner.address], - certifier.address, - validatorSetHbbft.address, - keyGenHistory.address, - stubAddress, - owner.address - ], - { initializer: 'initialize' } - ) as TxPermissionHbbft; + miningAddresses = accountAddresses.slice(11, 20); + stakingAddresses = accountAddresses.slice(21, 30); - keyGenHistoryPermission = new Permission(txPermission, keyGenHistory, logOutput); + initializingMiningAddresses = miningAddresses.slice(0, 3); + initializingStakingAddresses = stakingAddresses.slice(0, 3); - await validatorSetHbbft.setBlockRewardContract(blockRewardHbbft.address); - await validatorSetHbbft.setRandomContract(randomHbbft.address); - await validatorSetHbbft.setStakingContract(stakingHbbft.address); - await validatorSetHbbft.setKeyGenHistoryContract(keyGenHistory.address); + if (logOutput) { + console.log('initial Mining Addresses', initializingMiningAddresses); + console.log('initial Staking Addresses', initializingStakingAddresses); + } - const validators = await validatorSetHbbft.getValidators(); + const ConnectivityTrackerFactory = await ethers.getContractFactory("ConnectivityTrackerHbbftMock"); + const connectivityTracker = await ConnectivityTrackerFactory.deploy(); + await connectivityTracker.waitForDeployment(); - validators.should.be.deep.equal(initializingMiningAddresses); - }); + // Deploy ValidatorSet contract + const ValidatorSetFactory = await ethers.getContractFactory("ValidatorSetHbbftMock"); + const validatorSetHbbftProxy = await upgrades.deployProxy( + ValidatorSetFactory, + [ + owner.address, + stubAddress, // _blockRewardContract + stubAddress, // _randomContract + stubAddress, // _stakingContract + stubAddress, // _keyGenHistoryContract + validatorInactivityThreshold, // _validatorInactivityThreshold + initializingMiningAddresses, // _initialMiningAddresses + initializingStakingAddresses, // _initialStakingAddresses + ], + { initializer: 'initialize' } + ); + + await validatorSetHbbftProxy.waitForDeployment(); + + const BlockRewardHbbftFactory = await ethers.getContractFactory("BlockRewardHbbftMock"); + const blockRewardHbbftProxy = await upgrades.deployProxy( + BlockRewardHbbftFactory, + [ + owner.address, + await validatorSetHbbftProxy.getAddress(), + await connectivityTracker.getAddress() + ], + { initializer: 'initialize' } + ); + + await blockRewardHbbftProxy.waitForDeployment(); + + const RandomHbbftFactory = await ethers.getContractFactory("RandomHbbft"); + const randomHbbftProxy = await upgrades.deployProxy( + RandomHbbftFactory, + [ + owner.address, + await validatorSetHbbftProxy.getAddress() + ], + { initializer: 'initialize' } + ); + + await randomHbbftProxy.waitForDeployment(); + + const stakingParams = { + _validatorSetContract: await validatorSetHbbftProxy.getAddress(), + _initialStakingAddresses: initializingStakingAddresses, + _delegatorMinStake: delegatorMinStake, + _candidateMinStake: candidateMinStake, + _maxStake: maxStake, + _stakingFixedEpochDuration: stakingEpochDuration, + _stakingTransitionTimeframeLength: stakingTransitionwindowLength, + _stakingWithdrawDisallowPeriod: stakingWithdrawDisallowPeriod + }; + + const StakingHbbftFactory = await ethers.getContractFactory("StakingHbbftMock"); + const stakingHbbftProxy = await upgrades.deployProxy( + StakingHbbftFactory, + [ + owner.address, + stakingParams, + publicKeys, + initialValidatorsIpAddresses + ], + { initializer: 'initialize' } + ); + + await stakingHbbftProxy.waitForDeployment(); + + const KeyGenFactory = await ethers.getContractFactory("KeyGenHistory"); + const keyGenHistoryProxy = await upgrades.deployProxy( + KeyGenFactory, + [ + owner.address, + await validatorSetHbbftProxy.getAddress(), + initializingMiningAddresses, + parts, + acks + ], + { initializer: 'initialize' } + ); + + await keyGenHistoryProxy.waitForDeployment(); + + const CertifierFactory = await ethers.getContractFactory("CertifierHbbft"); + const certifierProxy = await upgrades.deployProxy( + CertifierFactory, + [ + [owner.address], + await validatorSetHbbftProxy.getAddress(), + owner.address + ], + { initializer: 'initialize' } + ); + + await certifierProxy.waitForDeployment() + + const TxPermissionFactory = await ethers.getContractFactory("TxPermissionHbbft"); + const txPermissionProxy = await upgrades.deployProxy( + TxPermissionFactory, + [ + [owner.address], + await certifierProxy.getAddress(), + await validatorSetHbbftProxy.getAddress(), + await keyGenHistoryProxy.getAddress(), + stubAddress, + owner.address + ], + { initializer: 'initialize' } + ); + + await txPermissionProxy.waitForDeployment(); + + validatorSetHbbft = ValidatorSetFactory.attach( + await validatorSetHbbftProxy.getAddress() + ) as ValidatorSetHbbftMock; + + blockRewardHbbft = BlockRewardHbbftFactory.attach( + await blockRewardHbbftProxy.getAddress() + ) as BlockRewardHbbftMock; + + randomHbbft = RandomHbbftFactory.attach(await randomHbbftProxy.getAddress()) as RandomHbbft; + + stakingHbbft = StakingHbbftFactory.attach( + await stakingHbbftProxy.getAddress() + ) as StakingHbbftMock; + + keyGenHistory = KeyGenFactory.attach( + await keyGenHistoryProxy.getAddress() + ) as KeyGenHistory; + + certifier = CertifierFactory.attach( + await certifierProxy.getAddress() + ) as CertifierHbbft; + + txPermission = TxPermissionFactory.attach( + await txPermissionProxy.getAddress() + ) as TxPermissionHbbft; + + keyGenHistoryPermission = new Permission(txPermission, keyGenHistory, logOutput); + + await validatorSetHbbft.setBlockRewardContract(await blockRewardHbbft.getAddress()); + await validatorSetHbbft.setRandomContract(await randomHbbft.getAddress()); + await validatorSetHbbft.setStakingContract(await stakingHbbft.getAddress()); + await validatorSetHbbft.setKeyGenHistoryContract(await keyGenHistory.getAddress()); + + const validators = await validatorSetHbbft.getValidators(); + + expect(validators).to.be.deep.equal(initializingMiningAddresses); + }); + describe('Deployment', async () => { it('should revert initialization with owner = address(0)', async () => { const KeyGenFactory = await ethers.getContractFactory("KeyGenHistory"); await expect(upgrades.deployProxy( KeyGenFactory, [ - ethers.constants.AddressZero, - validatorSetHbbft.address, + ethers.ZeroAddress, + stubAddress, initializingMiningAddresses, parts, acks @@ -241,7 +391,7 @@ describe('KeyGenHistory', () => { KeyGenFactory, [ owner.address, - ethers.constants.AddressZero, + ethers.ZeroAddress, initializingMiningAddresses, parts, acks @@ -256,7 +406,7 @@ describe('KeyGenHistory', () => { KeyGenFactory, [ owner.address, - validatorSetHbbft.address, + stubAddress, [], parts, acks @@ -272,7 +422,7 @@ describe('KeyGenHistory', () => { KeyGenFactory, [ owner.address, - validatorSetHbbft.address, + stubAddress, initializingMiningAddresses, [], acks @@ -288,7 +438,7 @@ describe('KeyGenHistory', () => { KeyGenFactory, [ owner.address, - validatorSetHbbft.address, + stubAddress, initializingMiningAddresses, parts, [] @@ -303,7 +453,7 @@ describe('KeyGenHistory', () => { KeyGenFactory, [ owner.address, - validatorSetHbbft.address, + stubAddress, initializingMiningAddresses, parts, acks @@ -311,47 +461,38 @@ describe('KeyGenHistory', () => { { initializer: 'initialize' } ); - expect(await contract.deployed()); + await contract.waitForDeployment(); await expect(contract.initialize( owner.address, - validatorSetHbbft.address, + stubAddress, initializingMiningAddresses, parts, acks )).to.be.revertedWith('Initializable: contract is already initialized'); }); - it('should restrict calling clearPrevKeyGenState to ValidatorSet contract', async function() { + it('should restrict calling clearPrevKeyGenState to ValidatorSet contract', async function () { const caller = accounts[5]; - await expect(keyGenHistory.connect(caller).clearPrevKeyGenState([])) .to.be.revertedWith("Must by executed by validatorSetContract"); }); - it('should restrict calling notifyNewEpoch to ValidatorSet contract', async function() { + it('should restrict calling notifyNewEpoch to ValidatorSet contract', async function () { const caller = accounts[5]; await expect(keyGenHistory.connect(caller).notifyNewEpoch()) .to.be.revertedWith("Must by executed by validatorSetContract"); }); - it('should restrict calling notifyKeyGenFailed to ValidatorSet contract', async function() { + it('should restrict calling notifyKeyGenFailed to ValidatorSet contract', async function () { const caller = accounts[5]; await expect(keyGenHistory.connect(caller).notifyKeyGenFailed()) .to.be.revertedWith("Must by executed by validatorSetContract"); }); - it('failed KeyGeneration, availability.', async () => { - - // console.log('start failed key gen'); - // await timeTravelToTransition(); - // console.log('transition OK'); - // await timeTravelToEndEpoch(); - // console.log('end epoch'); - const stakingBanned = await validatorSetHbbft.bannedUntil(stakingAddresses[0]); const miningBanned = await validatorSetHbbft.bannedUntil(miningAddresses[0]); const currentTS = await helpers.time.latest(); @@ -366,16 +507,19 @@ describe('KeyGenHistory', () => { console.log('newPoolMiningAddress:', newPoolMiningAddress); } - false.should.be.equal(await stakingHbbft.isPoolActive(newPoolStakingAddress)); + expect(await stakingHbbft.isPoolActive(newPoolStakingAddress)).to.be.false; - await stakingHbbft.connect(await ethers.getSigner(newPoolStakingAddress)).addPool(newPoolMiningAddress, '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - '0x00000000000000000000000000000000', { value: candidateMinStake }); + await stakingHbbft.connect(await ethers.getSigner(newPoolStakingAddress)).addPool( + newPoolMiningAddress, + ethers.zeroPadBytes("0x00", 64), + ethers.zeroPadBytes("0x00", 16), + { value: candidateMinStake } + ); //await stakingHbbft.addPool(miningAddresses[5], '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', //'0x00000000000000000000000000000000', {from: stakingAddresses[5], value: candidateMinStake}); - const poolIsActiveNow = await stakingHbbft.isPoolActive(newPoolStakingAddress); - poolIsActiveNow.should.be.equal(true); + expect(await stakingHbbft.isPoolActive(newPoolStakingAddress)).to.be.true; //await stakingHbbft.stake(stakingAddresses[0], {from: stakingAddresses[0], value: candidateMinStake}); //await stakingHbbft.stake(stakingAddresses[1], {from: stakingAddresses[1], value: candidateMinStake}); @@ -397,8 +541,8 @@ describe('KeyGenHistory', () => { await printValidatorState('after failure:'); - (await stakingHbbft.getPoolsToBeElected()).should.be.deep.equal([]); - (await stakingHbbft.getPoolsInactive()).should.be.deep.equal([newPoolStakingAddress]); + expect(await stakingHbbft.getPoolsToBeElected()).to.be.empty; + expect(await stakingHbbft.getPoolsInactive()).to.be.deep.equal([newPoolStakingAddress]); // pending validators still should not have changed, since we dit not call end block. // WIP: this test currently failes. one of the initial validators takes over the list of pending validators @@ -410,13 +554,11 @@ describe('KeyGenHistory', () => { // announcing availability. // this should place us back on the list of active and available pools. await announceAvailability(newPoolMiningAddress); - await printValidatorState('after announceAvailability:'); // pool is available again! - (await stakingHbbft.getPoolsToBeElected()).should.be.deep.equal([newPoolStakingAddress]); - (await stakingHbbft.getPoolsInactive()).should.be.deep.equal([]); - + expect(await stakingHbbft.getPoolsToBeElected()).to.be.deep.equal([newPoolStakingAddress]); + expect(await stakingHbbft.getPoolsInactive()).to.be.empty; // the original validators took over. // lets travel again to the end of the epoch, to switch into the next epoch @@ -428,9 +570,7 @@ describe('KeyGenHistory', () => { // since there was never another electable candidate, the system should still // tread the one and only pending validator still as pending validator. - pendingValidators.should.be.deep.equal([newPoolMiningAddress]); - - + expect(pendingValidators).to.be.deep.equal([newPoolMiningAddress]); // since the initial round was failed, we are in the second round. const currentRoundCounter = '2'; @@ -438,22 +578,16 @@ describe('KeyGenHistory', () => { await writePart('1', currentRoundCounter, parts[0], pendingValidators[0]); //confirm that part was written. - const partFromBc = await keyGenHistory.getPart(pendingValidators[0]); - partFromBc.should.be.equal('0x' + parts[0].toString('hex')); //TODO! what was it supposed to be? , partFromBc, 'parts read from the blockchain require to be equal to the written data.' + //TODO! what was it supposed to be? , partFromBc, 'parts read from the blockchain require to be equal to the written data.' + expect(await keyGenHistory.getPart(pendingValidators[0])).to.be.equal(ethers.hexlify(parts[0])); await writeAcks('1', currentRoundCounter, acks[0], pendingValidators[0]); - await timeTravelToEndEpoch(); - let epoch = (await stakingHbbft.stakingEpoch()); - await printValidatorState('epoch1 start:'); - - epoch.should.be.equal(BigNumber.from('1')); - + expect(await stakingHbbft.stakingEpoch()).to.equal(1n); await timeTravelToTransition(); - await printValidatorState('epoch1 phase2:'); // // now write the ACK and the PART: @@ -467,13 +601,11 @@ describe('KeyGenHistory', () => { // now everything is fine, we can do the transition after failing // the first one. - epoch = (await stakingHbbft.stakingEpoch()); await printValidatorState('epoch2 start:'); - epoch.should.be.equal(BigNumber.from('2')); + expect(await stakingHbbft.stakingEpoch()).to.be.equal(2n); // // now the new node should be a validator. - (await validatorSetHbbft.getValidators()).should.be.deep.equal([newPoolMiningAddress]); - + expect(await validatorSetHbbft.getValidators()).to.be.deep.equal([newPoolMiningAddress]); }); it('1/2 KeyGeneration - PART Failure', async () => { @@ -486,20 +618,22 @@ describe('KeyGenHistory', () => { // even if the failing party manages to announce availability // within the extra-key-gen round he wont be picked up this round. - const poolStakingAddress1 = stakingAddresses[4]; const poolMiningAddress1 = miningAddresses[4]; // address1 is already picked up and a validator. // we double check if he is also marked for being available: - let validatorAvailableSince = await validatorSetHbbft.validatorAvailableSince(poolMiningAddress1); - validatorAvailableSince.should.not.be.equal(BigNumber.from('0')); + expect(await validatorSetHbbft.validatorAvailableSince(poolMiningAddress1)).to.be.not.equal(0n); const poolStakingAddress2 = stakingAddresses[5]; const poolMiningAddress2 = miningAddresses[5]; - await stakingHbbft.connect(await ethers.getSigner(poolStakingAddress2)).addPool(poolMiningAddress2, '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - '0x00000000000000000000000000000000', { value: candidateMinStake }); + await stakingHbbft.connect(await ethers.getSigner(poolStakingAddress2)).addPool( + poolMiningAddress2, + ethers.zeroPadBytes("0x00", 64), + ethers.zeroPadBytes("0x00", 16), + { value: candidateMinStake } + ); await printValidatorState('After adding mining address2:'); await timeTravelToTransition(); @@ -509,178 +643,56 @@ describe('KeyGenHistory', () => { // but pending validator 1 misses out to write it's part. await writePart('3', '1', parts[0], poolMiningAddress2); - - await writeAcks('3', '1', acks[0], poolMiningAddress2).should.be.rejected; + await expect(writeAcks('3', '1', acks[0], poolMiningAddress2)).to.be.rejected; if (logOutput) { console.log('numberOfPartsWritten: ', await keyGenHistory.numberOfPartsWritten()); console.log('numberOfAcksWritten: ', await keyGenHistory.numberOfAcksWritten()); } - await timeTravelToEndEpoch(); - await printValidatorState('failedEnd:'); // another TimeTravel to end epoch happened, // we expect that there was NO epoch change. // since Validator 1 failed writing his keys. - let epoch = (await stakingHbbft.stakingEpoch()); - epoch.should.be.equal(BigNumber.from('2')); + expect(await stakingHbbft.stakingEpoch()).to.be.equal(2n); // we expect Validator 1 now to be marked as unavailable, // since he failed to write his key. - validatorAvailableSince = await validatorSetHbbft.validatorAvailableSince(poolMiningAddress1); - validatorAvailableSince.should.be.equal(BigNumber.from('0')); + expect(await validatorSetHbbft.validatorAvailableSince(poolMiningAddress1)).to.be.equal(0n); // and only validator 2 is part of the Set. // validator 2 needs to write his keys again. - const pendingValidators = await validatorSetHbbft.getPendingValidators(); - pendingValidators.should.be.deep.equal([poolMiningAddress2]); - + expect(await validatorSetHbbft.getPendingValidators()).to.be.deep.equal([poolMiningAddress2]); }); + }); - }); // describe describe('Certifier', async () => { it("Owner must be able to certify any user", async () => { await certifier.connect(owner).certify(accounts[35].address); - (await certifier.certified(accounts[35].address)).should.be.equal(true); - (await certifier.certifiedExplicitly(accounts[35].address)).should.be.equal(true); + expect(await certifier.certified(accounts[35].address)).to.be.true; + expect(await certifier.certifiedExplicitly(accounts[35].address)).to.be.true; }); it("Mining addresses with pools should be certified by default", async () => { - (await certifier.certified(miningAddresses[1])).should.be.equal(true); - (await certifier.certifiedExplicitly(miningAddresses[1])).should.be.equal(false); + expect(await certifier.certified(miningAddresses[1])).to.be.true; + expect(await certifier.certifiedExplicitly(miningAddresses[1])).to.be.false; }) it("Should be able to revoke from non-validators", async () => { await certifier.connect(owner).revoke(accounts[35].address); - (await certifier.certified(accounts[35].address)).should.be.equal(false); + expect(await certifier.certified(accounts[35].address)).to.be.false; }); it("Shouldn't be able to revoke from working validators", async () => { await certifier.connect(owner).revoke(miningAddresses[1]); - (await certifier.certified(miningAddresses[1])).should.be.equal(true); + expect(await certifier.certified(miningAddresses[1])).to.be.true; }) it("Shouldn't be able to certify zero address", async () => { - await certifier.connect(owner).certify("0x0000000000000000000000000000000000000000").should.be.rejectedWith("certifier must not be address 0"); + await expect(certifier.connect(owner).certify(ethers.ZeroAddress)) + .to.be.revertedWith("certifier must not be address 0"); }) }) -}); // contract - - -async function printValidatorState(info: string) { - - if (!logOutput) { - return; - } - const validators = await validatorSetHbbft.getValidators(); - const pendingValidators = await validatorSetHbbft.getPendingValidators(); - - //Note: toBeElected are Pool (staking) addresses, and not Mining adresses. - // all other adresses are mining adresses. - const toBeElected = await stakingHbbft.getPoolsToBeElected(); - const pools = await stakingHbbft.getPools(); - const poolsInactive = await stakingHbbft.getPoolsInactive(); - const epoch = await stakingHbbft.stakingEpoch(); - - console.log(info + ' epoch : ', epoch); - console.log(info + ' pending :', pendingValidators); - console.log(info + ' validators:', validators); - console.log(info + ' pools: ', pools); - console.log(info + ' inactive pools: ', poolsInactive); - console.log(info + ' pools toBeElected: ', toBeElected); -} - -// checks if a validator is able to write parts for free -// and executes it. -// NOTE: It does not really send the transaction with 0 gas price, -// because that would only work if the network nodes would already -// run on the test contracts deployed here. -async function writePart(upcommingEpochNumber: string, round: string, parts: any, from: string) { - - await keyGenHistoryPermission.callFunction('writePart', from, [upcommingEpochNumber, round, parts]); -} - -async function writeAcks(upcommingEpochNumber: string, round: string, parts: any, from: string) { - await keyGenHistoryPermission.callFunction('writeAcks', from, [upcommingEpochNumber, round, parts]); -} - - -async function announceAvailability(pool: string) { - - const blockNumber = await ethers.provider.getBlockNumber() - const block = await ethers.provider.getBlock(blockNumber); - const asEncoded = validatorSetHbbft.interface.encodeFunctionData("announceAvailability", [blockNumber, block.hash]); - if (logOutput) { - console.log('calling: announceAvailability'); - console.log('pool: ', pool) - console.log('ecodedCall: ', asEncoded); - } - - const allowedTxType = await txPermission.allowedTxTypes(pool, validatorSetHbbft.address, '0x0' /* value */, '0x0' /* gas price */, asEncoded); - - //console.log(allowedTxType.typesMask.toString()); - // don't ask to cache this result. - allowedTxType.cache.should.be.equal(false); - - /// 0x01 - basic transaction (e.g. ether transferring to user wallet); - /// 0x02 - contract call; - /// 0x04 - contract creation; - /// 0x08 - private transaction. - - allowedTxType.typesMask.should.be.equal(BigNumber.from('2'), 'Transaction should be allowed according to TxPermission Contract.'); - - // we know now, that this call is allowed. - // so we can execute it. - await (await ethers.getSigner(pool)).sendTransaction({ to: validatorSetHbbft.address, data: asEncoded }); - - -} - -async function callReward(isEpochEndBlock: boolean) { - // console.log('getting validators...'); - // note: this call used to crash because of a internal problem with a previous call of evm_mine and evm_increase_time https://github.com/DMDcoin/hbbft-posdao-contracts/issues/13 - // console.log('got validators:', validators); - await blockRewardHbbft.setSystemAddress(owner.address); - await blockRewardHbbft.connect(owner).reward(isEpochEndBlock); - await blockRewardHbbft.setSystemAddress('0xffffFFFfFFffffffffffffffFfFFFfffFFFfFFfE'); -} - -// time travels forward to the beginning of the next transition, -// and simulate a block mining (calling reward()) -async function timeTravelToTransition() { - let currentTimestamp = await helpers.time.latest(); - let startTimeOfNextPhaseTransition = await stakingHbbft.startTimeOfNextPhaseTransition(); - - if (logOutput) { - console.log(`timetraveling from ${currentTimestamp} to ${startTimeOfNextPhaseTransition}`); - } - - await helpers.time.increaseTo(startTimeOfNextPhaseTransition); - await callReward(false); -} - -async function timeTravelToEndEpoch() { - // todo: mimic the behavor of the nodes here: - // if The Validators managed to write the correct number - // of Acks and Parts, we are happy and set a "true" - // if not, we send a "false" - // note: the Nodes they DO check if the ACKS and PARTS - // make it possible to generate a treshold key here, - // but within the tests, we just mimic this behavior. - const callResult = await keyGenHistory.getNumberOfKeyFragmentsWritten(); - - const numberOfParts = callResult['0'].toNumber(); - const numberOfAcks = callResult['1'].toNumber(); - - const pendingValidators = await validatorSetHbbft.getPendingValidators(); - const numberOfPendingValidators = pendingValidators.length; - let callRewardParameter = (numberOfParts === numberOfPendingValidators && numberOfAcks === numberOfPendingValidators); - - const endTimeOfCurrentEpoch = await stakingHbbft.stakingFixedEpochEndTime(); - - await helpers.time.increaseTo(endTimeOfCurrentEpoch); - await callReward(callRewardParameter); -} +}); diff --git a/test/RandomHbbft.ts b/test/RandomHbbft.ts index 8695a96f..f60c1f70 100644 --- a/test/RandomHbbft.ts +++ b/test/RandomHbbft.ts @@ -1,7 +1,6 @@ import { ethers, upgrades } from "hardhat"; -import { BigNumber } from "ethers"; -import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers"; import { expect } from "chai"; +import { HardhatEthersSigner } from "@nomicfoundation/hardhat-ethers/signers"; import * as helpers from "@nomicfoundation/hardhat-network-helpers"; import fp from "lodash/fp"; @@ -11,138 +10,149 @@ import { ValidatorSetHbbftMock, } from "../src/types"; -//smart contracts -let randomHbbft: RandomHbbft; -let validatorSetHbbft: ValidatorSetHbbftMock; -let stakingHbbft: StakingHbbftMock; +import { random, range } from "./utils/utils"; -//addresses -let owner: SignerWithAddress; -let accounts: SignerWithAddress[]; -let initialValidators: string[]; -let initialStakingAddresses: string[]; +const minStake = ethers.parseEther('1'); +const maxStake = ethers.parseEther('100000'); -const minStake = BigNumber.from(ethers.utils.parseEther('1')); -const maxStake = BigNumber.from(ethers.utils.parseEther('100000')); // one epoch in 1 day. -const stakingFixedEpochDuration = BigNumber.from(86400); - +const stakingFixedEpochDuration = 86400n; // the transition time window is 1 hour. -const stakingTransitionTimeframeLength = BigNumber.from(3600); - -const stakingWithdrawDisallowPeriod = BigNumber.from(1); - -// the reward for the first epoch. -const epochReward = BigNumber.from(ethers.utils.parseEther('1')); - +const stakingTransitionTimeframeLength = 3600n; +const stakingWithdrawDisallowPeriod = 1n; const validatorInactivityThreshold = 365 * 86400 // 1 year const SystemAccountAddress = "0xffffFFFfFFffffffffffffffFfFFFfffFFFfFFfE"; describe('RandomHbbft', () => { + let owner: HardhatEthersSigner; + let accounts: HardhatEthersSigner[]; + let initialValidators: string[]; + let initialStakingAddresses: string[]; + let stubAddress: string + + async function deployContracts() { + const ValidatorSetFactory = await ethers.getContractFactory("ValidatorSetHbbftMock"); + const validatorSetHbbftProxy = await upgrades.deployProxy( + ValidatorSetFactory, + [ + owner.address, + '0x1000000000000000000000000000000000000001', // _blockRewardContract + stubAddress, // _randomContract + stubAddress, // _stakingContract + '0x4000000000000000000000000000000000000001', // _keyGenHistoryContract + validatorInactivityThreshold, // _validatorInactivityThreshold + initialValidators, // _initialMiningAddresses + initialStakingAddresses, // _initialStakingAddresses + ], + { initializer: 'initialize' } + ); + + await validatorSetHbbftProxy.waitForDeployment(); + + const RandomHbbftFactory = await ethers.getContractFactory("RandomHbbft"); + const randomHbbftProxy = await upgrades.deployProxy( + RandomHbbftFactory, + [ + owner.address, + await validatorSetHbbftProxy.getAddress() + ], + { initializer: 'initialize' } + ); + + await randomHbbftProxy.waitForDeployment(); + + let stakingParams = { + _validatorSetContract: await validatorSetHbbftProxy.getAddress(), + _initialStakingAddresses: initialStakingAddresses, + _delegatorMinStake: minStake, + _candidateMinStake: minStake, + _maxStake: maxStake, + _stakingFixedEpochDuration: stakingFixedEpochDuration, + _stakingTransitionTimeframeLength: stakingTransitionTimeframeLength, + _stakingWithdrawDisallowPeriod: stakingWithdrawDisallowPeriod + }; + + let initialValidatorsPubKeys: string[] = []; + let initialValidatorsIpAddresses: string[] = []; + + for (let i = 0; i < initialStakingAddresses.length; i++) { + initialValidatorsPubKeys.push(ethers.Wallet.createRandom().signingKey.publicKey); + initialValidatorsIpAddresses.push('0x00000000000000000000000000000000'); + } + + let initialValidatorsPubKeysSplit = fp.flatMap( + (x: string) => [ + x.substring(0, 66), + "0x" + x.substring(66, 130), + ])(initialValidatorsPubKeys); + + const StakingHbbftFactory = await ethers.getContractFactory("StakingHbbftMock"); + const stakingHbbftProxy = await upgrades.deployProxy( + StakingHbbftFactory, + [ + owner.address, + stakingParams, + initialValidatorsPubKeysSplit, // _publicKeys + initialValidatorsIpAddresses // _internetAddresses + ], + { initializer: 'initialize' } + ); + + await stakingHbbftProxy.waitForDeployment(); + + const validatorSetHbbft = ValidatorSetFactory.attach( + await validatorSetHbbftProxy.getAddress() + ) as ValidatorSetHbbftMock; + + const randomHbbft = RandomHbbftFactory.attach( + await randomHbbftProxy.getAddress() + ) as RandomHbbft; + + const stakingHbbft = StakingHbbftFactory.attach( + await stakingHbbftProxy.getAddress() + ) as StakingHbbftMock; + + await validatorSetHbbft.setSystemAddress(owner.address); + await validatorSetHbbft.setRandomContract(await randomHbbft.getAddress()); + await validatorSetHbbft.setStakingContract(await stakingHbbft.getAddress()); + + return { randomHbbft, validatorSetHbbft, stakingHbbft }; + } + async function impersonateSystemAcc() { await helpers.impersonateAccount(SystemAccountAddress); await owner.sendTransaction({ to: SystemAccountAddress, - value: ethers.utils.parseEther('10'), + value: ethers.parseEther('10'), }); return await ethers.getSigner(SystemAccountAddress); } - describe('Initializer', async () => { - beforeEach('Deploy Contracts', async () => { - [owner, ...accounts] = await ethers.getSigners(); - const accountAddresses = accounts.map(item => item.address); - - const stubAddress = owner.address; - - initialValidators = accountAddresses.slice(1, 25 + 1); // accounts[1...3] - initialStakingAddresses = accountAddresses.slice(26, 51); // accounts[4...6] - - expect(initialValidators.length).to.be.equal(25); - expect(initialStakingAddresses.length).to.be.equal(25); - expect(initialValidators[0]).to.not.be.equal(ethers.constants.AddressZero); - expect(initialValidators[1]).to.not.be.equal(ethers.constants.AddressZero); - expect(initialValidators[2]).to.not.be.equal(ethers.constants.AddressZero); + before(async function () { + [owner, ...accounts] = await ethers.getSigners(); - // Deploy ValidatorSetHbbft contract - const ValidatorSetFactory = await ethers.getContractFactory("ValidatorSetHbbftMock"); - validatorSetHbbft = await upgrades.deployProxy( - ValidatorSetFactory, - [ - owner.address, - '0x1000000000000000000000000000000000000001', // _blockRewardContract - stubAddress, // _randomContract - stubAddress, // _stakingContract - '0x4000000000000000000000000000000000000001', // _keyGenHistoryContract - validatorInactivityThreshold, // _validatorInactivityThreshold - initialValidators, // _initialMiningAddresses - initialStakingAddresses, // _initialStakingAddresses - ], - { initializer: 'initialize' } - ) as ValidatorSetHbbftMock; + stubAddress = owner.address; - // Deploy RandomHbbft contract - const RandomHbbftFactory = await ethers.getContractFactory("RandomHbbft"); - randomHbbft = await upgrades.deployProxy( - RandomHbbftFactory, - [ - owner.address, - validatorSetHbbft.address - ], - { initializer: 'initialize' } - ) as RandomHbbft; - - let stakingParams = { - _validatorSetContract: validatorSetHbbft.address, - _initialStakingAddresses: initialStakingAddresses, - _delegatorMinStake: minStake, - _candidateMinStake: minStake, - _maxStake: maxStake, - _stakingFixedEpochDuration: stakingFixedEpochDuration, - _stakingTransitionTimeframeLength: stakingTransitionTimeframeLength, - _stakingWithdrawDisallowPeriod: stakingWithdrawDisallowPeriod - }; - - let initialValidatorsPubKeys: string[] = []; - let initialValidatorsIpAddresses: string[] = []; - - for (let i = 0; i < initialStakingAddresses.length; i++) { - initialValidatorsPubKeys.push(ethers.Wallet.createRandom().publicKey); - initialValidatorsIpAddresses.push('0x00000000000000000000000000000000'); - } + const accountAddresses = accounts.map(item => item.address); - let initialValidatorsPubKeysSplit = fp.flatMap((x: string) => [x.substring(0, 66), '0x' + x.substring(66, 130)]) - (initialValidatorsPubKeys); + initialValidators = accountAddresses.slice(1, 25 + 1); // accounts[1...25] + initialStakingAddresses = accountAddresses.slice(26, 51); // accounts[26...50] - const StakingHbbftFactory = await ethers.getContractFactory("StakingHbbftMock"); - //Deploy StakingHbbft contract - stakingHbbft = await upgrades.deployProxy( - StakingHbbftFactory, - [ - owner.address, - stakingParams, - initialValidatorsPubKeysSplit, // _publicKeys - initialValidatorsIpAddresses // _internetAddresses - ], - { initializer: 'initialize' } - ) as StakingHbbftMock; - - // await randomHbbft.setSystemAddress(owner.address); - await validatorSetHbbft.setSystemAddress(owner.address); - await validatorSetHbbft.setRandomContract(randomHbbft.address); - await validatorSetHbbft.setStakingContract(stakingHbbft.address); - }); + expect(initialValidators.length).to.be.equal(25); + expect(initialStakingAddresses.length).to.be.equal(25); + }); + describe('Initializer', async () => { it("should revert initialization with validator contract = address(0)", async () => { const RandomHbbftFactory = await ethers.getContractFactory("RandomHbbft"); await expect(upgrades.deployProxy( RandomHbbftFactory, [ - owner.address, - ethers.constants.AddressZero + stubAddress, + ethers.ZeroAddress ], { initializer: 'initialize' } )).to.be.revertedWith('ValidatorSet must not be 0'); @@ -153,8 +163,8 @@ describe('RandomHbbft', () => { await expect(upgrades.deployProxy( RandomHbbftFactory, [ - ethers.constants.AddressZero, - validatorSetHbbft.address + ethers.ZeroAddress, + stubAddress, ], { initializer: 'initialize' } )).to.be.revertedWith('Owner address must not be 0'); @@ -165,169 +175,175 @@ describe('RandomHbbft', () => { const contract = await upgrades.deployProxy( RandomHbbftFactory, [ - owner.address, - validatorSetHbbft.address + stubAddress, + stubAddress, ], { initializer: 'initialize' } ); - expect(await contract.deployed()); + await contract.waitForDeployment(); await expect(contract.initialize( - owner.address, - validatorSetHbbft.address + stubAddress, + stubAddress, )).to.be.revertedWith('Initializable: contract is already initialized'); }); + }); - describe("currentSeed()", async () => { - it('setCurrentSeed must revert if called by non-owner', async () => { - await expect(randomHbbft.setCurrentSeed(100)) - .to.be.revertedWith('Must be executed by System'); - }); - - it('should set current seed by system', async function () { - const systemSigner = await impersonateSystemAcc(); - - await validatorSetHbbft.setIsFullHealth(true); - - const blockNumber = await helpers.time.latestBlock(); - const randomSeed = BigNumber.from(random(0, Number.MAX_SAFE_INTEGER)); + describe("currentSeed()", async () => { + it('setCurrentSeed must revert if called by non-owner', async () => { + const { randomHbbft } = await helpers.loadFixture(deployContracts); - await randomHbbft.connect(systemSigner).setCurrentSeed(randomSeed); + await expect(randomHbbft.setCurrentSeed(100n)).to.be.revertedWith('Must be executed by System'); + }); - expect(await randomHbbft.getSeedHistoric(blockNumber + 1)).to.equal(randomSeed); + it('should set current seed by system', async function () { + const { randomHbbft, validatorSetHbbft } = await helpers.loadFixture(deployContracts); - await helpers.stopImpersonatingAccount(SystemAccountAddress); - }); + const systemSigner = await impersonateSystemAcc(); - it('last 10 seeds must be equal to last 10 elements in the array', async () => { - const systemSigner = await impersonateSystemAcc(); - let seedsArray = new Array(); + await validatorSetHbbft.setIsFullHealth(true); - for (let i = 0; i < 100; i++) { - let randomSeed = BigNumber.from(random(0, Number.MAX_SAFE_INTEGER)); - seedsArray.push(randomSeed); - await randomHbbft.connect(systemSigner).setCurrentSeed(randomSeed); - } + const blockNumber = await helpers.time.latestBlock(); + const randomSeed = random(0, Number.MAX_SAFE_INTEGER); - await helpers.stopImpersonatingAccount(SystemAccountAddress); + await randomHbbft.connect(systemSigner).setCurrentSeed(randomSeed); - let currentBlock = await helpers.time.latestBlock(); + expect(await randomHbbft.getSeedHistoric(blockNumber + 1)).to.equal(randomSeed); - expect(await randomHbbft.currentSeed()).to.be.equal(seedsArray[seedsArray.length - 1]); - expect(await randomHbbft.getSeedsHistoric(range(currentBlock - 9, currentBlock + 1))).to.be.deep.equal(seedsArray.slice(-10)); - }); + await helpers.stopImpersonatingAccount(SystemAccountAddress); }); - describe("FullHealth()", async function () { - // it('should display health correctly', async () => { - // ((await validatorSetHbbft.getValidators()).length).should.be.equal(25); - // (await randomHbbft.isFullHealth()).should.be.equal(true); - // await validatorSetHbbft.connect(owner).removeMaliciousValidators([accounts[15].address]); - // ((await validatorSetHbbft.getValidators()).length).should.be.equal(24); - // (await randomHbbft.isFullHealth()).should.be.equal(false); - // }); + it('last 10 seeds must be equal to last 10 elements in the array', async () => { + const { randomHbbft } = await helpers.loadFixture(deployContracts); - // it('should set historical FullHealth() value as true when the block is healthy', async () => { - // let randomSeed = BigNumber.from(random(0, Number.MAX_SAFE_INTEGER)); - // // storing current seed and the health state of the network, network is healthy with 25 validators - // await randomHbbft.connect(owner).setCurrentSeed(randomSeed); - // ((await validatorSetHbbft.getValidators()).length).should.be.equal(25); + const systemSigner = await impersonateSystemAcc(); + let seedsArray = new Array(); - // // removing a validator so the network is not healthy - // await validatorSetHbbft.connect(owner).removeMaliciousValidators([accounts[15].address]); + for (let i = 0; i < 100; ++i) { + let randomSeed = random(0, Number.MAX_SAFE_INTEGER); + seedsArray.push(randomSeed); - // randomSeed = BigNumber.from(random(0, Number.MAX_SAFE_INTEGER)); - // // storing current seed and the health state of the network, network is NOT healthy with 24 validators - // await randomHbbft.connect(owner).setCurrentSeed(randomSeed); - // ((await validatorSetHbbft.getValidators()).length).should.be.equal(24); - // // getting historical health values for both previous and current block - // let blockNumber = await ethers.provider.getBlockNumber(); - // (await randomHbbft.isFullHealthsHistoric([blockNumber, blockNumber - 1])).should.be.deep.equal([false, true]); - // }); + await randomHbbft.connect(systemSigner).setCurrentSeed(randomSeed); + } - it('should display health correctly', async() => { - let healthy = false; + await helpers.stopImpersonatingAccount(SystemAccountAddress); - await validatorSetHbbft.setIsFullHealth(healthy); - expect(await randomHbbft.isFullHealth()).to.be.equal(healthy); + let currentBlock = await helpers.time.latestBlock(); - healthy = true; + expect(await randomHbbft.currentSeed()).to.be.equal(seedsArray[seedsArray.length - 1]); + expect(await randomHbbft.getSeedsHistoric(range(currentBlock - 9, currentBlock + 1))).to.be.deep.equal(seedsArray.slice(-10)); + }); + }); - await validatorSetHbbft.setIsFullHealth(healthy); - expect(await randomHbbft.isFullHealth()).to.be.equal(healthy); - }); + describe("FullHealth()", async function () { + // it('should display health correctly', async () => { + // ((await validatorSetHbbft.getValidators()).length).should.be.equal(25); + // (await randomHbbft.isFullHealth()).should.be.equal(true); + // await validatorSetHbbft.connect(owner).removeMaliciousValidators([accounts[15].address]); + // ((await validatorSetHbbft.getValidators()).length).should.be.equal(24); + // (await randomHbbft.isFullHealth()).should.be.equal(false); + // }); + + // it('should set historical FullHealth() value as true when the block is healthy', async () => { + // let randomSeed = BigNumber.from(random(0, Number.MAX_SAFE_INTEGER)); + // // storing current seed and the health state of the network, network is healthy with 25 validators + // await randomHbbft.connect(owner).setCurrentSeed(randomSeed); + // ((await validatorSetHbbft.getValidators()).length).should.be.equal(25); + + // // removing a validator so the network is not healthy + // await validatorSetHbbft.connect(owner).removeMaliciousValidators([accounts[15].address]); + + // randomSeed = BigNumber.from(random(0, Number.MAX_SAFE_INTEGER)); + // // storing current seed and the health state of the network, network is NOT healthy with 24 validators + // await randomHbbft.connect(owner).setCurrentSeed(randomSeed); + // ((await validatorSetHbbft.getValidators()).length).should.be.equal(24); + // // getting historical health values for both previous and current block + // let blockNumber = await ethers.provider.getBlockNumber(); + // (await randomHbbft.isFullHealthsHistoric([blockNumber, blockNumber - 1])).should.be.deep.equal([false, true]); + // }); + + it('should display health correctly', async () => { + const { randomHbbft, validatorSetHbbft } = await helpers.loadFixture(deployContracts); + + let healthy = false; + + await validatorSetHbbft.setIsFullHealth(healthy); + expect(await randomHbbft.isFullHealth()).to.be.equal(healthy); + + healthy = true; + + await validatorSetHbbft.setIsFullHealth(healthy); + expect(await randomHbbft.isFullHealth()).to.be.equal(healthy); + }); - it('should mark unhealty blocks', async() => { - let healthy = false; + it('should mark unhealty blocks', async () => { + const { randomHbbft, validatorSetHbbft } = await helpers.loadFixture(deployContracts); - await validatorSetHbbft.setIsFullHealth(healthy); - expect(await randomHbbft.isFullHealth()).to.be.equal(healthy); + let healthy = false; - const systemSigner = await impersonateSystemAcc(); + await validatorSetHbbft.setIsFullHealth(healthy); + expect(await randomHbbft.isFullHealth()).to.be.equal(healthy); - const blockNumber = await helpers.time.latestBlock(); - const randomSeed = BigNumber.from(random(0, Number.MAX_SAFE_INTEGER)); + const systemSigner = await impersonateSystemAcc(); - await randomHbbft.connect(systemSigner).setCurrentSeed(randomSeed); + const blockNumber = await helpers.time.latestBlock(); + const randomSeed = random(0, Number.MAX_SAFE_INTEGER); - expect(await randomHbbft.getSeedHistoric(blockNumber + 1)).to.equal(randomSeed); - expect(await randomHbbft.isFullHealthHistoric(blockNumber + 1)).to.equal(healthy); + await randomHbbft.connect(systemSigner).setCurrentSeed(randomSeed); - await helpers.stopImpersonatingAccount(SystemAccountAddress); + expect(await randomHbbft.getSeedHistoric(blockNumber + 1)).to.equal(randomSeed); + expect(await randomHbbft.isFullHealthHistoric(blockNumber + 1)).to.equal(healthy); - healthy = true; - await validatorSetHbbft.setIsFullHealth(true); - }); + await helpers.stopImpersonatingAccount(SystemAccountAddress); - it('should get full health historic array ', async () => { - const systemSigner = await impersonateSystemAcc(); + healthy = true; + await validatorSetHbbft.setIsFullHealth(true); + }); - let blocks = new Array(); - let expected = new Array(); + it('should get full health historic array ', async () => { + const { randomHbbft, validatorSetHbbft } = await helpers.loadFixture(deployContracts); - let healthy = true; - await validatorSetHbbft.setIsFullHealth(healthy); - expect(await randomHbbft.isFullHealth()).to.be.equal(healthy); + const systemSigner = await impersonateSystemAcc(); - let startBlock = await helpers.time.latestBlock(); + let blocks = new Array(); + let expected = new Array(); - for (let i = 0; i < 50; ++i) { - const randomSeed = BigNumber.from(random(0, Number.MAX_SAFE_INTEGER)); + let healthy = true; + await validatorSetHbbft.setIsFullHealth(healthy); + expect(await randomHbbft.isFullHealth()).to.be.equal(healthy); - await randomHbbft.connect(systemSigner).setCurrentSeed(randomSeed); + let startBlock = await helpers.time.latestBlock(); - blocks.push(BigNumber.from(startBlock).add(i + 1)); - expected.push(healthy); - } + for (let i = 0; i < 50; ++i) { + const randomSeed = random(0, Number.MAX_SAFE_INTEGER); - healthy = false; - await validatorSetHbbft.setIsFullHealth(healthy); - expect(await randomHbbft.isFullHealth()).to.be.equal(healthy); + await randomHbbft.connect(systemSigner).setCurrentSeed(randomSeed); - startBlock = await helpers.time.latestBlock(); + blocks.push(BigInt(startBlock + i + 1)); + expected.push(healthy); + } - for (let i = 0; i < 50; ++i) { - const randomSeed = BigNumber.from(random(0, Number.MAX_SAFE_INTEGER)); + healthy = false; + await validatorSetHbbft.setIsFullHealth(healthy); + expect(await randomHbbft.isFullHealth()).to.be.equal(healthy); - await randomHbbft.connect(systemSigner).setCurrentSeed(randomSeed); + startBlock = await helpers.time.latestBlock(); - blocks.push(BigNumber.from(startBlock).add(i + 1)); - expected.push(healthy); - } + for (let i = 0; i < 50; ++i) { + const randomSeed = random(0, Number.MAX_SAFE_INTEGER); - await helpers.stopImpersonatingAccount(SystemAccountAddress); + await randomHbbft.connect(systemSigner).setCurrentSeed(randomSeed); - const result = await randomHbbft.isFullHealthsHistoric(blocks); + blocks.push(BigInt(startBlock + i + 1)); + expected.push(healthy); + } - expect(result).to.be.deep.equal(expected); - }); - }) - }); -}); + await helpers.stopImpersonatingAccount(SystemAccountAddress); -function random(low: number, high: number) { - return Math.floor((Math.random() * (high - low) + low)); -} + const result = await randomHbbft.isFullHealthsHistoric(blocks); -const range = (start: number, end: number) => Array.from({ length: (end - start) }, (v, k) => k + start); + expect(result).to.be.deep.equal(expected); + }); + }) +}); diff --git a/test/StakingHbbft.ts b/test/StakingHbbft.ts index 98742b2f..4bb40997 100644 --- a/test/StakingHbbft.ts +++ b/test/StakingHbbft.ts @@ -1,6 +1,9 @@ import { ethers, network, upgrades } from "hardhat"; - +import { expect } from "chai"; +import { HardhatEthersSigner } from "@nomicfoundation/hardhat-ethers/signers"; import * as helpers from "@nomicfoundation/hardhat-network-helpers"; +import fp from "lodash/fp"; +import * as _ from "lodash"; import { BlockRewardHbbftMock, @@ -8,68 +11,68 @@ import { ValidatorSetHbbftMock, StakingHbbftMock, KeyGenHistory, - ConnectivityTrackerHbbftMock } from "../src/types"; -import fp from 'lodash/fp'; -import { BigNumber } from "ethers"; -import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers"; -import { PromiseOrValue } from "../src/types/common"; -import { expect } from "chai"; -import exp from "constants"; - - -require('chai') - .use(require('chai-as-promised')) - .use(require('chai-bn')(BigNumber)) - .should(); - -//addresses -let owner: SignerWithAddress; -let candidateMiningAddress: SignerWithAddress; -let candidateStakingAddress: SignerWithAddress; -let accounts: SignerWithAddress[]; +import { getNValidatorsPartNAcks } from "./testhelpers/data"; //consts -const ERROR_MSG = 'VM Exception while processing transaction: revert'; +const SystemAccountAddress = '0xffffFFFfFFffffffffffffffFfFFFfffFFFfFFfE'; +const ZeroPublicKey = ethers.zeroPadBytes("0x00", 64); +const ZeroIpAddress = ethers.zeroPadBytes("0x00", 16); describe('StakingHbbft', () => { + let owner: HardhatEthersSigner; + let candidateMiningAddress: HardhatEthersSigner; + let candidateStakingAddress: HardhatEthersSigner; + let accounts: HardhatEthersSigner[]; + let initialValidators: string[]; let initialStakingAddresses: string[]; let initialValidatorsPubKeys: string[]; let initialValidatorsPubKeysSplit: string[]; let initialValidatorsIpAddresses: string[]; - const minStake = BigNumber.from(ethers.utils.parseEther('1')); - const maxStake = BigNumber.from(ethers.utils.parseEther('100000')); - // one epoch in 1 day. - const stakingFixedEpochDuration = BigNumber.from(86400); + const minStake = ethers.parseEther('1'); + const maxStake = ethers.parseEther('100000'); - // the transition time window is 1 hour. - const stakingTransitionTimeframeLength = BigNumber.from(3600); + // the reward for the first epoch. + const epochReward = ethers.parseEther('1'); - const stakingWithdrawDisallowPeriod = BigNumber.from(1); + // one epoch in 1 day. + const stakingFixedEpochDuration = 86400n; - // the reward for the first epoch. - const epochReward = BigNumber.from(ethers.utils.parseEther('1')); + // the transition time window is 1 hour. + const stakingTransitionTimeframeLength = 3600n; + const stakingWithdrawDisallowPeriod = 1n; // the amount the deltaPot gets filled up. // this is 60-times more, since the deltaPot get's // drained each step by 60 by default. - const deltaPotFillupValue = epochReward.mul(BigNumber.from('60')); + const deltaPotFillupValue = epochReward * 60n; - const validatorInactivityThreshold = 365 * 86400 // 1 year + const validatorInactivityThreshold = 365n * 86400n // 1 year + + async function impersonateAcc(accAddress: string) { + await helpers.impersonateAccount(accAddress); + + await owner.sendTransaction({ + to: accAddress, + value: ethers.parseEther('10'), + }); + + return await ethers.getSigner(accAddress); + } async function deployContractsFixture() { const stubAddress = owner.address; const ConnectivityTrackerFactory = await ethers.getContractFactory("ConnectivityTrackerHbbftMock"); - const connectivityTracker = await upgrades.deployProxy(ConnectivityTrackerFactory) as ConnectivityTrackerHbbftMock; - await connectivityTracker.deployed(); + const connectivityTracker = await ConnectivityTrackerFactory.deploy(); + await connectivityTracker.waitForDeployment(); // Deploy ValidatorSet contract const ValidatorSetFactory = await ethers.getContractFactory("ValidatorSetHbbftMock"); - const validatorSetHbbft = await upgrades.deployProxy( + const validatorSetHbbftProxy = await upgrades.deployProxy( ValidatorSetFactory, [ owner.address, @@ -82,54 +85,61 @@ describe('StakingHbbft', () => { initialStakingAddresses, // _initialStakingAddresses ], { initializer: 'initialize' } - ) as ValidatorSetHbbftMock; + ); + + await validatorSetHbbftProxy.waitForDeployment(); // Deploy BlockRewardHbbft contract const BlockRewardHbbftFactory = await ethers.getContractFactory("BlockRewardHbbftMock"); - const blockRewardHbbft = await upgrades.deployProxy( + const blockRewardHbbftProxy = await upgrades.deployProxy( BlockRewardHbbftFactory, [ owner.address, - validatorSetHbbft.address, - connectivityTracker.address + await validatorSetHbbftProxy.getAddress(), + await connectivityTracker.getAddress(), ], { initializer: 'initialize' } - ) as BlockRewardHbbftMock; + ); + + await blockRewardHbbftProxy.waitForDeployment(); - await validatorSetHbbft.setBlockRewardContract(blockRewardHbbft.address); + await validatorSetHbbftProxy.setBlockRewardContract(await blockRewardHbbftProxy.getAddress()); const RandomHbbftFactory = await ethers.getContractFactory("RandomHbbft"); - const randomHbbft = await upgrades.deployProxy( + const randomHbbftProxy = await upgrades.deployProxy( RandomHbbftFactory, [ owner.address, - validatorSetHbbft.address + await validatorSetHbbftProxy.getAddress() ], { initializer: 'initialize' } - ) as RandomHbbft; + ); + + await randomHbbftProxy.waitForDeployment(); //without that, the Time is 0, //meaning a lot of checks that expect time to have some value deliver incorrect results. // await increaseTime(1); - const parts = [[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 181, 129, 31, 84, 186, 242, 5, 151, 59, 35, 196, 140, 106, 29, 40, 112, 142, 156, 132, 158, 47, 223, 253, 185, 227, 249, 190, 96, 5, 99, 239, 213, 127, 29, 136, 115, 71, 164, 202, 44, 6, 171, 131, 251, 147, 159, 54, 49, 1, 0, 0, 0, 0, 0, 0, 0, 153, 0, 0, 0, 0, 0, 0, 0, 4, 177, 133, 61, 18, 58, 222, 74, 65, 5, 126, 253, 181, 113, 165, 43, 141, 56, 226, 132, 208, 218, 197, 119, 179, 128, 30, 162, 251, 23, 33, 73, 38, 120, 246, 223, 233, 11, 104, 60, 154, 241, 182, 147, 219, 81, 45, 134, 239, 69, 169, 198, 188, 152, 95, 254, 170, 108, 60, 166, 107, 254, 204, 195, 170, 234, 154, 134, 26, 91, 9, 139, 174, 178, 248, 60, 65, 196, 218, 46, 163, 218, 72, 1, 98, 12, 109, 186, 152, 148, 159, 121, 254, 34, 112, 51, 70, 121, 51, 167, 35, 240, 5, 134, 197, 125, 252, 3, 213, 84, 70, 176, 160, 36, 73, 140, 104, 92, 117, 184, 80, 26, 240, 106, 230, 241, 26, 79, 46, 241, 195, 20, 106, 12, 186, 49, 254, 168, 233, 25, 179, 96, 62, 104, 118, 153, 95, 53, 127, 160, 237, 246, 41], [0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 181, 129, 31, 84, 186, 242, 5, 151, 59, 35, 196, 140, 106, 29, 40, 112, 142, 156, 132, 158, 47, 223, 253, 185, 227, 249, 190, 96, 5, 99, 239, 213, 127, 29, 136, 115, 71, 164, 202, 44, 6, 171, 131, 251, 147, 159, 54, 49, 1, 0, 0, 0, 0, 0, 0, 0, 153, 0, 0, 0, 0, 0, 0, 0, 4, 177, 133, 61, 18, 58, 222, 74, 65, 5, 126, 253, 181, 113, 165, 43, 141, 56, 226, 132, 208, 218, 197, 119, 179, 128, 30, 162, 251, 23, 33, 73, 38, 120, 246, 223, 233, 11, 104, 60, 154, 241, 182, 147, 219, 81, 45, 134, 239, 69, 169, 198, 188, 152, 95, 254, 170, 108, 60, 166, 107, 254, 204, 195, 170, 234, 154, 134, 26, 91, 9, 139, 174, 178, 248, 60, 65, 196, 218, 46, 163, 218, 72, 1, 98, 12, 109, 186, 152, 148, 159, 121, 254, 34, 112, 51, 70, 121, 51, 167, 35, 240, 5, 134, 197, 125, 252, 3, 213, 84, 70, 176, 160, 36, 73, 140, 104, 92, 117, 184, 80, 26, 240, 106, 230, 241, 26, 79, 46, 241, 195, 20, 106, 12, 186, 49, 254, 168, 233, 25, 179, 96, 62, 104, 118, 153, 95, 53, 127, 160, 237, 246, 41], [0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 181, 129, 31, 84, 186, 242, 5, 151, 59, 35, 196, 140, 106, 29, 40, 112, 142, 156, 132, 158, 47, 223, 253, 185, 227, 249, 190, 96, 5, 99, 239, 213, 127, 29, 136, 115, 71, 164, 202, 44, 6, 171, 131, 251, 147, 159, 54, 49, 1, 0, 0, 0, 0, 0, 0, 0, 153, 0, 0, 0, 0, 0, 0, 0, 4, 177, 133, 61, 18, 58, 222, 74, 65, 5, 126, 253, 181, 113, 165, 43, 141, 56, 226, 132, 208, 218, 197, 119, 179, 128, 30, 162, 251, 23, 33, 73, 38, 120, 246, 223, 233, 11, 104, 60, 154, 241, 182, 147, 219, 81, 45, 134, 239, 69, 169, 198, 188, 152, 95, 254, 170, 108, 60, 166, 107, 254, 204, 195, 170, 234, 154, 134, 26, 91, 9, 139, 174, 178, 248, 60, 65, 196, 218, 46, 163, 218, 72, 1, 98, 12, 109, 186, 152, 148, 159, 121, 254, 34, 112, 51, 70, 121, 51, 167, 35, 240, 5, 134, 197, 125, 252, 3, 213, 84, 70, 176, 160, 36, 73, 140, 104, 92, 117, 184, 80, 26, 240, 106, 230, 241, 26, 79, 46, 241, 195, 20, 106, 12, 186, 49, 254, 168, 233, 25, 179, 96, 62, 104, 118, 153, 95, 53, 127, 160, 237, 246, 41]]; - const acks = [[[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 145, 0, 0, 0, 0, 0, 0, 0, 4, 239, 1, 112, 13, 13, 251, 103, 186, 212, 78, 44, 47, 250, 221, 84, 118, 88, 7, 64, 206, 186, 11, 2, 8, 204, 140, 106, 179, 52, 251, 237, 19, 53, 74, 187, 217, 134, 94, 66, 68, 89, 42, 85, 207, 155, 220, 101, 223, 51, 199, 37, 38, 203, 132, 13, 77, 78, 114, 53, 219, 114, 93, 21, 25, 164, 12, 43, 252, 160, 16, 23, 111, 79, 230, 121, 95, 223, 174, 211, 172, 231, 0, 52, 25, 49, 152, 79, 128, 39, 117, 216, 85, 201, 237, 242, 151, 219, 149, 214, 77, 233, 145, 47, 10, 184, 175, 162, 174, 237, 177, 131, 45, 126, 231, 32, 147, 227, 170, 125, 133, 36, 123, 164, 232, 129, 135, 196, 136, 186, 45, 73, 226, 179, 169, 147, 42, 41, 140, 202, 191, 12, 73, 146, 2]], [[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 145, 0, 0, 0, 0, 0, 0, 0, 4, 239, 1, 112, 13, 13, 251, 103, 186, 212, 78, 44, 47, 250, 221, 84, 118, 88, 7, 64, 206, 186, 11, 2, 8, 204, 140, 106, 179, 52, 251, 237, 19, 53, 74, 187, 217, 134, 94, 66, 68, 89, 42, 85, 207, 155, 220, 101, 223, 51, 199, 37, 38, 203, 132, 13, 77, 78, 114, 53, 219, 114, 93, 21, 25, 164, 12, 43, 252, 160, 16, 23, 111, 79, 230, 121, 95, 223, 174, 211, 172, 231, 0, 52, 25, 49, 152, 79, 128, 39, 117, 216, 85, 201, 237, 242, 151, 219, 149, 214, 77, 233, 145, 47, 10, 184, 175, 162, 174, 237, 177, 131, 45, 126, 231, 32, 147, 227, 170, 125, 133, 36, 123, 164, 232, 129, 135, 196, 136, 186, 45, 73, 226, 179, 169, 147, 42, 41, 140, 202, 191, 12, 73, 146, 2]], [[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 145, 0, 0, 0, 0, 0, 0, 0, 4, 239, 1, 112, 13, 13, 251, 103, 186, 212, 78, 44, 47, 250, 221, 84, 118, 88, 7, 64, 206, 186, 11, 2, 8, 204, 140, 106, 179, 52, 251, 237, 19, 53, 74, 187, 217, 134, 94, 66, 68, 89, 42, 85, 207, 155, 220, 101, 223, 51, 199, 37, 38, 203, 132, 13, 77, 78, 114, 53, 219, 114, 93, 21, 25, 164, 12, 43, 252, 160, 16, 23, 111, 79, 230, 121, 95, 223, 174, 211, 172, 231, 0, 52, 25, 49, 152, 79, 128, 39, 117, 216, 85, 201, 237, 242, 151, 219, 149, 214, 77, 233, 145, 47, 10, 184, 175, 162, 174, 237, 177, 131, 45, 126, 231, 32, 147, 227, 170, 125, 133, 36, 123, 164, 232, 129, 135, 196, 136, 186, 45, 73, 226, 179, 169, 147, 42, 41, 140, 202, 191, 12, 73, 146, 2]]]; + const { parts, acks } = getNValidatorsPartNAcks(initialValidators.length); const KeyGenFactory = await ethers.getContractFactory("KeyGenHistory"); - const keyGenHistory = await upgrades.deployProxy( + const keyGenHistoryProxy = await upgrades.deployProxy( KeyGenFactory, [ owner.address, - validatorSetHbbft.address, + await validatorSetHbbftProxy.getAddress(), initialValidators, parts, acks ], { initializer: 'initialize' } - ) as KeyGenHistory; + ); + + await keyGenHistoryProxy.waitForDeployment(); let stakingParams = { - _validatorSetContract: validatorSetHbbft.address, + _validatorSetContract: await validatorSetHbbftProxy.getAddress(), _initialStakingAddresses: initialStakingAddresses, _delegatorMinStake: minStake, _candidateMinStake: minStake, @@ -152,14 +162,10 @@ describe('StakingHbbft', () => { (initialValidatorsPubKeys); // The IP addresses are irrelevant for these unit test, just initialize them to 0. - initialValidatorsIpAddresses = [ - '0x00000000000000000000000000000000', - '0x00000000000000000000000000000000', - '0x00000000000000000000000000000000' - ]; + initialValidatorsIpAddresses = Array(initialValidators.length).fill(ZeroIpAddress); const StakingHbbftFactory = await ethers.getContractFactory("StakingHbbftMock"); - const stakingHbbft = await upgrades.deployProxy( + const stakingHbbftProxy = await upgrades.deployProxy( StakingHbbftFactory, [ owner.address, @@ -168,15 +174,32 @@ describe('StakingHbbft', () => { initialValidatorsIpAddresses // _internetAddresses ], { initializer: 'initialize' } + ); + + await stakingHbbftProxy.waitForDeployment(); + + await validatorSetHbbftProxy.setRandomContract(await randomHbbftProxy.getAddress()); + await validatorSetHbbftProxy.setStakingContract(await stakingHbbftProxy.getAddress()); + await validatorSetHbbftProxy.setKeyGenHistoryContract(await keyGenHistoryProxy.getAddress()); + + const validatorSetHbbft = ValidatorSetFactory.attach( + await validatorSetHbbftProxy.getAddress() + ) as ValidatorSetHbbftMock; + + const stakingHbbft = StakingHbbftFactory.attach( + await stakingHbbftProxy.getAddress() ) as StakingHbbftMock; - await validatorSetHbbft.setRandomContract(randomHbbft.address); - await validatorSetHbbft.setStakingContract(stakingHbbft.address); - await validatorSetHbbft.setKeyGenHistoryContract(keyGenHistory.address); + const blockRewardHbbft = BlockRewardHbbftFactory.attach( + await blockRewardHbbftProxy.getAddress() + ) as BlockRewardHbbftMock; const delegatorMinStake = await stakingHbbft.delegatorMinStake(); const candidateMinStake = await stakingHbbft.candidateMinStake(); + const randomHbbft = RandomHbbftFactory.attach(await randomHbbftProxy.getAddress()) as RandomHbbft; + const keyGenHistory = KeyGenFactory.attach(await keyGenHistoryProxy.getAddress()) as KeyGenHistory; + return { validatorSetHbbft, stakingHbbft, @@ -190,1540 +213,369 @@ describe('StakingHbbft', () => { beforeEach(async () => { [owner, ...accounts] = await ethers.getSigners(); + const accountAddresses = accounts.map(item => item.address); + initialValidators = accountAddresses.slice(1, 3 + 1); // accounts[1...3] initialStakingAddresses = accountAddresses.slice(4, 6 + 1); // accounts[4...6] - initialStakingAddresses.length.should.be.equal(3); - initialStakingAddresses[0].should.not.be.equal('0x0000000000000000000000000000000000000000'); - initialStakingAddresses[1].should.not.be.equal('0x0000000000000000000000000000000000000000'); - initialStakingAddresses[2].should.not.be.equal('0x0000000000000000000000000000000000000000'); + + expect(initialStakingAddresses).to.be.lengthOf(3); + expect(initialStakingAddresses[0]).to.not.be.equal(ethers.ZeroAddress); + expect(initialStakingAddresses[1]).to.not.be.equal(ethers.ZeroAddress); + expect(initialStakingAddresses[2]).to.not.be.equal(ethers.ZeroAddress); }); describe('addPool()', async () => { - let candidateMiningAddress: SignerWithAddress; - let candidateStakingAddress: SignerWithAddress; - - before(async () => { - [owner, ...accounts] = await ethers.getSigners(); + let candidateMiningAddress: HardhatEthersSigner; + let candidateStakingAddress: HardhatEthersSigner; + beforeEach(async () => { candidateMiningAddress = accounts[7]; candidateStakingAddress = accounts[8]; }); it('should set the corresponding public keys', async () => { - const { stakingHbbft } = await helpers.loadFixture(deployContractsFixture); - - for (let i = 0; i < initialStakingAddresses.length; i++) { - (await stakingHbbft.getPoolPublicKey(initialStakingAddresses[i])).should.be.deep.equal(initialValidatorsPubKeys[i]); - } - }); - - it('should set the corresponding IP addresses', async () => { - const { stakingHbbft } = await helpers.loadFixture(deployContractsFixture); - - for (let i = 0; i < initialStakingAddresses.length; i++) { - let ip_result = (await stakingHbbft.getPoolInternetAddress(initialStakingAddresses[i])); - ip_result[0].should.be.deep.equal(initialValidatorsIpAddresses[i]); - } - }); - - it('should create a new pool', async () => { - const { stakingHbbft } = await helpers.loadFixture(deployContractsFixture); - - false.should.be.equal(await stakingHbbft.isPoolActive(candidateStakingAddress.address)); - await stakingHbbft.connect(candidateStakingAddress).addPool( - candidateMiningAddress.address, - '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - '0x00000000000000000000000000000000', - { value: minStake } - ); - - const poolIsActiveNow = await stakingHbbft.isPoolActive(candidateStakingAddress.address); - true.should.be.equal(poolIsActiveNow); - }); - - it('should fail if created with overstaked pool', async () => { - const { stakingHbbft } = await helpers.loadFixture(deployContractsFixture); - - false.should.be.equal(await stakingHbbft.isPoolActive(candidateStakingAddress.address)); - await stakingHbbft.connect(candidateStakingAddress).addPool( - candidateMiningAddress.address, - '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - '0x00000000000000000000000000000000', - { value: maxStake.add(minStake) } - ).should.be.revertedWith('stake limit has been exceeded'); - }); - - it('should fail if mining address is 0', async () => { - const { stakingHbbft } = await helpers.loadFixture(deployContractsFixture); - - await stakingHbbft.connect(candidateStakingAddress).addPool( - '0x0000000000000000000000000000000000000000', - '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - '0x00000000000000000000000000000000', - { value: minStake } - ).should.be.revertedWith("Mining address can't be 0"); - }); - - it('should fail if mining address is equal to staking', async () => { - const { stakingHbbft } = await helpers.loadFixture(deployContractsFixture); - - await stakingHbbft.connect(candidateStakingAddress).addPool( - candidateStakingAddress.address, - '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - '0x00000000000000000000000000000000', - { value: minStake } - ).should.be.revertedWith("Mining address cannot be the same as the staking one"); - }); - - it('should fail if the pool with the same mining/staking address is already existing', async () => { - const { stakingHbbft } = await helpers.loadFixture(deployContractsFixture); - - const candidateMiningAddress2 = accounts[9]; - const candidateStakingAddress2 = accounts[10]; - - await stakingHbbft.connect(candidateStakingAddress).addPool(candidateMiningAddress.address, '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - '0x00000000000000000000000000000000', { value: minStake }); - - await stakingHbbft.connect(candidateStakingAddress2).addPool(candidateMiningAddress.address, '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - '0x00000000000000000000000000000000', { value: minStake }).should.be.rejectedWith("Mining address already used as a mining one"); - await stakingHbbft.connect(candidateStakingAddress).addPool(candidateMiningAddress2.address, '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - '0x00000000000000000000000000000000', { value: minStake }).should.be.rejectedWith("Staking address already used as a staking one"); - - await stakingHbbft.connect(candidateMiningAddress2).addPool(candidateStakingAddress.address, '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - '0x00000000000000000000000000000000', { value: minStake }).should.be.rejectedWith("Mining address already used as a staking one"); - await stakingHbbft.connect(candidateMiningAddress).addPool(candidateStakingAddress2.address, '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - '0x00000000000000000000000000000000', { value: minStake }).should.be.rejectedWith("Staking address already used as a mining one"); - - await stakingHbbft.connect(candidateMiningAddress2).addPool(candidateMiningAddress.address, '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - '0x00000000000000000000000000000000', { value: minStake }).should.be.rejectedWith("Mining address already used as a mining one"); - await stakingHbbft.connect(candidateMiningAddress).addPool(candidateMiningAddress2.address, '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - '0x00000000000000000000000000000000', { value: minStake }).should.be.rejectedWith("Staking address already used as a mining one"); - - await stakingHbbft.connect(candidateStakingAddress2).addPool(candidateStakingAddress.address, '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - '0x00000000000000000000000000000000', { value: minStake }).should.be.rejectedWith("Mining address already used as a staking one"); - await stakingHbbft.connect(candidateStakingAddress).addPool(candidateStakingAddress2.address, '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - '0x00000000000000000000000000000000', { value: minStake }).should.be.rejectedWith("Staking address already used as a staking one"); - - await stakingHbbft.connect(candidateStakingAddress2).addPool(candidateMiningAddress2.address, '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - '0x00000000000000000000000000000000', { value: minStake }); - }); - - it('should fail if gasPrice is 0', async () => { - const { stakingHbbft } = await helpers.loadFixture(deployContractsFixture); - - await stakingHbbft.connect(candidateStakingAddress).addPool(candidateMiningAddress.address, '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - '0x00000000000000000000000000000000', { gasPrice: 0, value: minStake }).should.be.rejectedWith("GasPrice is 0"); - }); - - it('should fail if staking amount is 0', async () => { - const { stakingHbbft } = await helpers.loadFixture(deployContractsFixture); - - await stakingHbbft.connect(candidateStakingAddress).addPool(candidateMiningAddress.address, '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - '0x00000000000000000000000000000000', { value: BigNumber.from(0) }).should.be.rejectedWith("Stake: stakingAmount is 0"); - }); - - // it('should fail if stacking time is inside disallowed range', async () => { - // await stakingHbbft.addPool(candidateMiningAddress.address, '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - // '0x00000000000000000000000000000000', {connect(candidateStakingAddress).value: minStake}).should.be.rejectedWith("Stake: disallowed period"); - // await increaseTime(2); - // await stakingHbbft.addPool(candidateMiningAddress.address, '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - // '0x00000000000000000000000000000000', {connect(candidateStakingAddress).value: minStake}); - // }); - - it('should fail if staking amount is less than CANDIDATE_MIN_STAKE', async () => { - const { stakingHbbft } = await helpers.loadFixture(deployContractsFixture); - - await stakingHbbft.connect(candidateStakingAddress).addPool(candidateMiningAddress.address, '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - '0x00000000000000000000000000000000', { value: minStake.div(BigNumber.from(2)) }).should.be.rejectedWith("Stake: candidateStake less than candidateMinStake"); - }); - - it('stake amount should be increased', async () => { - const { stakingHbbft } = await helpers.loadFixture(deployContractsFixture); - - const amount = minStake.mul(BigNumber.from(2)); - await stakingHbbft.connect(candidateStakingAddress).addPool(candidateMiningAddress.address, '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - '0x00000000000000000000000000000000', { value: amount }); - amount.should.be.equal(await stakingHbbft.stakeAmount(candidateStakingAddress.address, candidateStakingAddress.address)); - amount.should.be.equal(await stakingHbbft.stakeAmountByCurrentEpoch(candidateStakingAddress.address, candidateStakingAddress.address)); - amount.should.be.equal(await stakingHbbft.stakeAmountTotal(candidateStakingAddress.address)); - }); - - it('should be able to add more than one pool', async () => { - const { stakingHbbft, validatorSetHbbft } = await helpers.loadFixture(deployContractsFixture); - - const candidate1MiningAddress = candidateMiningAddress; - const candidate1StakingAddress = candidateStakingAddress; - const candidate2MiningAddress = accounts[9]; - const candidate2StakingAddress = accounts[10]; - const amount1 = minStake.mul(BigNumber.from(2)); - const amount2 = minStake.mul(BigNumber.from(3)); - - // Add two new pools - (await stakingHbbft.isPoolActive(candidate1StakingAddress.address)).should.be.equal(false); - (await stakingHbbft.isPoolActive(candidate2StakingAddress.address)).should.be.equal(false); - await stakingHbbft.connect(candidate1StakingAddress).addPool(candidate1MiningAddress.address, '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - '0x00000000000000000000000000000000', { value: amount1 }); - await stakingHbbft.connect(candidate2StakingAddress).addPool(candidate2MiningAddress.address, '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - '0x00000000000000000000000000000000', { value: amount2 }); - (await stakingHbbft.isPoolActive(candidate1StakingAddress.address)).should.be.equal(true); - (await stakingHbbft.isPoolActive(candidate2StakingAddress.address)).should.be.equal(true); - - // Check indexes (0...2 are busy by initial validators) - BigNumber.from(3).should.be.equal(await stakingHbbft.poolIndex(candidate1StakingAddress.address)); - BigNumber.from(4).should.be.equal(await stakingHbbft.poolIndex(candidate2StakingAddress.address)); - - // Check indexes in the `poolsToBeElected` list - BigNumber.from(0).should.be.equal(await stakingHbbft.poolToBeElectedIndex(candidate1StakingAddress.address)); - BigNumber.from(1).should.be.equal(await stakingHbbft.poolToBeElectedIndex(candidate2StakingAddress.address)); - - // Check pools' existence - const validators = await validatorSetHbbft.getValidators(); - - (await stakingHbbft.getPools()).should.be.deep.equal([ - await validatorSetHbbft.stakingByMiningAddress(validators[0]), - await validatorSetHbbft.stakingByMiningAddress(validators[1]), - await validatorSetHbbft.stakingByMiningAddress(validators[2]), - candidate1StakingAddress.address, - candidate2StakingAddress.address - ]); - }); - - it("shouldn't allow adding more than MAX_CANDIDATES pools", async () => { - const { stakingHbbft } = await helpers.loadFixture(deployContractsFixture); - - for (let p = initialValidators.length; p < 100; p++) { - // Generate new candidate staking address - let candidateStakingAddress = '0x'; - for (let i = 0; i < 20; i++) { - let randomByte = random(0, 255).toString(16); - if (randomByte.length % 2) { - randomByte = '0' + randomByte; - } - candidateStakingAddress += randomByte; - } - - // Add a new pool - await stakingHbbft.addPoolActiveMock(candidateStakingAddress); - BigNumber.from(p).should.be.equal(await stakingHbbft.poolIndex(candidateStakingAddress)); - } - - // Try to add a new pool outside of max limit, max limit is 100 in mock contract. - await stakingHbbft.connect(candidateStakingAddress).addPool(candidateMiningAddress.address, '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - '0x00000000000000000000000000000000', { value: minStake }).should.be.rejectedWith("MAX_CANDIDATES pools exceeded"); - false.should.be.equal(await stakingHbbft.isPoolActive(candidateStakingAddress.address)); - }); - - it('should remove added pool from the list of inactive pools', async () => { - const { stakingHbbft } = await helpers.loadFixture(deployContractsFixture); - - await stakingHbbft.addPoolInactiveMock(candidateStakingAddress.address); - (await stakingHbbft.getPoolsInactive()).should.be.deep.equal([candidateStakingAddress.address]); - await stakingHbbft.connect(candidateStakingAddress).addPool(candidateMiningAddress.address, '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - '0x00000000000000000000000000000000', { value: minStake }); - true.should.be.equal(await stakingHbbft.isPoolActive(candidateStakingAddress.address)); - (await stakingHbbft.getPoolsInactive()).length.should.be.equal(0); - }); - }); - - describe('contract balance', async () => { - before(async () => { - [owner, ...accounts] = await ethers.getSigners(); - - candidateMiningAddress = accounts[7]; - candidateStakingAddress = accounts[8]; - }); - - it('cannot be increased by sending native coins', async () => { - const { stakingHbbft } = await helpers.loadFixture(deployContractsFixture); - - await owner.sendTransaction({ to: stakingHbbft.address, value: 1 }).should.be.rejectedWith("Not payable"); - await owner.sendTransaction({ to: accounts[1].address, value: 1 }); - (await ethers.provider.getBalance(stakingHbbft.address)).should.be.equal('0'); - }); - - it('can be increased by sending coins to payable functions', async () => { - const { stakingHbbft } = await helpers.loadFixture(deployContractsFixture); - - (await ethers.provider.getBalance(stakingHbbft.address)).should.be.equal('0'); - await stakingHbbft.connect(candidateStakingAddress).addPool(candidateMiningAddress.address, '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - '0x00000000000000000000000000000000', { value: minStake }); - (BigNumber.from(await ethers.provider.getBalance(stakingHbbft.address))).should.be.equal(minStake); - await stakingHbbft.connect(candidateStakingAddress).stake(candidateStakingAddress.address, { value: minStake }); - (BigNumber.from(await ethers.provider.getBalance(stakingHbbft.address))).should.be.equal(minStake.mul(BigNumber.from(2))); - }); - }); - - describe('claimReward()', async () => { - let delegator: SignerWithAddress; - let delegatorMinStake: BigNumber; - - let stakingHbbftContract: StakingHbbftMock; - let validatorSetContract: ValidatorSetHbbftMock; - let blockRewardContract: BlockRewardHbbftMock; - - beforeEach(async () => { - const { stakingHbbft, validatorSetHbbft, blockRewardHbbft } = await helpers.loadFixture(deployContractsFixture); - - stakingHbbftContract = stakingHbbft; - validatorSetContract = validatorSetHbbft; - blockRewardContract = blockRewardHbbft; - - // Staking epoch #0 starts on block #1 - (await stakingHbbft.stakingEpoch()).should.be.equal(BigNumber.from(0)); - //(await stakingHbbft.stakingEpochStartBlock()).should.be.equal(BigNumber.from(1)); - //(await validatorSetHbbft.getCurrentBlockNumber()).should.be.equal(BigNumber.from(1)); - //(await stakingHbbft.getCurrentBlockNumber()).should.be.equal(BigNumber.from(1)); - - // Validators place stakes during the epoch #0 - const candidateMinStake = await stakingHbbft.candidateMinStake(); - for (let i = 0; i < initialStakingAddresses.length; i++) { - // Validator places stake on themselves - await stakingHbbft.connect(await ethers.getSigner(initialStakingAddresses[i])).stake(initialStakingAddresses[i], { value: candidateMinStake }); - } - - // The delegator places stake on the first validator - delegator = accounts[10]; - delegatorMinStake = await stakingHbbft.delegatorMinStake(); - await stakingHbbft.connect(delegator).stake(initialStakingAddresses[0], { value: delegatorMinStake }); - - // Epoch's fixed duration ends - //const stakingFixedEpochEndBlock = await stakingHbbft.stakingFixedEpochEndBlock(); - // - - await timeTravelToTransition(blockRewardContract, stakingHbbftContract); - - // the pending validator set should be updated - (await validatorSetHbbft.getPendingValidators()).length.should.be.equal(3); - - // Staking epoch #0 finishes - //const stakingEpochEndBlock = stakingFixedEpochEndBlock.add(keyGenerationDuration); - - await timeTravelToEndEpoch(blockRewardContract, stakingHbbftContract); - (await stakingHbbft.stakingEpoch()).should.be.equal(BigNumber.from(1)); - }); - - async function _claimRewardStakeIncreasing(epochsPoolRewarded: number[], epochsStakeIncreased: number[]) { - const miningAddress = initialValidators[0]; - const stakingAddress = initialStakingAddresses[0]; - const epochPoolReward = BigNumber.from(ethers.utils.parseEther('1')); - const maxStakingEpoch = Math.max(Math.max.apply(null, epochsPoolRewarded), Math.max.apply(null, epochsStakeIncreased)); - - (await ethers.provider.getBalance(blockRewardContract.address)).should.be.equal('0'); - - // Emulate rewards for the pool - for (let i = 0; i < epochsPoolRewarded.length; i++) { - const stakingEpoch = epochsPoolRewarded[i]; - await blockRewardContract.setEpochPoolReward(stakingEpoch, miningAddress, { value: epochPoolReward }); - } - - (BigNumber.from(await ethers.provider.getBalance(blockRewardContract.address))).should.be.equal(epochPoolReward.mul(BigNumber.from(epochsPoolRewarded.length))); - - let prevStakingEpoch = 0; - const validatorStakeAmount = await stakingHbbftContract.stakeAmount(stakingAddress, stakingAddress); - let stakeAmount = await stakingHbbftContract.stakeAmount(stakingAddress, delegator.address); - let stakeAmountOnEpoch = [BigNumber.from(0)]; - - let s = 0; - for (let epoch = 1; epoch <= maxStakingEpoch; epoch++) { - const stakingEpoch = epochsStakeIncreased[s]; - - if (stakingEpoch == epoch) { - const startBlock = BigNumber.from(120954 * stakingEpoch + 1); - await stakingHbbftContract.setStakingEpoch(stakingEpoch); - await stakingHbbftContract.setValidatorMockSetAddress(owner.address); - //await stakingHbbft.setStakingEpochStartBlock(startBlock); - await stakingHbbftContract.setValidatorMockSetAddress(validatorSetContract.address); - - - // Emulate delegator's stake increasing - await stakingHbbftContract.connect(delegator).stake(stakingAddress, { value: delegatorMinStake }); - - for (let e = prevStakingEpoch + 1; e <= stakingEpoch; e++) { - stakeAmountOnEpoch[e] = stakeAmount; - } - stakeAmount = await stakingHbbftContract.stakeAmount(stakingAddress, delegator.address); - prevStakingEpoch = stakingEpoch; - s++; - } - - // Emulate snapshotting for the pool - await blockRewardContract.snapshotPoolStakeAmounts(stakingHbbftContract.address, epoch + 1, miningAddress); - } - - const lastEpochRewarded = epochsPoolRewarded[epochsPoolRewarded.length - 1]; - await stakingHbbftContract.setStakingEpoch(lastEpochRewarded + 1); - - if (prevStakingEpoch < lastEpochRewarded) { - for (let e = prevStakingEpoch + 1; e <= lastEpochRewarded; e++) { - stakeAmountOnEpoch[e] = stakeAmount; - } - } - - let delegatorRewardExpected = BigNumber.from(0); - let validatorRewardExpected = BigNumber.from(0); - for (let i = 0; i < epochsPoolRewarded.length; i++) { - const stakingEpoch = epochsPoolRewarded[i]; - await blockRewardContract.setValidatorMinRewardPercent(stakingEpoch, 30); - const delegatorShare = await blockRewardContract.delegatorShare( - stakingEpoch, - stakeAmountOnEpoch[stakingEpoch], - validatorStakeAmount, - validatorStakeAmount.add(stakeAmountOnEpoch[stakingEpoch]), - epochPoolReward - ); - const validatorShare = await blockRewardContract.validatorShare( - stakingEpoch, - validatorStakeAmount, - validatorStakeAmount.add(stakeAmountOnEpoch[stakingEpoch]), - epochPoolReward - ); - delegatorRewardExpected = delegatorRewardExpected.add(delegatorShare); - validatorRewardExpected = validatorRewardExpected.add(validatorShare); - } - - return { - delegatorMinStake, - miningAddress, - stakingAddress, - epochPoolReward, - maxStakingEpoch, - delegatorRewardExpected, - validatorRewardExpected - }; - } - - async function _delegatorNeverStakedBefore() { - const miningAddress = initialValidators[0]; - const stakingAddress = initialStakingAddresses[0]; - - const epochPoolReward = BigNumber.from(ethers.utils.parseEther('1')); - const deltaPotFillupValue = epochPoolReward.mul(BigNumber.from('60')); - //blockRewardHbbft.add - await blockRewardContract.addToDeltaPot({ value: deltaPotFillupValue }); - - - // the beforeeach alsready runs 1 epoch, so we expect to be in epoch 1 here. - (await stakingHbbftContract.stakingEpoch()).should.be.equal(BigNumber.from(1)); - - //await timeTravelToEndEpoch(blockRewardContract, stakingHbbftContract); - //(await stakingHbbft.stakingEpoch()).should.be.equal(BigNumber.from(2)); - - // the pending validator set should be empy - (await validatorSetContract.getPendingValidators()).length.should.be.equal(0); - - // Staking epoch #1: Start - (await validatorSetContract.getValidators()).should.be.deep.equal(initialValidators); - (await stakingHbbftContract.areStakeAndWithdrawAllowed()).should.be.equal(true); - await stakingHbbftContract.connect(delegator).orderWithdraw(stakingAddress, delegatorMinStake); - - - (await validatorSetContract.getPendingValidators()).length.should.be.equal(0); - - // Staking epoch #1: start of Transition Phase! - await timeTravelToTransition(blockRewardContract, stakingHbbftContract); - - // the pending validator set should be updated - (await validatorSetContract.getPendingValidators()).length.should.be.equal(3); - - //!!! here it failes for some reason - //Staking epoch #1: Epoch end block - await timeTravelToEndEpoch(blockRewardContract, stakingHbbftContract); - - // we restock this one epoch reward that got payed out. - // todo: think about: Maybe this restocking should happen in the timeTravelToEndEpoch function to have - // constant epoch payouts. - await blockRewardContract.addToDeltaPot({ value: epochPoolReward }); - - // now epoch #2 has started. - (await stakingHbbftContract.stakingEpoch()).should.be.equal(BigNumber.from(2)); - - // the pending validator set should be empty - (await validatorSetContract.getPendingValidators()).length.should.be.equal(0); - - // epoch #2: the delegator withdraws their stake - await stakingHbbftContract.connect(delegator).claimOrderedWithdraw(stakingAddress); - - (await stakingHbbftContract.stakeAmount(stakingAddress, delegator.address)).should.be.equal(BigNumber.from(0)); - (await stakingHbbftContract.orderedWithdrawAmount(stakingAddress, delegator.address)).should.be.equal(BigNumber.from(0)); - (await stakingHbbftContract.stakeFirstEpoch(stakingAddress, delegator.address)).should.be.equal(BigNumber.from(1)); - (await stakingHbbftContract.stakeLastEpoch(stakingAddress, delegator.address)).should.be.equal(BigNumber.from(2)); - - await stakingHbbftContract.setStakeFirstEpoch(stakingAddress, delegator.address, BigNumber.from(0)); - await stakingHbbftContract.setStakeLastEpoch(stakingAddress, delegator.address, BigNumber.from(0)); - await stakingHbbftContract.clearDelegatorStakeSnapshot(stakingAddress, delegator.address, BigNumber.from(1)); - await stakingHbbftContract.clearDelegatorStakeSnapshot(stakingAddress, delegator.address, BigNumber.from(2)); - - // Staking epoch #2: end of fixed duration - await timeTravelToTransition(blockRewardContract, stakingHbbftContract); - - // Staking epoch #2: Epoch end block - await timeTravelToEndEpoch(blockRewardContract, stakingHbbftContract); - - (await stakingHbbftContract.stakingEpoch()).should.be.equal(BigNumber.from(3)); - //(await stakingHbbft.stakingEpochStartBlock()).should.be.equal(stakingEpochEndBlock.add(BigNumber.from(1))); - return { miningAddress, stakingAddress, epochPoolReward }; - } - - async function testClaimRewardRandom(epochsPoolRewarded: number[], epochsStakeIncreased: number[]) { - const { - delegatorMinStake, - miningAddress, - stakingAddress, - epochPoolReward, - maxStakingEpoch, - delegatorRewardExpected, - validatorRewardExpected - } = await _claimRewardStakeIncreasing( - epochsPoolRewarded, - epochsStakeIncreased - ); - - const delegatorCoinsBalanceBefore = BigNumber.from(await ethers.provider.getBalance(delegator.address)); - let weiSpent = BigNumber.from(0); - let epochsPoolRewardedRandom = epochsPoolRewarded; - shuffle(epochsPoolRewardedRandom); - for (let i = 0; i < epochsPoolRewardedRandom.length; i++) { - const stakingEpoch = epochsPoolRewardedRandom[i]; - let result = await stakingHbbftContract.connect(delegator).claimReward([stakingEpoch], stakingAddress); - let receipt = await ethers.provider.getTransactionReceipt(result.hash); - weiSpent = weiSpent.add((BigNumber.from(receipt.gasUsed)).mul(BigNumber.from(result.gasPrice))); - // Call once again to ensure the reward cannot be withdrawn twice - result = await stakingHbbftContract.connect(delegator).claimReward([stakingEpoch], stakingAddress); - receipt = await ethers.provider.getTransactionReceipt(result.hash); - weiSpent = weiSpent.add((BigNumber.from(receipt.gasUsed)).mul(BigNumber.from(result.gasPrice))); - } - const delegatorCoinsBalanceAfter = BigNumber.from(await ethers.provider.getBalance(delegator.address)); - delegatorCoinsBalanceAfter.should.be.equal(delegatorCoinsBalanceBefore.add(delegatorRewardExpected).sub(weiSpent)); - - const validatorCoinsBalanceBefore = BigNumber.from(await ethers.provider.getBalance(stakingAddress)); - weiSpent = BigNumber.from(0); - shuffle(epochsPoolRewardedRandom); - for (let i = 0; i < epochsPoolRewardedRandom.length; i++) { - const stakingEpoch = epochsPoolRewardedRandom[i]; - const result = await stakingHbbftContract.connect(await ethers.getSigner(stakingAddress)).claimReward([stakingEpoch], stakingAddress); - let receipt = await ethers.provider.getTransactionReceipt(result.hash); - weiSpent = weiSpent.add((BigNumber.from(receipt.gasUsed)).mul(BigNumber.from(result.gasPrice))); - } - const validatorCoinsBalanceAfter = BigNumber.from(await ethers.provider.getBalance(stakingAddress)); - validatorCoinsBalanceAfter.should.be.equal(validatorCoinsBalanceBefore.add(validatorRewardExpected).sub(weiSpent)); - - const blockRewardBalanceExpected = epochPoolReward.mul(BigNumber.from(epochsPoolRewarded.length)).sub(delegatorRewardExpected).sub(validatorRewardExpected); - (BigNumber.from(await ethers.provider.getBalance(blockRewardContract.address))).should.be.equal(blockRewardBalanceExpected); - } - - async function testClaimRewardAfterStakeIncreasing(epochsPoolRewarded: number[], epochsStakeIncreased: number[]) { - const { - delegatorMinStake, - miningAddress, - stakingAddress, - epochPoolReward, - maxStakingEpoch, - delegatorRewardExpected, - validatorRewardExpected - } = await _claimRewardStakeIncreasing( - epochsPoolRewarded, - epochsStakeIncreased - ); - - let rewardAmountsCalculated = await stakingHbbftContract.getRewardAmount([], stakingAddress, delegator.address); - rewardAmountsCalculated.should.be.equal(delegatorRewardExpected); - - const delegatorCoinsBalanceBefore = BigNumber.from(await ethers.provider.getBalance(delegator.address)); - const result = await stakingHbbftContract.connect(delegator).claimReward([], stakingAddress); - const receipt = await result.wait(); - const weiSpent = (BigNumber.from(receipt.gasUsed)).mul(BigNumber.from(result.gasPrice)); - const delegatorCoinsBalanceAfter = BigNumber.from(await ethers.provider.getBalance(delegator.address)); - - delegatorCoinsBalanceAfter.should.be.equal(delegatorCoinsBalanceBefore.add(delegatorRewardExpected).sub(weiSpent)); - - rewardAmountsCalculated = await stakingHbbftContract.getRewardAmount([], stakingAddress, stakingAddress); - rewardAmountsCalculated.should.be.equal(validatorRewardExpected); - - await stakingHbbftContract.connect(await ethers.getSigner(stakingAddress)).claimReward([], stakingAddress); - - const blockRewardBalanceExpected = epochPoolReward.mul(BigNumber.from(epochsPoolRewarded.length)).sub(delegatorRewardExpected).sub(validatorRewardExpected); - - (BigNumber.from(await ethers.provider.getBalance(blockRewardContract.address))).should.be.equal(blockRewardBalanceExpected); - } - - async function testClaimRewardAfterStakeMovements(epochsPoolRewarded: number[], epochsStakeMovement: number[]) { - const miningAddress = initialValidators[0]; - const stakingAddress = initialStakingAddresses[0]; - const epochPoolReward = BigNumber.from(ethers.utils.parseEther('1')); - - const deltaPotFillupValue = epochPoolReward.mul(BigNumber.from('60')); - //blockRewardHbbft.add - await blockRewardContract.addToDeltaPot({ value: deltaPotFillupValue }); - - const currentblockRewardHbbftBalance = BigNumber.from(await ethers.provider.getBalance(blockRewardContract.address)); - currentblockRewardHbbftBalance.should.be.equal(deltaPotFillupValue); - - for (let i = 0; i < epochsPoolRewarded.length; i++) { - const stakingEpoch = epochsPoolRewarded[i]; - - // Emulate snapshotting for the pool - await blockRewardContract.snapshotPoolStakeAmounts(stakingHbbftContract.address, stakingEpoch, miningAddress); - - // Emulate rewards for the pool - await blockRewardContract.setEpochPoolReward(stakingEpoch, miningAddress, { value: epochPoolReward }); - } - - // initial validator got reward for epochsPoolRewarded - (await blockRewardContract.epochsPoolGotRewardFor(miningAddress)).length.should.be.equal(epochsPoolRewarded.length); - - (BigNumber.from(await ethers.provider.getBalance(blockRewardContract.address))).should.be.equal(deltaPotFillupValue.add(epochPoolReward.mul(BigNumber.from(epochsPoolRewarded.length)))); - - for (let i = 0; i < epochsStakeMovement.length; i++) { - const stakingEpoch = epochsStakeMovement[i]; - - // Emulate delegator's stake movement - const startBlock = BigNumber.from(120954 * stakingEpoch + 1); - await stakingHbbftContract.setStakingEpoch(stakingEpoch); - await stakingHbbftContract.setValidatorMockSetAddress(owner.address); - //await stakingHbbft.setStakingEpochStartBlock(startBlock); - await stakingHbbftContract.setValidatorMockSetAddress(validatorSetContract.address); - await stakingHbbftContract.connect(delegator).orderWithdraw(stakingAddress, delegatorMinStake); - await stakingHbbftContract.connect(delegator).orderWithdraw(stakingAddress, BigNumber.from(0).sub(delegatorMinStake)); - } - - const stakeFirstEpoch = await stakingHbbftContract.stakeFirstEpoch(stakingAddress, delegator.address); - await stakingHbbftContract.setStakeFirstEpoch(stakingAddress, delegator.address, 0); - await stakingHbbftContract.connect(delegator).claimReward([], stakingAddress).should.be.rejectedWith("Claim: first epoch can't be 0"); - await stakingHbbftContract.setStakeFirstEpoch(stakingAddress, delegator.address, stakeFirstEpoch); - - if (epochsPoolRewarded.length > 0) { - if (epochsPoolRewarded.length > 1) { - const reversedEpochsPoolRewarded = [...epochsPoolRewarded].reverse(); - const currentEpoch = (await stakingHbbftContract.stakingEpoch()).toNumber(); - if (reversedEpochsPoolRewarded[0] < currentEpoch) { - await stakingHbbftContract.connect(delegator).claimReward(reversedEpochsPoolRewarded, stakingAddress).should.be.rejectedWith("Claim: need strictly increasing order"); - } else { - await stakingHbbftContract.connect(delegator).claimReward([], stakingAddress).should.be.rejectedWith("Claim: only before current epoch"); - } - } - - await stakingHbbftContract.setStakingEpoch(epochsPoolRewarded[epochsPoolRewarded.length - 1]); - await stakingHbbftContract.connect(delegator).claimReward([], stakingAddress).should.be.rejectedWith("Claim: only before current epoch"); - await stakingHbbftContract.setStakingEpoch(epochsPoolRewarded[epochsPoolRewarded.length - 1] + 1); - - if (epochsPoolRewarded.length == 1) { - const validatorStakeAmount = await blockRewardContract.snapshotPoolValidatorStakeAmount(epochsPoolRewarded[0], miningAddress); - await blockRewardContract.setSnapshotPoolValidatorStakeAmount(epochsPoolRewarded[0], miningAddress, 0); - const result = await stakingHbbftContract.connect(delegator).claimReward([], stakingAddress); - const receipt = await result.wait(); - receipt.events?.length.should.be.equal(1); - receipt.events?.[0].args?.nativeCoinsAmount.should.be.equal(BigNumber.from(0)); - await blockRewardContract.setSnapshotPoolValidatorStakeAmount(epochsPoolRewarded[0], miningAddress, validatorStakeAmount); - await stakingHbbftContract.clearRewardWasTaken(stakingAddress, delegator.address, epochsPoolRewarded[0]); - } - } - //staked half the amount, hence .div(2) - const delegatorRewardExpected = epochPoolReward.mul(BigNumber.from(epochsPoolRewarded.length)).div(BigNumber.from(2)); - - const rewardAmountsCalculated = await stakingHbbftContract.getRewardAmount([], stakingAddress, delegator.address); - rewardAmountsCalculated.should.be.equal(delegatorRewardExpected); - - const delegatorCoinsBalanceBefore = BigNumber.from(await ethers.provider.getBalance(delegator.address)); - let weiSpent = BigNumber.from(0); - for (let i = 0; i < 3; i++) { - // We call `claimReward` several times, but it withdraws the reward only once - const result = await stakingHbbftContract.connect(delegator).claimReward([], stakingAddress); - const receipt = await result.wait(); - weiSpent = weiSpent.add((BigNumber.from(receipt.gasUsed)).mul(BigNumber.from(result.gasPrice))); - } - const delegatorCoinsBalanceAfter = BigNumber.from(await ethers.provider.getBalance(delegator.address)); - - delegatorCoinsBalanceAfter.should.be.equal(delegatorCoinsBalanceBefore.add(delegatorRewardExpected).sub(weiSpent)); - - for (let i = 0; i < 3; i++) { - // We call `claimReward` several times, but it withdraws the reward only once - const result = await stakingHbbftContract.connect(await ethers.getSigner(stakingAddress)).claimReward([], stakingAddress); - const receipt = await result.wait(); - if (i == 0) { - receipt.events?.length.should.be.equal(epochsPoolRewarded.length); - } else { - receipt.events?.length.should.be.equal(0); - } - } - (BigNumber.from(await ethers.provider.getBalance(blockRewardContract.address))).should.be.equal(deltaPotFillupValue); - } - - it('reward tries to be withdrawn before first stake', async () => { - const { - miningAddress, - stakingAddress, - } = await _delegatorNeverStakedBefore(); - - //const deltaPotFillupValue = BigNumber.from(web3.eth.toWei(60)); - //await blockRewardHbbft.addToDeltaPot({value: deltaPotFillupValue}); - - // a fake epoch reward. - const epochPoolReward = '1000'; - - // Emulate snapshotting and rewards for the pool on the epoch #9 - let stakingEpoch = 9; - await blockRewardContract.snapshotPoolStakeAmounts(stakingHbbftContract.address, stakingEpoch, miningAddress); - await blockRewardContract.setEpochPoolReward(stakingEpoch, miningAddress, { value: epochPoolReward }); - (await blockRewardContract.epochPoolNativeReward(stakingEpoch, miningAddress)).should.be.equal(epochPoolReward); - await blockRewardContract.snapshotPoolStakeAmounts(stakingHbbftContract.address, stakingEpoch + 1, miningAddress); - - // Emulate the delegator's first stake on epoch #10 - stakingEpoch = 10; - - await stakingHbbftContract.setStakingEpoch(stakingEpoch); - await stakingHbbftContract.setValidatorMockSetAddress(owner.address); - //await stakingHbbft.setStakingEpochStartBlock(startBlock); - await stakingHbbftContract.setValidatorMockSetAddress(validatorSetContract.address); - - await stakingHbbftContract.connect(delegator).stake(stakingAddress, { value: delegatorMinStake }); - await blockRewardContract.setEpochPoolReward(stakingEpoch, miningAddress, { value: epochPoolReward }); - (await blockRewardContract.epochPoolNativeReward(stakingEpoch, miningAddress)).should.be.equal(epochPoolReward); - await blockRewardContract.snapshotPoolStakeAmounts(stakingHbbftContract.address, stakingEpoch + 1, miningAddress); - - // // Emulate rewards for the pool on epoch #11 - stakingEpoch = 11; - await stakingHbbftContract.setStakingEpoch(stakingEpoch); - await blockRewardContract.setEpochPoolReward(stakingEpoch, miningAddress, { value: epochPoolReward }); - (await blockRewardContract.epochPoolNativeReward(stakingEpoch, miningAddress)).should.be.equal(epochPoolReward); - await blockRewardContract.snapshotPoolStakeAmounts(stakingHbbftContract.address, stakingEpoch + 1, miningAddress); - - await stakingHbbftContract.setStakingEpoch(12); - - const rewardAmountsCalculated = await stakingHbbftContract.getRewardAmount([9, 10], stakingAddress, delegator.address); - rewardAmountsCalculated.should.be.equal(BigNumber.from(0)); - - const delegatorCoinsBalanceBefore = BigNumber.from(await ethers.provider.getBalance(delegator.address)); - let result = await stakingHbbftContract.connect(delegator).claimReward([9, 10], stakingAddress); - let receipt = await result.wait(); - const weiSpent = (BigNumber.from(receipt.gasUsed)).mul(BigNumber.from(result.gasPrice)); - const delegatorCoinsBalanceAfter = BigNumber.from(await ethers.provider.getBalance(delegator.address)); - - receipt.events?.length.should.be.equal(0); - delegatorCoinsBalanceAfter.should.be.equal(delegatorCoinsBalanceBefore.sub(weiSpent)); - - const unclaimedEpochs = await blockRewardContract.epochsPoolGotRewardFor(miningAddress); - - result = await stakingHbbftContract.connect(await ethers.getSigner(stakingAddress)).claimReward([], stakingAddress); - receipt = await result.wait(); - //console.log('rewards for ', stakingAddress); - //console.log(result); - receipt.events?.length.should.be.equal(5); - receipt.events?.[0].args?.stakingEpoch.should.be.equal(BigNumber.from(1)); - receipt.events?.[1].args?.stakingEpoch.should.be.equal(BigNumber.from(2)); - receipt.events?.[2].args?.stakingEpoch.should.be.equal(BigNumber.from(9)); - receipt.events?.[3].args?.stakingEpoch.should.be.equal(BigNumber.from(10)); - receipt.events?.[4].args?.stakingEpoch.should.be.equal(BigNumber.from(11)); - - result = await stakingHbbftContract.connect(delegator).claimReward([], stakingAddress); - receipt = await result.wait(); - receipt.events?.length.should.be.equal(1); - receipt.events?.[0].args?.stakingEpoch.should.be.equal(BigNumber.from(11)); - - (await stakingHbbftContract.stakeFirstEpoch(stakingAddress, delegator.address)).should.be.equal(BigNumber.from(11)); - (await stakingHbbftContract.stakeLastEpoch(stakingAddress, delegator.address)).should.be.equal(BigNumber.from(0)); - }); - - it('delegator stakes and withdraws at the same epoch', async () => { - const { - miningAddress, - stakingAddress - } = await _delegatorNeverStakedBefore(); - - const epochPoolReward = '1000'; - - // Emulate snapshotting and rewards for the pool on the epoch #9 - let stakingEpoch = 9; - await blockRewardContract.snapshotPoolStakeAmounts(stakingHbbftContract.address, stakingEpoch, miningAddress); - await blockRewardContract.setEpochPoolReward(stakingEpoch, miningAddress, { value: epochPoolReward }); - (await blockRewardContract.epochPoolNativeReward(stakingEpoch, miningAddress)).should.be.equal(epochPoolReward); - await blockRewardContract.snapshotPoolStakeAmounts(stakingHbbftContract.address, stakingEpoch + 1, miningAddress); - - // Emulate the delegator's first stake and withdrawal on epoch #10 - stakingEpoch = 10; - const startBlock = BigNumber.from(120954 * stakingEpoch + 1); - await stakingHbbftContract.setStakingEpoch(stakingEpoch); - await stakingHbbftContract.setValidatorMockSetAddress(owner.address); - //await stakingHbbftContract.setStakingEpochStartBlock(startBlock); - await stakingHbbftContract.setValidatorMockSetAddress(validatorSetContract.address); - - await stakingHbbftContract.connect(delegator).stake(stakingAddress, { value: delegatorMinStake }); - await stakingHbbftContract.connect(delegator).withdraw(stakingAddress, delegatorMinStake); - await blockRewardContract.setEpochPoolReward(stakingEpoch, miningAddress, { value: epochPoolReward }); - await blockRewardContract.snapshotPoolStakeAmounts(stakingHbbftContract.address, stakingEpoch + 1, miningAddress); - - // Emulate rewards for the pool on epoch #11 - stakingEpoch = 11; - await blockRewardContract.setEpochPoolReward(stakingEpoch, miningAddress, { value: epochPoolReward }); - await blockRewardContract.snapshotPoolStakeAmounts(stakingHbbftContract.address, stakingEpoch + 1, miningAddress); - - await stakingHbbftContract.setStakingEpoch(12); - - const rewardAmountsCalculated = await stakingHbbftContract.getRewardAmount([], stakingAddress, delegator.address); - rewardAmountsCalculated.should.be.equal(BigNumber.from(0)); - - - const delegatorCoinsBalanceBefore = BigNumber.from(await ethers.provider.getBalance(delegator.address)); - let result = await stakingHbbftContract.connect(delegator).claimReward([], stakingAddress); - let receipt = await result.wait(); - const weiSpent = (BigNumber.from(receipt.gasUsed)).mul(BigNumber.from(result.gasPrice)); - const delegatorCoinsBalanceAfter = BigNumber.from(await ethers.provider.getBalance(delegator.address)); - - receipt.events?.length.should.be.equal(0); - delegatorCoinsBalanceAfter.should.be.equal(delegatorCoinsBalanceBefore.sub(weiSpent)); - - result = await stakingHbbftContract.connect(await ethers.getSigner(stakingAddress)).claimReward([], stakingAddress); - receipt = await result.wait(); - receipt.events?.length.should.be.equal(5); - receipt.events?.[0].args?.stakingEpoch.should.be.equal(BigNumber.from(1)); - receipt.events?.[1].args?.stakingEpoch.should.be.equal(BigNumber.from(2)); - receipt.events?.[2].args?.stakingEpoch.should.be.equal(BigNumber.from(9)); - receipt.events?.[3].args?.stakingEpoch.should.be.equal(BigNumber.from(10)); - receipt.events?.[4].args?.stakingEpoch.should.be.equal(BigNumber.from(11)); - - (await stakingHbbftContract.stakeFirstEpoch(stakingAddress, delegator.address)).should.be.equal(BigNumber.from(11)); - (await stakingHbbftContract.stakeLastEpoch(stakingAddress, delegator.address)).should.be.equal(BigNumber.from(11)); - }); - - it('non-rewarded epochs are passed', async () => { - const miningAddress = initialValidators[0]; - const stakingAddress = initialStakingAddresses[0]; - const epochPoolReward = BigNumber.from(ethers.utils.parseEther('1')); - - const epochsPoolRewarded = [10, 20, 30, 40, 50]; - for (let i = 0; i < epochsPoolRewarded.length; i++) { - const stakingEpoch = epochsPoolRewarded[i]; - - // Emulate snapshotting for the pool - await blockRewardContract.snapshotPoolStakeAmounts(stakingHbbftContract.address, stakingEpoch, miningAddress); - - // Emulate rewards for the pool - await blockRewardContract.setEpochPoolReward(stakingEpoch, miningAddress, { value: epochPoolReward }); - } - // initial validator got reward for epochs: [10, 20, 30, 40, 50] - (await blockRewardContract.epochsPoolGotRewardFor(miningAddress)).length.should.be.equal(5); - - await stakingHbbftContract.setStakingEpoch(51); - - const epochsToWithdrawFrom = [15, 25, 35, 45]; - const delegatorCoinsBalanceBefore = BigNumber.from(await ethers.provider.getBalance(delegator.address)); - const result = await stakingHbbftContract.connect(delegator).claimReward(epochsToWithdrawFrom, stakingAddress); - const receipt = await result.wait(); - const weiSpent = (BigNumber.from(receipt.gasUsed)).mul(BigNumber.from(result.gasPrice)); - const delegatorCoinsBalanceAfter = BigNumber.from(await ethers.provider.getBalance(delegator.address)); - - receipt.events?.length.should.be.equal(epochsToWithdrawFrom.length); - for (let i = 0; i < epochsToWithdrawFrom.length; i++) { - receipt.events?.[i].args?.stakingEpoch.should.be.equal(BigNumber.from(epochsToWithdrawFrom[i])); - receipt.events?.[i].args?.nativeCoinsAmount.should.be.equal(BigNumber.from(0)); - } - - delegatorCoinsBalanceAfter.should.be.equal(delegatorCoinsBalanceBefore.sub(weiSpent)); - }); - - it('stake movements 1', async () => { - await testClaimRewardAfterStakeMovements( - [5, 15, 25, 35], - [10, 20, 30] - ); - }); - - it('stake movements 2', async () => { - await testClaimRewardAfterStakeMovements( - [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], - [1, 2, 3, 4, 5, 6, 7, 8, 9] - ); - }); - - it('stake movements 3', async () => { - await testClaimRewardAfterStakeMovements( - [1, 3, 6, 10], - [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13] - ); - }); - - it('stake movements 4', async () => { - await testClaimRewardAfterStakeMovements( - [], - [1, 2, 3] - ); - }); - - it('stake movements 5', async () => { - await testClaimRewardAfterStakeMovements( - [2], - [1, 2, 3] - ); - }); - - it('stake increasing 1', async () => { - await testClaimRewardAfterStakeIncreasing( - [5, 15, 25, 35], - [4, 14, 24, 34] - ); - }); - - it('stake increasing 2', async () => { - await testClaimRewardAfterStakeIncreasing( - [5, 15, 25, 35], - [10, 20, 30] - ); - }); - - it('stake increasing 3', async () => { - await testClaimRewardAfterStakeIncreasing( - [1, 2, 3, 4, 5, 6], - [1, 2, 3, 4, 5] - ); - }); - - it('stake increasing 4', async () => { - await testClaimRewardAfterStakeIncreasing( - [1, 3, 6, 10], - [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13] - ); - }); - - it('stake increasing 5', async () => { - await testClaimRewardAfterStakeIncreasing( - [5, 15, 25], - [5, 15, 25] - ); - }); - - it('stake increasing', async () => { - await testClaimRewardAfterStakeIncreasing( - [5, 7, 9], - [6, 8, 10] - ); - }); - - it('random withdrawal 1', async () => { - await testClaimRewardRandom( - [5, 15, 25, 35], - [4, 14, 24, 34] - ); - }); - - it('random withdrawal 2', async () => { - await testClaimRewardRandom( - [5, 15, 25, 35], - [10, 20, 30] - ); - }); - - it('random withdrawal 3', async () => { - await testClaimRewardRandom( - [1, 2, 3, 4, 5, 6], - [1, 2, 3, 4, 5] - ); - }); - - it('random withdrawal 4', async () => { - await testClaimRewardRandom( - [1, 3, 6, 10], - [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13] - ); - }); - - it('random withdrawal 5', async () => { - await testClaimRewardRandom( - [5, 15, 25], - [5, 15, 25] - ); - }); - - it('random withdrawal 6', async () => { - await testClaimRewardRandom( - [5, 7, 9], - [6, 8, 10] - ); - }); - - it('reward got from the first epoch', async () => { - await testClaimRewardAfterStakeMovements([1], []); - }); - - it('stake is withdrawn forever 1', async () => { - const miningAddress = initialValidators[0]; - const stakingAddress = initialStakingAddresses[0]; - const epochPoolReward = BigNumber.from(ethers.utils.parseEther('1')); - - (await ethers.provider.getBalance(blockRewardContract.address)).should.be.equal('0'); - - let stakingEpoch; - - // Emulate snapshotting and rewards for the pool - stakingEpoch = 9; - await blockRewardContract.snapshotPoolStakeAmounts(stakingHbbftContract.address, stakingEpoch, miningAddress); - await blockRewardContract.setEpochPoolReward(stakingEpoch, miningAddress, { value: epochPoolReward }); - (BigNumber.from(await ethers.provider.getBalance(blockRewardContract.address))).should.be.equal(epochPoolReward); - await blockRewardContract.snapshotPoolStakeAmounts(stakingHbbftContract.address, stakingEpoch + 1, miningAddress); - - // Emulate delegator's stake withdrawal - stakingEpoch = 10; - //const stakingEpochStartBlock = BigNumber.from(120954 * stakingEpoch + 1); - await stakingHbbftContract.setStakingEpoch(stakingEpoch); - await stakingHbbftContract.setValidatorMockSetAddress(owner.address); - //await stakingHbbft.setStakingEpochStartBlock(stakingEpochStartBlock); - await stakingHbbftContract.setValidatorMockSetAddress(validatorSetContract.address); - - await stakingHbbftContract.connect(delegator).orderWithdraw(stakingAddress, delegatorMinStake); - await blockRewardContract.setEpochPoolReward(stakingEpoch, miningAddress, { value: epochPoolReward }); - (BigNumber.from(await ethers.provider.getBalance(blockRewardContract.address))).should.be.equal(epochPoolReward.mul(BigNumber.from(2))); - await blockRewardContract.snapshotPoolStakeAmounts(stakingHbbftContract.address, stakingEpoch + 1, miningAddress); - - // Emulate rewards for the pool - stakingEpoch = 11; - await blockRewardContract.setEpochPoolReward(stakingEpoch, miningAddress, { value: epochPoolReward }); - (BigNumber.from(await ethers.provider.getBalance(blockRewardContract.address))).should.be.equal(epochPoolReward.mul(BigNumber.from(3))); - await blockRewardContract.snapshotPoolStakeAmounts(stakingHbbftContract.address, stakingEpoch + 1, miningAddress); - - await stakingHbbftContract.setStakingEpoch(12); - - const delegatorRewardExpected = epochPoolReward.mul(BigNumber.from(2)).div(BigNumber.from(2)); - - const rewardAmountsCalculated = await stakingHbbftContract.getRewardAmount([], stakingAddress, delegator.address); - rewardAmountsCalculated.should.be.equal(delegatorRewardExpected); - - const delegatorCoinsBalanceBefore = BigNumber.from(await ethers.provider.getBalance(delegator.address)); - let result = await stakingHbbftContract.connect(delegator).claimReward([], stakingAddress); - let receipt = await result.wait(); - const weiSpent = (BigNumber.from(receipt.gasUsed)).mul(BigNumber.from(result.gasPrice)); - const delegatorCoinsBalanceAfter = BigNumber.from(await ethers.provider.getBalance(delegator.address)); - - receipt.events?.length.should.be.equal(2); - receipt.events?.[0].event?.should.be.equal("ClaimedReward"); - receipt.events?.[0].args?.stakingEpoch.should.be.equal(BigNumber.from(9)); - receipt.events?.[0].args?.nativeCoinsAmount.should.be.equal(epochPoolReward.div(BigNumber.from(2))); - receipt.events?.[1].event?.should.be.equal("ClaimedReward"); - receipt.events?.[1].args?.stakingEpoch.should.be.equal(BigNumber.from(10)); - receipt.events?.[1].args?.nativeCoinsAmount.should.be.equal(epochPoolReward.div(BigNumber.from(2))); - - delegatorCoinsBalanceAfter.should.be.equal(delegatorCoinsBalanceBefore.add(delegatorRewardExpected).sub(weiSpent)); - - result = await stakingHbbftContract.connect(await ethers.getSigner(stakingAddress)).claimReward([], stakingAddress); - receipt = await result.wait(); - receipt.events?.length.should.be.equal(3); - receipt.events?.[0].args?.stakingEpoch.should.be.equal(BigNumber.from(9)); - receipt.events?.[1].args?.stakingEpoch.should.be.equal(BigNumber.from(10)); - receipt.events?.[2].args?.stakingEpoch.should.be.equal(BigNumber.from(11)); - (BigNumber.from(await ethers.provider.getBalance(blockRewardContract.address))).should.be.equal(BigNumber.from(0)); - }); - - it('stake is withdrawn forever 2', async () => { - const miningAddress = initialValidators[0]; - const stakingAddress = initialStakingAddresses[0]; - const epochPoolReward = BigNumber.from(ethers.utils.parseEther('1')); - - (await ethers.provider.getBalance(blockRewardContract.address)).should.be.equal('0'); - - let stakingEpoch; - - // Emulate snapshotting and rewards for the pool - stakingEpoch = 9; - await blockRewardContract.snapshotPoolStakeAmounts(stakingHbbftContract.address, stakingEpoch, miningAddress); - await blockRewardContract.setEpochPoolReward(stakingEpoch, miningAddress, { value: epochPoolReward }); - (BigNumber.from(await ethers.provider.getBalance(blockRewardContract.address))).should.be.equal(epochPoolReward); - await blockRewardContract.snapshotPoolStakeAmounts(stakingHbbftContract.address, stakingEpoch + 1, miningAddress); - - // Emulate delegator's stake withdrawal - stakingEpoch = 10; - //const stakingEpochStartBlock = BigNumber.from(120954 * stakingEpoch + 1); - await stakingHbbftContract.setStakingEpoch(stakingEpoch); - await stakingHbbftContract.setValidatorMockSetAddress(owner.address); - //await stakingHbbft.setStakingEpochStartBlock(stakingEpochStartBlock); - await stakingHbbftContract.setValidatorMockSetAddress(validatorSetContract.address); - - await stakingHbbftContract.connect(delegator).orderWithdraw(stakingAddress, delegatorMinStake); - await blockRewardContract.setEpochPoolReward(stakingEpoch, miningAddress, { value: epochPoolReward }); - (BigNumber.from(await ethers.provider.getBalance(blockRewardContract.address))).should.be.equal(epochPoolReward.mul(BigNumber.from(2))); - await blockRewardContract.snapshotPoolStakeAmounts(stakingHbbftContract.address, stakingEpoch + 1, miningAddress); - - // Emulate rewards for the pool - stakingEpoch = 11; - await blockRewardContract.setEpochPoolReward(stakingEpoch, miningAddress, { value: epochPoolReward }); - (BigNumber.from(await ethers.provider.getBalance(blockRewardContract.address))).should.be.equal(epochPoolReward.mul(BigNumber.from(3))); - await blockRewardContract.snapshotPoolStakeAmounts(stakingHbbftContract.address, stakingEpoch + 1, miningAddress); - - await stakingHbbftContract.setStakingEpoch(12); - - const rewardAmountsCalculated = await stakingHbbftContract.getRewardAmount([11], stakingAddress, delegator.address); - rewardAmountsCalculated.should.be.equal(BigNumber.from(0)); - - const delegatorCoinsBalanceBefore = BigNumber.from(await ethers.provider.getBalance(delegator.address)); - const result = await stakingHbbftContract.connect(delegator).claimReward([11], stakingAddress); - const receipt = await result.wait(); - const weiSpent = (BigNumber.from(receipt.gasUsed)).mul(BigNumber.from(result.gasPrice)); - const delegatorCoinsBalanceAfter = BigNumber.from(await ethers.provider.getBalance(delegator.address)); - - receipt.events?.length.should.be.equal(0); - delegatorCoinsBalanceAfter.should.be.equal(delegatorCoinsBalanceBefore.sub(weiSpent)); - }); - - it('gas consumption for one staking epoch is OK', async () => { - const stakingEpoch = 2600; - - await blockRewardContract.addToDeltaPot({ value: deltaPotFillupValue }); - - for (let i = 0; i < initialValidators.length; i++) { - await blockRewardContract.snapshotPoolStakeAmounts(stakingHbbftContract.address, stakingEpoch, initialValidators[i]); - } - - await stakingHbbftContract.setStakingEpoch(stakingEpoch - 1); - - await stakingHbbftContract.setValidatorMockSetAddress(owner.address); - //await stakingHbbftContract.setStakingEpochStartBlock(epochStartBlock); - await stakingHbbftContract.setValidatorMockSetAddress(validatorSetContract.address); - // new validatorSet at the end of fixed epoch duration - - await timeTravelToTransition(blockRewardContract, stakingHbbftContract); - await timeTravelToEndEpoch(blockRewardContract, stakingHbbftContract); - - (await validatorSetContract.getValidators()).should.be.deep.equal(initialValidators); - (await stakingHbbftContract.stakingEpoch()).should.be.equal(BigNumber.from(stakingEpoch)); - - - let blockRewardCoinsBalanceBefore = BigNumber.from(await ethers.provider.getBalance(blockRewardContract.address)); - - for (let i = 0; i < initialValidators.length; i++) { - (await blockRewardContract.epochPoolNativeReward(stakingEpoch, initialValidators[i])).should.be.equal(BigNumber.from(0)); - } - - await timeTravelToTransition(blockRewardContract, stakingHbbftContract); - await timeTravelToEndEpoch(blockRewardContract, stakingHbbftContract); - - (await stakingHbbftContract.stakingEpoch()).should.be.equal(BigNumber.from(stakingEpoch + 1)); - //epochStartBlock = await stakingHbbftContract.stakingEpochStartBlock(); - //epochStartBlock.should.be.equal(BigNumber.from(120954 * (stakingEpoch + 1) + 2 + 2 + 1)); // +2 for kegen duration - - let distributedCoinsAmount = BigNumber.from(0); - for (let i = 0; i < initialValidators.length; i++) { - const epochPoolNativeReward = await blockRewardContract.epochPoolNativeReward(stakingEpoch, initialValidators[i]); - epochPoolNativeReward.should.be.above(BigNumber.from(0)); - distributedCoinsAmount = distributedCoinsAmount.add(epochPoolNativeReward); - } - - // const blockRewardContract.maintenanceFundAddress(); - // console.log('DAO Coin amount'); - // distributedCoinsAmount - - let blockRewardCoinsBalanceAfter = BigNumber.from(await ethers.provider.getBalance(blockRewardContract.address)); - blockRewardCoinsBalanceAfter.should.be.equal(blockRewardCoinsBalanceBefore.add(distributedCoinsAmount)); - - // The delegator claims their rewards - const delegatorCoinsBalanceBefore = BigNumber.from(await ethers.provider.getBalance(delegator.address)); - - blockRewardCoinsBalanceBefore = BigNumber.from(await ethers.provider.getBalance(blockRewardContract.address)); - - const expectedClaimRewardAmounts = (await stakingHbbftContract.getRewardAmount([stakingEpoch], initialStakingAddresses[0], delegator.address)); - - const result = await stakingHbbftContract.connect(delegator).claimReward([stakingEpoch], initialStakingAddresses[0]); - - let receipt = await result.wait(); - - receipt.events?.[0].event?.should.be.equal("ClaimedReward"); - receipt.events?.[0].args?.fromPoolStakingAddress.should.be.equal(initialStakingAddresses[0]); - receipt.events?.[0].args?.staker.should.be.equal(delegator.address); - receipt.events?.[0].args?.stakingEpoch.should.be.equal(BigNumber.from(stakingEpoch)); - - const claimedCoinsAmount = receipt.events?.[0].args?.nativeCoinsAmount; - expectedClaimRewardAmounts.should.be.equal(claimedCoinsAmount); - - const weiSpent = (BigNumber.from(receipt.gasUsed)).mul(BigNumber.from(result.gasPrice)); - - if (!!process.env.SOLIDITY_COVERAGE !== true) { - // receipt.gasUsed.should.be.below(1700000); - receipt.gasUsed.should.be.below(3120000); // for Istanbul - } - - const delegatorCoinsBalanceAfter = BigNumber.from(await ethers.provider.getBalance(delegator.address)); - blockRewardCoinsBalanceAfter = BigNumber.from(await ethers.provider.getBalance(blockRewardContract.address)); - delegatorCoinsBalanceAfter.should.be.equal(delegatorCoinsBalanceBefore.add(claimedCoinsAmount).sub(weiSpent)); - blockRewardCoinsBalanceAfter.should.be.equal(blockRewardCoinsBalanceBefore.sub(claimedCoinsAmount)); - }); - - it('gas consumption for 20 staking epochs is OK', async () => { - const maxStakingEpoch = 20; - maxStakingEpoch.should.be.above(2); - - await blockRewardContract.addToDeltaPot({ value: deltaPotFillupValue }); - - // Loop of staking epochs - for (let stakingEpoch = 1; stakingEpoch <= maxStakingEpoch; stakingEpoch++) { - // Finalize change i.e. finalize pending validators, increase epoch and set stakingEpochStartBlock - if (stakingEpoch == 1) { - await stakingHbbftContract.setStakingEpoch(1); - - await stakingHbbftContract.setValidatorMockSetAddress(owner.address); - //await stakingHbbftContract.setStakingEpochStartBlock(startBlock); - await stakingHbbftContract.setValidatorMockSetAddress(validatorSetContract.address); - } - - (await validatorSetContract.getValidators()).should.be.deep.equal(initialValidators); - (await stakingHbbftContract.stakingEpoch()).should.be.equal(BigNumber.from(stakingEpoch)); - - // await timeTravelToTransition(validatorSetContract, blockRewardContract, stakingHbbftContract); - // await timeTravelToEndEpoch(validatorSetContract, blockRewardContract, stakingHbbftContract); - - const blockRewardCoinsBalanceBefore = BigNumber.from(await ethers.provider.getBalance(blockRewardContract.address)); - for (let i = 0; i < initialValidators.length; i++) { - (await blockRewardContract.epochPoolNativeReward(stakingEpoch, initialValidators[i])).should.be.equal(BigNumber.from(0)); - } - - await timeTravelToTransition(blockRewardContract, stakingHbbftContract); - await timeTravelToEndEpoch(blockRewardContract, stakingHbbftContract); + const { stakingHbbft } = await helpers.loadFixture(deployContractsFixture); - let distributedCoinsAmount = BigNumber.from(0); - for (let i = 0; i < initialValidators.length; i++) { - const epochPoolNativeReward = await blockRewardContract.epochPoolNativeReward(stakingEpoch, initialValidators[i]); - epochPoolNativeReward.should.be.above(BigNumber.from(0)); - distributedCoinsAmount = distributedCoinsAmount.add(epochPoolNativeReward); - } - const blockRewardCoinsBalanceAfter = BigNumber.from(await ethers.provider.getBalance(blockRewardContract.address)); - blockRewardCoinsBalanceAfter.should.be.equal(blockRewardCoinsBalanceBefore.add(distributedCoinsAmount)); + for (let i = 0; i < initialStakingAddresses.length; i++) { + expect(await stakingHbbft.getPoolPublicKey(initialStakingAddresses[i])) + .to.be.equal(initialValidatorsPubKeys[i]); } + }); - // The delegator claims their rewards - let initialGasConsumption = BigNumber.from(0); - let startGasConsumption = BigNumber.from(0); - let endGasConsumption = BigNumber.from(0); - let blockRewardCoinsBalanceTotalBefore = BigNumber.from(await ethers.provider.getBalance(blockRewardContract.address)); - - let coinsDelegatorGotForAllEpochs = BigNumber.from(0); - for (let stakingEpoch = 1; stakingEpoch <= maxStakingEpoch; stakingEpoch++) { - const delegatorCoinsBalanceBefore = BigNumber.from(await ethers.provider.getBalance(delegator.address)); + it('should set the corresponding IP addresses', async () => { + const { stakingHbbft } = await helpers.loadFixture(deployContractsFixture); - const blockRewardCoinsBalanceBefore = BigNumber.from(await ethers.provider.getBalance(blockRewardContract.address)); + for (let i = 0; i < initialStakingAddresses.length; i++) { + let ip_result = (await stakingHbbft.getPoolInternetAddress(initialStakingAddresses[i])); + expect(ip_result[0]).to.be.equal(initialValidatorsIpAddresses[i]); + } + }); - const expectedClaimRewardAmounts = (await stakingHbbftContract.getRewardAmount([stakingEpoch], initialStakingAddresses[0], delegator.address)); + it('should create a new pool', async () => { + const { stakingHbbft } = await helpers.loadFixture(deployContractsFixture); - let result = await stakingHbbftContract.connect(delegator).claimReward([stakingEpoch], initialStakingAddresses[0]); - let receipt = await result.wait(); - receipt.events?.[0].event?.should.be.equal("ClaimedReward"); - receipt.events?.[0].args?.fromPoolStakingAddress.should.be.equal(initialStakingAddresses[0]); - receipt.events?.[0].args?.staker.should.be.equal(delegator.address); - receipt.events?.[0].args?.stakingEpoch.should.be.equal(BigNumber.from(stakingEpoch)); + expect(await stakingHbbft.isPoolActive(candidateStakingAddress.address)).to.be.false; - const claimedCoinsAmount = receipt.events?.[0].args?.nativeCoinsAmount; + await stakingHbbft.connect(candidateStakingAddress).addPool( + candidateMiningAddress.address, + ZeroPublicKey, + ZeroIpAddress, + { value: minStake } + ); - expectedClaimRewardAmounts.should.be.equal(claimedCoinsAmount); + expect(await stakingHbbft.isPoolActive(candidateStakingAddress.address)).to.be.true; + }); - receipt = await result.wait(); - const weiSpent = (BigNumber.from(receipt.gasUsed)).mul(BigNumber.from(result.gasPrice)); + it('should fail if created with overstaked pool', async () => { + const { stakingHbbft } = await helpers.loadFixture(deployContractsFixture); - if (stakingEpoch == 1) { - initialGasConsumption = BigNumber.from(receipt.gasUsed); - } else if (stakingEpoch == 2) { - startGasConsumption = BigNumber.from(receipt.gasUsed); - } else if (stakingEpoch == maxStakingEpoch) { - endGasConsumption = BigNumber.from(receipt.gasUsed); - } + expect(await stakingHbbft.isPoolActive(candidateStakingAddress.address)).to.be.false; - const delegatorCoinsBalanceAfter = BigNumber.from(await ethers.provider.getBalance(delegator.address)); - const blockRewardCoinsBalanceAfter = BigNumber.from(await ethers.provider.getBalance(blockRewardContract.address)); - delegatorCoinsBalanceAfter.should.be.equal(delegatorCoinsBalanceBefore.add(claimedCoinsAmount).sub(weiSpent)); - blockRewardCoinsBalanceAfter.should.be.equal(blockRewardCoinsBalanceBefore.sub(claimedCoinsAmount)); + await expect(stakingHbbft.connect(candidateStakingAddress).addPool( + candidateMiningAddress.address, + ZeroPublicKey, + ZeroIpAddress, + { value: maxStake + minStake } + )).to.be.revertedWith('stake limit has been exceeded'); + }); - coinsDelegatorGotForAllEpochs = coinsDelegatorGotForAllEpochs.add(claimedCoinsAmount); + it('should fail if mining address is 0', async () => { + const { stakingHbbft } = await helpers.loadFixture(deployContractsFixture); - // console.log(`stakingEpoch = ${stakingEpoch}, gasUsed = ${receipt.gasUsed}, cumulativeGasUsed = ${receipt.cumulativeGasUsed}`); - } + await expect(stakingHbbft.connect(candidateStakingAddress).addPool( + ethers.ZeroAddress, + ZeroPublicKey, + ZeroIpAddress, + { value: minStake } + )).to.be.revertedWith("Mining address can't be 0"); + }); - if (!!process.env.SOLIDITY_COVERAGE !== true) { - const perEpochGasConsumption = endGasConsumption.sub(startGasConsumption).div(BigNumber.from(maxStakingEpoch - 2)); - // perEpochGasConsumption.should.be.equal(BigNumber.from(509)); - perEpochGasConsumption.should.be.equal(BigNumber.from(1159)); // for Istanbul + it('should fail if mining address is equal to staking', async () => { + const { stakingHbbft } = await helpers.loadFixture(deployContractsFixture); - // Check gas consumption for the case when the delegator didn't touch their - // stake for 50 years (2600 staking epochs) - const maxGasConsumption = initialGasConsumption.sub(perEpochGasConsumption).add(perEpochGasConsumption.mul(BigNumber.from(2600))); - // maxGasConsumption.should.be.below(BigNumber.from(1700000)); - maxGasConsumption.should.be.below(BigNumber.from(3120000)); // for Istanbul - } + await expect(stakingHbbft.connect(candidateStakingAddress).addPool( + candidateStakingAddress.address, + ZeroPublicKey, + ZeroIpAddress, + { value: minStake } + )).to.be.revertedWith("Mining address cannot be the same as the staking one"); + }); - let blockRewardCoinsBalanceTotalAfter = BigNumber.from(await ethers.provider.getBalance(blockRewardContract.address)); + it('should fail if the pool with the same mining/staking address is already existing', async () => { + const { stakingHbbft } = await helpers.loadFixture(deployContractsFixture); - blockRewardCoinsBalanceTotalAfter.should.be.equal(blockRewardCoinsBalanceTotalBefore.sub(coinsDelegatorGotForAllEpochs)); + const candidateMiningAddress2 = accounts[9]; + const candidateStakingAddress2 = accounts[10]; - // The validators claim their rewards - let coinsValidatorsGotForAllEpochs = BigNumber.from(0); - for (let v = 0; v < initialStakingAddresses.length; v++) { - for (let stakingEpoch = 1; stakingEpoch <= maxStakingEpoch; stakingEpoch++) { - const validator = initialStakingAddresses[v]; - const validatorCoinsBalanceBefore = BigNumber.from(await ethers.provider.getBalance(validator)); - const blockRewardCoinsBalanceBefore = BigNumber.from(await ethers.provider.getBalance(blockRewardContract.address)); + await stakingHbbft.connect(candidateStakingAddress).addPool( + candidateMiningAddress.address, + ZeroPublicKey, + ZeroIpAddress, + { value: minStake } + ); - const expectedClaimRewardAmounts = (await stakingHbbftContract.getRewardAmount([stakingEpoch], validator, validator)); + await expect(stakingHbbft.connect(candidateStakingAddress2).addPool( + candidateMiningAddress.address, + ZeroPublicKey, + ZeroIpAddress, + { value: minStake } + )).to.be.revertedWith("Mining address already used as a mining one"); - let result = await stakingHbbftContract.connect(await ethers.getSigner(validator)).claimReward([stakingEpoch], validator); - let receipt = await result.wait() - receipt.events?.[0].event?.should.be.equal("ClaimedReward"); - receipt.events?.[0].args?.fromPoolStakingAddress.should.be.equal(validator); - receipt.events?.[0].args?.staker.should.be.equal(validator); - receipt.events?.[0].args?.stakingEpoch.should.be.equal(BigNumber.from(stakingEpoch)); + await expect(stakingHbbft.connect(candidateStakingAddress).addPool( + candidateMiningAddress2.address, + ZeroPublicKey, + ZeroIpAddress, + { value: minStake } + )).to.be.revertedWith("Staking address already used as a staking one"); - const claimedCoinsAmount = receipt.events?.[0].args?.nativeCoinsAmount; + await expect(stakingHbbft.connect(candidateMiningAddress2).addPool( + candidateStakingAddress.address, + ZeroPublicKey, + ZeroIpAddress, + { value: minStake } + )).to.be.revertedWith("Mining address already used as a staking one"); - expectedClaimRewardAmounts.should.be.equal(claimedCoinsAmount); + await expect(stakingHbbft.connect(candidateMiningAddress).addPool( + candidateStakingAddress2.address, + ZeroPublicKey, + ZeroIpAddress, + { value: minStake } + )).to.be.revertedWith("Staking address already used as a mining one"); - receipt = await result.wait(); - const weiSpent = (BigNumber.from(receipt.gasUsed)).mul(BigNumber.from(result.gasPrice)); + await expect(stakingHbbft.connect(candidateMiningAddress2).addPool( + candidateMiningAddress.address, + ZeroPublicKey, + ZeroIpAddress, + { value: minStake } + )).to.be.revertedWith("Mining address already used as a mining one"); - const validatorCoinsBalanceAfter = BigNumber.from(await ethers.provider.getBalance(validator)); - const blockRewardCoinsBalanceAfter = BigNumber.from(await ethers.provider.getBalance(blockRewardContract.address)); + await expect(stakingHbbft.connect(candidateMiningAddress).addPool( + candidateMiningAddress2.address, + ZeroPublicKey, + ZeroIpAddress, + { value: minStake } + )).to.be.revertedWith("Staking address already used as a mining one"); - validatorCoinsBalanceAfter.should.be.equal(validatorCoinsBalanceBefore.add(claimedCoinsAmount).sub(weiSpent)); - blockRewardCoinsBalanceAfter.should.be.equal(blockRewardCoinsBalanceBefore.sub(claimedCoinsAmount)); + await expect(stakingHbbft.connect(candidateStakingAddress2).addPool( + candidateStakingAddress.address, + ZeroPublicKey, + ZeroIpAddress, + { value: minStake } + )).to.be.revertedWith("Mining address already used as a staking one"); - coinsValidatorsGotForAllEpochs = coinsValidatorsGotForAllEpochs.add(claimedCoinsAmount); - } - } + await expect(stakingHbbft.connect(candidateStakingAddress).addPool( + candidateStakingAddress2.address, + ZeroPublicKey, + ZeroIpAddress, + { value: minStake } + )).to.be.revertedWith("Staking address already used as a staking one"); - blockRewardCoinsBalanceTotalAfter = BigNumber.from(await ethers.provider.getBalance(blockRewardContract.address)); - blockRewardCoinsBalanceTotalAfter.should.be.equal(blockRewardCoinsBalanceTotalBefore.sub(coinsDelegatorGotForAllEpochs).sub(coinsValidatorsGotForAllEpochs)); - blockRewardCoinsBalanceTotalAfter.should.be.gte(BigNumber.from(0)); + expect(await stakingHbbft.connect(candidateStakingAddress2).addPool( + candidateMiningAddress2.address, + ZeroPublicKey, + ZeroIpAddress, + { value: minStake } + )); }); - it('gas consumption for 52 staking epochs is OK 1', async () => { - const maxStakingEpoch = 52; - - await blockRewardContract.addToDeltaPot({ value: deltaPotFillupValue }); + it('should fail if gasPrice is 0', async () => { + const { stakingHbbft } = await helpers.loadFixture(deployContractsFixture); - // Loop of staking epochs - for (let stakingEpoch = 1; stakingEpoch <= maxStakingEpoch; stakingEpoch++) { - if (stakingEpoch == 1) { - await stakingHbbftContract.setStakingEpoch(1); - //const startBlock = BigNumber.from(120954 + 2 + 1); + await expect(stakingHbbft.connect(candidateStakingAddress).addPool( + candidateMiningAddress.address, + ZeroPublicKey, + ZeroIpAddress, + { gasPrice: 0, value: minStake } + )).to.be.revertedWith("GasPrice is 0"); + }); - await stakingHbbftContract.setValidatorMockSetAddress(owner.address); - //await stakingHbbft.setStakingEpochStartBlock(startBlock); - await stakingHbbftContract.setValidatorMockSetAddress(validatorSetContract.address); - } + it('should fail if staking amount is 0', async () => { + const { stakingHbbft } = await helpers.loadFixture(deployContractsFixture); - (await validatorSetContract.getValidators()).should.be.deep.equal(initialValidators); - (await stakingHbbftContract.stakingEpoch()).should.be.equal(BigNumber.from(stakingEpoch)); + await expect(stakingHbbft.connect(candidateStakingAddress).addPool( + candidateMiningAddress.address, + ZeroPublicKey, + ZeroIpAddress, + { value: 0n } + )).to.be.revertedWith("Stake: stakingAmount is 0"); + }); - await callReward(blockRewardContract, false); + it.skip('should fail if stacking time is inside disallowed range', async () => { + const { stakingHbbft } = await helpers.loadFixture(deployContractsFixture); - const blockRewardCoinsBalanceBefore = BigNumber.from(await ethers.provider.getBalance(blockRewardContract.address)); - for (let i = 0; i < initialValidators.length; i++) { - (await blockRewardContract.epochPoolNativeReward(stakingEpoch, initialValidators[i])).should.be.equal(BigNumber.from(0)); - } + await expect(stakingHbbft.connect(candidateStakingAddress).addPool( + candidateMiningAddress.address, + ZeroPublicKey, + ZeroIpAddress, + { value: minStake }, + )).to.be.revertedWith("Stake: disallowed period"); - await timeTravelToTransition(blockRewardContract, stakingHbbftContract); - await timeTravelToEndEpoch(blockRewardContract, stakingHbbftContract); + await helpers.time.increase(2); - let distributedCoinsAmount = BigNumber.from(0); - for (let i = 0; i < initialValidators.length; i++) { - const epochPoolNativeReward = await blockRewardContract.epochPoolNativeReward(stakingEpoch, initialValidators[i]); - epochPoolNativeReward.should.be.above(BigNumber.from(0)); - distributedCoinsAmount = distributedCoinsAmount.add(epochPoolNativeReward); - } - const blockRewardCoinsBalanceAfter = BigNumber.from(await ethers.provider.getBalance(blockRewardContract.address)); - blockRewardCoinsBalanceAfter.should.be.equal(blockRewardCoinsBalanceBefore.add(distributedCoinsAmount)); - } + await stakingHbbft.connect(candidateStakingAddress).addPool( + candidateMiningAddress.address, + ZeroPublicKey, + ZeroIpAddress, + { value: minStake }, + ); + }); - // The delegator claims their rewards - const delegatorCoinsBalanceBefore = BigNumber.from(await ethers.provider.getBalance(delegator.address)); - const blockRewardCoinsBalanceBefore = BigNumber.from(await ethers.provider.getBalance(blockRewardContract.address)); - const blockRewardCoinsBalanceTotalBefore = blockRewardCoinsBalanceBefore; + it('should fail if staking amount is less than CANDIDATE_MIN_STAKE', async () => { + const { stakingHbbft } = await helpers.loadFixture(deployContractsFixture); - const expectedClaimRewardAmounts = (await stakingHbbftContract.getRewardAmount([], initialStakingAddresses[0], delegator.address)); + await expect(stakingHbbft.connect(candidateStakingAddress).addPool( + candidateMiningAddress.address, + ZeroPublicKey, + ZeroIpAddress, + { value: minStake / 2n } + )).to.be.revertedWith("Stake: candidateStake less than candidateMinStake"); + }); - const result = await stakingHbbftContract.connect(delegator).claimReward([], initialStakingAddresses[0]); - let receipt = await result.wait(); + it('stake amount should be increased', async () => { + const { stakingHbbft } = await helpers.loadFixture(deployContractsFixture); - let coinsDelegatorGotForAllEpochs = BigNumber.from(0); - for (let i = 0; i < maxStakingEpoch; i++) { - receipt.events?.[i].event?.should.be.equal("ClaimedReward"); - receipt.events?.[i].args?.fromPoolStakingAddress.should.be.equal(initialStakingAddresses[0]); - receipt.events?.[i].args?.staker.should.be.equal(delegator.address); - receipt.events?.[i].args?.stakingEpoch.should.be.equal(BigNumber.from(i + 1)); - coinsDelegatorGotForAllEpochs = coinsDelegatorGotForAllEpochs.add(receipt.events?.[i].args?.nativeCoinsAmount); - } + const amount = minStake * 2n; + await stakingHbbft.connect(candidateStakingAddress).addPool( + candidateMiningAddress.address, + ZeroPublicKey, + ZeroIpAddress, + { value: amount } + ); - expectedClaimRewardAmounts.should.be.equal(coinsDelegatorGotForAllEpochs); + expect(await stakingHbbft.stakeAmount(candidateStakingAddress.address, candidateStakingAddress.address)).to.equal(amount); + expect(await stakingHbbft.stakeAmountByCurrentEpoch(candidateStakingAddress.address, candidateStakingAddress.address)).to.equal(amount); + expect(await stakingHbbft.stakeAmountTotal(candidateStakingAddress.address)).to.equal(amount); + }); - const weiSpent = (BigNumber.from(receipt.gasUsed)).mul(BigNumber.from(result.gasPrice)); + it('should be able to add more than one pool', async () => { + const { stakingHbbft, validatorSetHbbft } = await helpers.loadFixture(deployContractsFixture); - // console.log(`gasUsed = ${receipt.gasUsed}, cumulativeGasUsed = ${receipt.cumulativeGasUsed}`); + const candidate1MiningAddress = candidateMiningAddress; + const candidate1StakingAddress = candidateStakingAddress; + const candidate2MiningAddress = accounts[9]; + const candidate2StakingAddress = accounts[10]; - if (!!process.env.SOLIDITY_COVERAGE !== true) { - // receipt.gasUsed.should.be.below(1710000); - receipt.gasUsed.should.be.below(2100000); // for Istanbul - } + const amount1 = minStake * 2n; + const amount2 = minStake * 3n; - const delegatorCoinsBalanceAfter = BigNumber.from(await ethers.provider.getBalance(delegator.address)); - const blockRewardCoinsBalanceAfter = BigNumber.from(await ethers.provider.getBalance(blockRewardContract.address)); - - coinsDelegatorGotForAllEpochs.should.be.gte(BigNumber.from(0)); - delegatorCoinsBalanceAfter.should.be.equal(delegatorCoinsBalanceBefore.add(coinsDelegatorGotForAllEpochs).sub(weiSpent)); - blockRewardCoinsBalanceAfter.should.be.equal(blockRewardCoinsBalanceBefore.sub(coinsDelegatorGotForAllEpochs)); - - // The validators claim their rewards - let coinsValidatorsGotForAllEpochs = BigNumber.from(0); - for (let v = 0; v < initialStakingAddresses.length; v++) { - const validator = initialStakingAddresses[v]; - const validatorCoinsBalanceBefore = BigNumber.from(await ethers.provider.getBalance(validator)); - const blockRewardCoinsBalanceBefore = BigNumber.from(await ethers.provider.getBalance(blockRewardContract.address)); - const expectedClaimRewardAmounts = (await stakingHbbftContract.getRewardAmount([], validator, validator)); - const result = await stakingHbbftContract.connect(await ethers.getSigner(validator)).claimReward([], validator); - const receipt = await result.wait(); - - let claimedCoinsAmount = BigNumber.from(0); - for (let i = 0; i < maxStakingEpoch; i++) { - receipt.events?.[i].event?.should.be.equal("ClaimedReward"); - receipt.events?.[i].args?.fromPoolStakingAddress.should.be.equal(validator); - receipt.events?.[i].args?.staker.should.be.equal(validator); - receipt.events?.[i].args?.stakingEpoch.should.be.equal(BigNumber.from(i + 1)); - claimedCoinsAmount = claimedCoinsAmount.add(receipt.events?.[i].args?.nativeCoinsAmount); - } + // Add two new pools + expect(await stakingHbbft.isPoolActive(candidate1StakingAddress.address)).to.be.false; + expect(await stakingHbbft.isPoolActive(candidate2StakingAddress.address)).to.be.false; + + await stakingHbbft.connect(candidate1StakingAddress).addPool( + candidate1MiningAddress.address, + ZeroPublicKey, + ZeroIpAddress, + { value: amount1 } + ); - expectedClaimRewardAmounts.should.be.equal(claimedCoinsAmount); + await stakingHbbft.connect(candidate2StakingAddress).addPool( + candidate2MiningAddress.address, + ZeroPublicKey, + ZeroIpAddress, + { value: amount2 } + ); - const weiSpent = (BigNumber.from(receipt.gasUsed)).mul(BigNumber.from(result.gasPrice)); + expect(await stakingHbbft.isPoolActive(candidate1StakingAddress.address)).to.be.true; + expect(await stakingHbbft.isPoolActive(candidate2StakingAddress.address)).to.be.true; - const validatorCoinsBalanceAfter = BigNumber.from(await ethers.provider.getBalance(validator)); - const blockRewardCoinsBalanceAfter = BigNumber.from(await ethers.provider.getBalance(blockRewardContract.address)); + // Check indexes in the `poolsToBeElected` list + expect(await stakingHbbft.poolToBeElectedIndex(candidate1StakingAddress.address)).to.equal(0n); + expect(await stakingHbbft.poolToBeElectedIndex(candidate2StakingAddress.address)).to.equal(1n); - claimedCoinsAmount.should.be.gte(BigNumber.from(0)); - validatorCoinsBalanceAfter.should.be.equal(validatorCoinsBalanceBefore.add(claimedCoinsAmount).sub(weiSpent)); - blockRewardCoinsBalanceAfter.should.be.equal(blockRewardCoinsBalanceBefore.sub(claimedCoinsAmount)); - coinsValidatorsGotForAllEpochs = coinsValidatorsGotForAllEpochs.add(claimedCoinsAmount); - } + // Check pools' existence + const validators = await validatorSetHbbft.getValidators(); - const blockRewardCoinsBalanceTotalAfter = BigNumber.from(await ethers.provider.getBalance(blockRewardContract.address)); - blockRewardCoinsBalanceTotalAfter.should.be.equal(blockRewardCoinsBalanceTotalBefore.sub(coinsDelegatorGotForAllEpochs).sub(coinsValidatorsGotForAllEpochs)); - blockRewardCoinsBalanceTotalAfter.should.be.gte(BigNumber.from(0)); + expect(await stakingHbbft.getPools()).to.be.deep.equal([ + await validatorSetHbbft.stakingByMiningAddress(validators[0]), + await validatorSetHbbft.stakingByMiningAddress(validators[1]), + await validatorSetHbbft.stakingByMiningAddress(validators[2]), + candidate1StakingAddress.address, + candidate2StakingAddress.address + ]); }); - it('gas consumption for 52 staking epochs (including gaps ~ 10 years) is OK', async () => { - const maxStakingEpochs = 52; - const gapSize = 10; - - await blockRewardContract.addToDeltaPot({ value: deltaPotFillupValue }); - - // Loop of staking epochs - for (let s = 0; s < maxStakingEpochs; s++) { - if (s == 0) { - await stakingHbbftContract.setStakingEpoch(1); - await stakingHbbftContract.setValidatorMockSetAddress(owner.address); - await stakingHbbftContract.setValidatorMockSetAddress(validatorSetContract.address); - } - - const stakingEpoch = (await stakingHbbftContract.stakingEpoch()).toNumber(); - - (await validatorSetContract.getValidators()).should.be.deep.equal(initialValidators); - (await stakingHbbftContract.stakingEpoch()).should.be.equal(BigNumber.from(stakingEpoch)); - - const blockRewardCoinsBalanceBefore = BigNumber.from(await ethers.provider.getBalance(blockRewardContract.address)); - for (let i = 0; i < initialValidators.length; i++) { - (await blockRewardContract.epochPoolNativeReward(stakingEpoch, initialValidators[i])).should.be.equal(BigNumber.from(0)); - } + it("shouldn't allow adding more than MAX_CANDIDATES pools", async () => { + const { stakingHbbft } = await helpers.loadFixture(deployContractsFixture); - await timeTravelToTransition(blockRewardContract, stakingHbbftContract); - await timeTravelToEndEpoch(blockRewardContract, stakingHbbftContract); + const maxCandidates = await stakingHbbft.getMaxCandidates(); - let distributedCoinsAmount = BigNumber.from(0); - for (let i = 0; i < initialValidators.length; i++) { - const epochPoolNativeReward = await blockRewardContract.epochPoolNativeReward(stakingEpoch, initialValidators[i]); - epochPoolNativeReward.should.be.above(BigNumber.from(0)); - distributedCoinsAmount = distributedCoinsAmount.add(epochPoolNativeReward); - } - const blockRewardCoinsBalanceAfter = BigNumber.from(await ethers.provider.getBalance(blockRewardContract.address)); - blockRewardCoinsBalanceAfter.should.be.equal(blockRewardCoinsBalanceBefore.add(distributedCoinsAmount)); - - const nextStakingEpoch = stakingEpoch + gapSize; // jump through a few epochs - await stakingHbbftContract.setStakingEpoch(nextStakingEpoch); - await stakingHbbftContract.setValidatorMockSetAddress(owner.address); - //await stakingHbbft.setStakingEpochStartBlock((120954 + 2) * nextStakingEpoch + 1); - await stakingHbbftContract.setValidatorMockSetAddress(validatorSetContract.address); - for (let i = 0; i < initialValidators.length; i++) { - await blockRewardContract.snapshotPoolStakeAmounts(stakingHbbftContract.address, nextStakingEpoch, initialValidators[i]); - } + for (let i = initialValidators.length; i < maxCandidates; ++i) { + // Add a new pool + await stakingHbbft.addPoolActiveMock(ethers.Wallet.createRandom().address); } - const epochsPoolGotRewardFor = await blockRewardContract.epochsPoolGotRewardFor(initialValidators[0]); + // Try to add a new pool outside of max limit, max limit is 100 in mock contract. + await expect(stakingHbbft.connect(candidateStakingAddress).addPool( + candidateMiningAddress.address, + ZeroPublicKey, + ZeroIpAddress, + { value: minStake } + )).to.be.revertedWith("MAX_CANDIDATES pools exceeded"); - // The delegator claims their rewards - const delegatorCoinsBalanceBefore = BigNumber.from(await ethers.provider.getBalance(delegator.address)); - const blockRewardCoinsBalanceBefore = BigNumber.from(await ethers.provider.getBalance(blockRewardContract.address)); - const blockRewardCoinsBalanceTotalBefore = blockRewardCoinsBalanceBefore; + expect(await stakingHbbft.isPoolActive(candidateStakingAddress.address)).to.be.false; + }); - const expectedClaimRewardAmounts = (await stakingHbbftContract.getRewardAmount([], initialStakingAddresses[0], delegator.address)); + it('should remove added pool from the list of inactive pools', async () => { + const { stakingHbbft } = await helpers.loadFixture(deployContractsFixture); - const result = await stakingHbbftContract.connect(delegator).claimReward([], initialStakingAddresses[0]); - const receipt = await result.wait(); + await stakingHbbft.addPoolInactiveMock(candidateStakingAddress.address); + expect(await stakingHbbft.getPoolsInactive()).to.be.deep.equal([candidateStakingAddress.address]); - let coinsDelegatorGotForAllEpochs = BigNumber.from(0); - for (let i = 0; i < maxStakingEpochs; i++) { - receipt.events?.[i].event?.should.be.equal("ClaimedReward"); - receipt.events?.[i].args?.fromPoolStakingAddress.should.be.equal(initialStakingAddresses[0]); - receipt.events?.[i].args?.staker.should.be.equal(delegator.address); - receipt.events?.[i].args?.stakingEpoch.should.be.equal(epochsPoolGotRewardFor[i]); - coinsDelegatorGotForAllEpochs = coinsDelegatorGotForAllEpochs.add(receipt.events?.[i].args?.nativeCoinsAmount); - } + await stakingHbbft.connect(candidateStakingAddress).addPool( + candidateMiningAddress.address, + ZeroPublicKey, + ZeroIpAddress, + { value: minStake } + ); - expectedClaimRewardAmounts.should.be.equal(coinsDelegatorGotForAllEpochs); + expect(await stakingHbbft.isPoolActive(candidateStakingAddress.address)).to.be.true; + expect(await stakingHbbft.getPoolsInactive()).to.be.empty; + }); + }); - const weiSpent = (BigNumber.from(receipt.gasUsed)).mul(BigNumber.from(result.gasPrice)); + describe('contract balance', async () => { + before(async () => { + candidateMiningAddress = accounts[7]; + candidateStakingAddress = accounts[8]; + }); - // console.log(`gasUsed = ${receipt.gasUsed}, cumulativeGasUsed = ${receipt.cumulativeGasUsed}`); + it('cannot be increased by sending native coins', async () => { + const { stakingHbbft } = await helpers.loadFixture(deployContractsFixture); - if (!!process.env.SOLIDITY_COVERAGE !== true) { - // receipt.gasUsed.should.be.below(2000000); - receipt.gasUsed.should.be.below(2610000); // for Istanbul - } + await expect(owner.sendTransaction({ to: await stakingHbbft.getAddress(), value: 1n })) + .to.be.revertedWith("Not payable"); - const delegatorCoinsBalanceAfter = BigNumber.from(await ethers.provider.getBalance(delegator.address)); - const blockRewardCoinsBalanceAfter = BigNumber.from(await ethers.provider.getBalance(blockRewardContract.address)); - - coinsDelegatorGotForAllEpochs.should.be.gte(BigNumber.from(0)); - delegatorCoinsBalanceAfter.should.be.equal(delegatorCoinsBalanceBefore.add(coinsDelegatorGotForAllEpochs).sub(weiSpent)); - blockRewardCoinsBalanceAfter.should.be.equal(blockRewardCoinsBalanceBefore.sub(coinsDelegatorGotForAllEpochs)); - - // The validators claim their rewards - let coinsValidatorsGotForAllEpochs = BigNumber.from(0); - for (let v = 0; v < initialStakingAddresses.length; v++) { - const validator = initialStakingAddresses[v]; - const validatorCoinsBalanceBefore = BigNumber.from(await ethers.provider.getBalance(validator)); - const blockRewardCoinsBalanceBefore = BigNumber.from(await ethers.provider.getBalance(blockRewardContract.address)); - const expectedClaimRewardAmounts = (await stakingHbbftContract.getRewardAmount([], validator, validator)); - const result = await stakingHbbftContract.connect(await ethers.getSigner(validator)).claimReward([], validator); - const receipt = await result.wait(); - - let claimedCoinsAmount = BigNumber.from(0); - for (let i = 0; i < maxStakingEpochs; i++) { - receipt.events?.[i].event?.should.be.equal("ClaimedReward"); - receipt.events?.[i].args?.fromPoolStakingAddress.should.be.equal(validator); - receipt.events?.[i].args?.staker.should.be.equal(validator); - receipt.events?.[i].args?.stakingEpoch.should.be.equal(epochsPoolGotRewardFor[i]); - claimedCoinsAmount = claimedCoinsAmount.add(receipt.events?.[i].args?.nativeCoinsAmount); - } + await owner.sendTransaction({ to: accounts[1].address, value: 1n }); + expect(await ethers.provider.getBalance(await stakingHbbft.getAddress())).to.be.equal(0n); + }); - expectedClaimRewardAmounts.should.be.equal(claimedCoinsAmount); + it('can be increased by sending coins to payable functions', async () => { + const { stakingHbbft } = await helpers.loadFixture(deployContractsFixture); - const weiSpent = (BigNumber.from(receipt.gasUsed)).mul(BigNumber.from(result.gasPrice)); + expect(await ethers.provider.getBalance(await stakingHbbft.getAddress())).to.be.equal(0n); + await stakingHbbft.connect(candidateStakingAddress).addPool( + candidateMiningAddress.address, + ZeroPublicKey, + ZeroIpAddress, + { value: minStake } + ); - const validatorCoinsBalanceAfter = BigNumber.from(await ethers.provider.getBalance(validator)); - const blockRewardCoinsBalanceAfter = BigNumber.from(await ethers.provider.getBalance(blockRewardContract.address)); + expect(await ethers.provider.getBalance(await stakingHbbft.getAddress())).to.to.be.equal(minStake); - claimedCoinsAmount.should.be.gte(BigNumber.from(0)); - validatorCoinsBalanceAfter.should.be.equal(validatorCoinsBalanceBefore.add(claimedCoinsAmount).sub(weiSpent)); - blockRewardCoinsBalanceAfter.should.be.equal(blockRewardCoinsBalanceBefore.sub(claimedCoinsAmount)); - coinsValidatorsGotForAllEpochs = coinsValidatorsGotForAllEpochs.add(claimedCoinsAmount); - } + await stakingHbbft.connect(candidateStakingAddress).stake( + candidateStakingAddress.address, + { value: minStake } + ); - const blockRewardCoinsBalanceTotalAfter = BigNumber.from(await ethers.provider.getBalance(blockRewardContract.address)); - blockRewardCoinsBalanceTotalAfter.should.be.equal(blockRewardCoinsBalanceTotalBefore.sub(coinsDelegatorGotForAllEpochs).sub(coinsValidatorsGotForAllEpochs)); - blockRewardCoinsBalanceTotalAfter.should.be.gte(BigNumber.from(0)); + expect(await ethers.provider.getBalance(await stakingHbbft.getAddress())).to.be.equal(minStake * 2n); }); }); describe('incrementStakingEpoch()', async () => { let stakingContract: StakingHbbftMock; - let validatorSetContract: SignerWithAddress; + let validatorSetContract: HardhatEthersSigner; beforeEach(async () => { const { stakingHbbft } = await helpers.loadFixture(deployContractsFixture); @@ -1731,25 +583,26 @@ describe('StakingHbbft', () => { stakingContract = stakingHbbft; validatorSetContract = accounts[7]; - await stakingHbbft.setValidatorMockSetAddress(validatorSetContract.address); + await stakingHbbft.setValidatorMockSetAddress(await validatorSetContract.getAddress()); }); it('should increment if called by the ValidatorSet', async () => { - (await stakingContract.stakingEpoch()).should.be.equal(BigNumber.from(0)); + expect(await stakingContract.stakingEpoch()).to.be.equal(0n); await stakingContract.connect(validatorSetContract).incrementStakingEpoch(); - (await stakingContract.stakingEpoch()).should.be.equal(BigNumber.from(1)); + + expect(await stakingContract.stakingEpoch()).to.be.equal(1n); }); it('can only be called by ValidatorSet contract', async () => { - await stakingContract.connect(accounts[8]).incrementStakingEpoch().should.be.rejectedWith("Only ValidatorSet"); + await expect(stakingContract.connect(accounts[8]).incrementStakingEpoch()) + .to.be.revertedWith("Only ValidatorSet"); }); }); - describe('initialize()', async () => { const validatorSetContract = '0x1000000000000000000000000000000000000001'; - beforeEach(async() => { + beforeEach(async () => { // The following private keys belong to the accounts 1-3, fixed by using the "--mnemonic" option when starting ganache. // const initialValidatorsPrivKeys = ["0x272b8400a202c08e23641b53368d603e5fec5c13ea2f438bce291f7be63a02a7", "0xa8ea110ffc8fe68a069c8a460ad6b9698b09e21ad5503285f633b3ad79076cf7", "0x5da461ff1378256f69cb9a9d0a8b370c97c460acbe88f5d897cb17209f891ffc"]; // Public keys corresponding to the three private keys above. @@ -1764,9 +617,9 @@ describe('StakingHbbft', () => { // The IP addresses are irrelevant for these unit test, just initialize them to 0. initialValidatorsIpAddresses = [ - '0x00000000000000000000000000000000', - '0x00000000000000000000000000000000', - '0x00000000000000000000000000000000' + ZeroIpAddress, + ZeroIpAddress, + ZeroIpAddress ]; }); @@ -1792,45 +645,53 @@ describe('StakingHbbft', () => { initialValidatorsIpAddresses // _internetAddresses ], { initializer: 'initialize' } - ) as StakingHbbftMock; - - stakingFixedEpochDuration.should.be.equal( - await stakingHbbft.stakingFixedEpochDuration() - ); - stakingWithdrawDisallowPeriod.should.be.equal( - await stakingHbbft.stakingWithdrawDisallowPeriod() ); - validatorSetContract.should.be.equal( - await stakingHbbft.validatorSetContract() - ); + await stakingHbbft.waitForDeployment(); - for (let i = 0; i < initialStakingAddresses.length; i++) { - BigNumber.from(i).should.be.equal( - await stakingHbbft.poolIndex(initialStakingAddresses[i]) - ); - true.should.be.equal( - await stakingHbbft.isPoolActive(initialStakingAddresses[i]) - ); - BigNumber.from(i).should.be.equal( - await stakingHbbft.poolToBeRemovedIndex(initialStakingAddresses[i]) - ); + expect(await stakingHbbft.stakingFixedEpochDuration()).to.be.equal(stakingFixedEpochDuration); + expect(await stakingHbbft.stakingWithdrawDisallowPeriod()).to.be.equal(stakingWithdrawDisallowPeriod); + expect(await stakingHbbft.validatorSetContract()).to.be.equal(validatorSetContract) + + for (const stakingAddress of initialStakingAddresses) { + expect(await stakingHbbft.isPoolActive(stakingAddress)).to.be.true; + expect(await stakingHbbft.getPools()).to.include(stakingAddress); + expect(await stakingHbbft.getPoolsToBeRemoved()).to.include(stakingAddress); } - (await stakingHbbft.getPools()).should.be.deep.equal(initialStakingAddresses); + expect(await stakingHbbft.getPools()).to.be.deep.equal(initialStakingAddresses); + expect(await stakingHbbft.delegatorMinStake()).to.be.equal(ethers.parseEther('1')); + expect(await stakingHbbft.candidateMinStake()).to.be.equal(ethers.parseEther('1')) + }); - BigNumber.from(ethers.utils.parseEther('1')).should.be.equal( - await stakingHbbft.delegatorMinStake() - ); + it('should fail if owner = address(0)', async () => { + let stakingParams = { + _validatorSetContract: validatorSetContract, + _initialStakingAddresses: initialStakingAddresses, + _delegatorMinStake: minStake, + _candidateMinStake: minStake, + _maxStake: maxStake, + _stakingFixedEpochDuration: stakingFixedEpochDuration, + _stakingTransitionTimeframeLength: stakingTransitionTimeframeLength, + _stakingWithdrawDisallowPeriod: stakingWithdrawDisallowPeriod + }; - BigNumber.from(ethers.utils.parseEther('1')).should.be.equal( - await stakingHbbft.candidateMinStake() - ); + const StakingHbbftFactory = await ethers.getContractFactory("StakingHbbftMock"); + await expect(upgrades.deployProxy( + StakingHbbftFactory, + [ + ethers.ZeroAddress, + stakingParams, + initialValidatorsPubKeysSplit, // _publicKeys + initialValidatorsIpAddresses // _internetAddresses + ], + { initializer: 'initialize' } + )).to.be.revertedWith("Owner address cannot be 0"); }); it('should fail if ValidatorSet contract address is zero', async () => { let stakingParams = { - _validatorSetContract: ethers.constants.AddressZero, + _validatorSetContract: ethers.ZeroAddress, _initialStakingAddresses: initialStakingAddresses, _delegatorMinStake: minStake, _candidateMinStake: minStake, @@ -1927,7 +788,7 @@ describe('StakingHbbft', () => { { initializer: 'initialize' } ); - expect(await stakingHbbft.deployed()); + await stakingHbbft.waitForDeployment(); await expect(stakingHbbft.initialize( owner.address, @@ -1971,7 +832,7 @@ describe('StakingHbbft', () => { _maxStake: maxStake, _stakingFixedEpochDuration: stakingFixedEpochDuration, _stakingTransitionTimeframeLength: stakingTransitionTimeframeLength, - _stakingWithdrawDisallowPeriod: 0 + _stakingWithdrawDisallowPeriod: 0n }; const StakingHbbftFactory = await ethers.getContractFactory("StakingHbbftMock"); @@ -1996,7 +857,7 @@ describe('StakingHbbft', () => { _maxStake: maxStake, _stakingFixedEpochDuration: stakingFixedEpochDuration, _stakingTransitionTimeframeLength: stakingTransitionTimeframeLength, - _stakingWithdrawDisallowPeriod: 120954 + _stakingWithdrawDisallowPeriod: 120954n }; const StakingHbbftFactory = await ethers.getContractFactory("StakingHbbftMock"); @@ -2013,7 +874,7 @@ describe('StakingHbbft', () => { }); it('should fail if some staking address is 0', async () => { - initialStakingAddresses[0] = '0x0000000000000000000000000000000000000000'; + initialStakingAddresses[0] = ethers.ZeroAddress; let stakingParams = { _validatorSetContract: validatorSetContract, @@ -2087,14 +948,13 @@ describe('StakingHbbft', () => { ], { initializer: 'initialize' } )).to.be.revertedWith("The transition timeframe must be shorter then the epoch duration"); - }); }); describe('moveStake()', async () => { - let delegatorAddress: SignerWithAddress; + let delegatorAddress: HardhatEthersSigner; let stakingContract: StakingHbbftMock; - const stakeAmount = minStake.mul(BigNumber.from(2)); + const stakeAmount = minStake * 2n; beforeEach(async () => { const { stakingHbbft } = await helpers.loadFixture(deployContractsFixture); @@ -2112,19 +972,21 @@ describe('StakingHbbft', () => { // we can move the stake, since the staking address is not part of the active validator set, // since we never did never a time travel. // If we do, the stakingAddresses are blocked to withdraw without an orderwithdraw. - (await stakingContract.stakeAmount(initialStakingAddresses[0], delegatorAddress.address)).should.be.equal(stakeAmount); - (await stakingContract.stakeAmount(initialStakingAddresses[1], delegatorAddress.address)).should.be.equal(BigNumber.from(0)); + expect(await stakingContract.stakeAmount(initialStakingAddresses[0], delegatorAddress.address)).to.be.equal(stakeAmount); + expect(await stakingContract.stakeAmount(initialStakingAddresses[1], delegatorAddress.address)).to.be.equal(0n); + await stakingContract.connect(delegatorAddress).moveStake(initialStakingAddresses[0], initialStakingAddresses[1], stakeAmount); - (await stakingContract.stakeAmount(initialStakingAddresses[0], delegatorAddress.address)).should.be.equal(BigNumber.from(0)); - (await stakingContract.stakeAmount(initialStakingAddresses[1], delegatorAddress.address)).should.be.equal(stakeAmount); + expect(await stakingContract.stakeAmount(initialStakingAddresses[0], delegatorAddress.address)).to.be.equal(0n); + expect(await stakingContract.stakeAmount(initialStakingAddresses[1], delegatorAddress.address)).to.be.equal(stakeAmount); }); it('should move part of the stake', async () => { - (await stakingContract.stakeAmount(initialStakingAddresses[0], delegatorAddress.address)).should.be.equal(stakeAmount); - (await stakingContract.stakeAmount(initialStakingAddresses[1], delegatorAddress.address)).should.be.equal(BigNumber.from(0)); + expect(await stakingContract.stakeAmount(initialStakingAddresses[0], delegatorAddress.address)).to.be.equal(stakeAmount); + expect(await stakingContract.stakeAmount(initialStakingAddresses[1], delegatorAddress.address)).to.be.equal(0n); + await stakingContract.connect(delegatorAddress).moveStake(initialStakingAddresses[0], initialStakingAddresses[1], minStake); - (await stakingContract.stakeAmount(initialStakingAddresses[0], delegatorAddress.address)).should.be.equal(minStake); - (await stakingContract.stakeAmount(initialStakingAddresses[1], delegatorAddress.address)).should.be.equal(minStake); + expect(await stakingContract.stakeAmount(initialStakingAddresses[0], delegatorAddress.address)).to.be.equal(minStake); + expect(await stakingContract.stakeAmount(initialStakingAddresses[1], delegatorAddress.address)).to.be.equal(minStake); }); it('should move part of the stake', async () => { @@ -2133,27 +995,40 @@ describe('StakingHbbft', () => { const sourcePool = initialStakingAddresses[0]; const targetPool = initialStakingAddresses[1]; - (await stakingContract.stakeAmount(sourcePool, delegatorAddress.address)).should.be.equal(stakeAmount); - (await stakingContract.stakeAmount(targetPool, delegatorAddress.address)).should.be.equal(stakeAmount); + expect(await stakingContract.stakeAmount(sourcePool, delegatorAddress.address)).to.be.equal(stakeAmount); + expect(await stakingContract.stakeAmount(targetPool, delegatorAddress.address)).to.be.equal(stakeAmount); - const moveAmount = minStake.div(BigNumber.from(2)); - moveAmount.should.be.below(await stakingContract.delegatorMinStake()); + const moveAmount = minStake / 2n; + expect(moveAmount).to.be.below(await stakingContract.delegatorMinStake()); await stakingContract.connect(delegatorAddress).moveStake(sourcePool, targetPool, moveAmount); - (await stakingContract.stakeAmount(sourcePool, delegatorAddress.address)).should.be.equal(stakeAmount.sub(moveAmount)); - (await stakingContract.stakeAmount(targetPool, delegatorAddress.address)).should.be.equal(stakeAmount.add(moveAmount)); + expect(await stakingContract.stakeAmount(sourcePool, delegatorAddress.address)).to.be.equal(stakeAmount - moveAmount); + expect(await stakingContract.stakeAmount(targetPool, delegatorAddress.address)).to.be.equal(stakeAmount + moveAmount); }); it('should fail for zero gas price', async () => { - await stakingContract.connect(delegatorAddress).moveStake(initialStakingAddresses[0], initialStakingAddresses[1], stakeAmount, { gasPrice: 0 }).should.be.rejectedWith("GasPrice is 0"); + await expect(stakingContract.connect(delegatorAddress).moveStake( + initialStakingAddresses[0], + initialStakingAddresses[1], + stakeAmount, + { gasPrice: 0 } + )).to.be.revertedWith("GasPrice is 0"); }); it('should fail if the source and destination addresses are the same', async () => { - await stakingContract.connect(delegatorAddress).moveStake(initialStakingAddresses[0], initialStakingAddresses[0], stakeAmount).should.be.rejectedWith("MoveStake: src and dst pool is the same"); + await expect(stakingContract.connect(delegatorAddress).moveStake( + initialStakingAddresses[0], + initialStakingAddresses[0], + stakeAmount + )).to.be.revertedWith("MoveStake: src and dst pool is the same"); }); it('should fail if the staker tries to move more than they have', async () => { - await stakingContract.connect(delegatorAddress).moveStake(initialStakingAddresses[0], initialStakingAddresses[1], stakeAmount.mul(BigNumber.from(2))).should.be.rejectedWith("Withdraw: maxWithdrawAllowed exceeded"); + await expect(stakingContract.connect(delegatorAddress).moveStake( + initialStakingAddresses[0], + initialStakingAddresses[1], + stakeAmount * 2n + )).to.be.revertedWith("Withdraw: maxWithdrawAllowed exceeded"); }); it('should fail if the staker tries to overstake by moving stake.', async () => { @@ -2162,19 +1037,24 @@ describe('StakingHbbft', () => { const sourcePool = initialStakingAddresses[0]; const targetPool = initialStakingAddresses[1]; - let currentSourceStake = BigNumber.from(await stakingContract.stakeAmountTotal(sourcePool)); - const totalStakeableSource = maxStake.sub(currentSourceStake); + let currentSourceStake = await stakingContract.stakeAmountTotal(sourcePool); + const totalStakeableSource = maxStake - currentSourceStake; await stakingContract.connect(delegatorAddress).stake(sourcePool, { value: totalStakeableSource }); - let currentTargetStake = BigNumber.from(await stakingContract.stakeAmountTotal(targetPool)); - const totalStakeableTarget = maxStake.sub(currentTargetStake); + + let currentTargetStake = await stakingContract.stakeAmountTotal(targetPool); + const totalStakeableTarget = maxStake - currentTargetStake; await stakingContract.connect(delegatorAddress).stake(targetPool, { value: totalStakeableTarget }); // source is at max stake now, now tip it over. - await stakingContract.connect(delegatorAddress).moveStake(sourcePool, targetPool, BigNumber.from(1)).should.be.rejectedWith("stake limit has been exceeded"); + await expect(stakingContract.connect(delegatorAddress).moveStake( + sourcePool, + targetPool, + 1n + )).to.be.revertedWith("stake limit has been exceeded"); }); }); describe('stake()', async () => { - let delegatorAddress: SignerWithAddress; + let delegatorAddress: HardhatEthersSigner; beforeEach(async () => { delegatorAddress = accounts[7]; @@ -2183,43 +1063,62 @@ describe('StakingHbbft', () => { it('should be zero initially', async () => { const { stakingHbbft } = await helpers.loadFixture(deployContractsFixture); - (await stakingHbbft.stakeAmount(initialStakingAddresses[1], initialStakingAddresses[1])).should.be.equal(BigNumber.from(0)); - (await stakingHbbft.stakeAmount(initialStakingAddresses[1], delegatorAddress.address)).should.be.equal(BigNumber.from(0)); + expect(await stakingHbbft.stakeAmount(initialStakingAddresses[1], initialStakingAddresses[1])).to.be.equal(0n); + expect(await stakingHbbft.stakeAmount(initialStakingAddresses[1], delegatorAddress.address)).to.be.equal(0n); }); it('should place a stake', async () => { const { stakingHbbft, candidateMinStake, delegatorMinStake } = await helpers.loadFixture(deployContractsFixture); - await stakingHbbft.connect(await ethers.getSigner(initialStakingAddresses[1])).stake(initialStakingAddresses[1], { value: candidateMinStake }); - (await stakingHbbft.stakeAmount(initialStakingAddresses[1], initialStakingAddresses[1])).should.be.equal(candidateMinStake); - const result = await stakingHbbft.connect(delegatorAddress).stake(initialStakingAddresses[1], { value: delegatorMinStake }); - let receipt = await result.wait() - receipt.events?.[0].event?.should.be.equal("PlacedStake"); - receipt.events?.[0].args?.toPoolStakingAddress.should.be.equal(initialStakingAddresses[1]); - receipt.events?.[0].args?.staker.should.be.equal(delegatorAddress.address); - receipt.events?.[0].args?.stakingEpoch.should.be.equal(BigNumber.from(0)); - receipt.events?.[0].args?.amount.should.be.equal(delegatorMinStake); - (await stakingHbbft.stakeAmount(initialStakingAddresses[1], delegatorAddress.address)).should.be.equal(delegatorMinStake); - (await stakingHbbft.stakeAmountTotal(initialStakingAddresses[1])).should.be.equal(candidateMinStake.add(delegatorMinStake)); + const pool = await ethers.getSigner(initialStakingAddresses[1]); + + await stakingHbbft.connect(pool).stake(pool.address, { value: candidateMinStake }); + + expect(await stakingHbbft.stakeAmount(pool.address, pool.address)).to.be.equal(candidateMinStake); + + await expect(stakingHbbft.connect(delegatorAddress).stake(pool.address, { value: delegatorMinStake })) + .to.emit(stakingHbbft, "PlacedStake") + .withArgs( + pool.address, + delegatorAddress.address, + 0n, + delegatorMinStake + ); + + expect(await stakingHbbft.stakeAmount(pool.address, delegatorAddress.address)).to.be.equal(delegatorMinStake); + expect(await stakingHbbft.stakeAmountTotal(pool.address)).to.be.equal(candidateMinStake + delegatorMinStake); }); it('should fail for zero gas price', async () => { const { stakingHbbft, candidateMinStake } = await helpers.loadFixture(deployContractsFixture); - await stakingHbbft.connect(await ethers.getSigner(initialStakingAddresses[1])).stake(initialStakingAddresses[1], { value: candidateMinStake, gasPrice: 0 }).should.be.rejectedWith("GasPrice is 0"); + const pool = await ethers.getSigner(initialStakingAddresses[1]); + + await expect(stakingHbbft.connect(pool).stake( + pool.address, + { value: candidateMinStake, gasPrice: 0 } + )).to.be.revertedWith("GasPrice is 0"); + }); + + it('should fail for a zero staking pool address', async () => { + const { stakingHbbft, delegatorMinStake } = await helpers.loadFixture(deployContractsFixture); + + await expect(stakingHbbft.connect(delegatorAddress).stake(ethers.ZeroAddress, { value: delegatorMinStake })) + .to.be.revertedWith("Stake: stakingAddress is 0"); }); it('should fail for a non-existing pool', async () => { const { stakingHbbft, delegatorMinStake } = await helpers.loadFixture(deployContractsFixture); - await stakingHbbft.connect(delegatorAddress).stake(accounts[10].address, { value: delegatorMinStake }).should.be.rejectedWith("Pool does not exist. miningAddress for that staking address is 0"); - await stakingHbbft.connect(delegatorAddress).stake('0x0000000000000000000000000000000000000000', { value: delegatorMinStake }).should.be.rejectedWith("Pool does not exist. miningAddress for that staking address is 0"); + await expect(stakingHbbft.connect(delegatorAddress).stake(accounts[10].address, { value: delegatorMinStake })) + .to.be.revertedWith("Pool does not exist. miningAddress for that staking address is 0"); }); it('should fail for a zero amount', async () => { const { stakingHbbft } = await helpers.loadFixture(deployContractsFixture); - await stakingHbbft.connect(delegatorAddress).stake(initialStakingAddresses[1], { value: 0 }).should.be.rejectedWith("Stake: stakingAmount is 0"); + await expect(stakingHbbft.connect(delegatorAddress).stake(initialStakingAddresses[1], { value: 0 })) + .to.be.revertedWith("Stake: stakingAmount is 0"); }); it('should fail for a banned validator', async () => { @@ -2230,120 +1129,246 @@ describe('StakingHbbft', () => { delegatorMinStake } = await helpers.loadFixture(deployContractsFixture); - await stakingHbbft.connect(await ethers.getSigner(initialStakingAddresses[1])).stake(initialStakingAddresses[1], { value: candidateMinStake }); + const pool = await ethers.getSigner(initialStakingAddresses[1]); + + await stakingHbbft.connect(pool).stake(pool.address, { value: candidateMinStake }); await validatorSetHbbft.setSystemAddress(owner.address); await validatorSetHbbft.connect(owner).removeMaliciousValidators([initialValidators[1]]); - await stakingHbbft.connect(delegatorAddress).stake(initialStakingAddresses[1], { value: delegatorMinStake }).should.be.rejectedWith("Stake: Mining address is banned"); + + await expect(stakingHbbft.connect(delegatorAddress).stake( + pool.address, + { value: delegatorMinStake } + )).to.be.revertedWith("Stake: Mining address is banned"); }); - // it('should only success in the allowed staking window', async () => { - // //await stakingHbbft.setCurrentBlockNumber(117000); - // await stakingHbbft.stake(initialStakingAddresses[1], {from: initialStakingAddresses[1], value: candidateMinStake}).should.be.rejectedWith("Stake: disallowed period"); - // }); + it.skip('should only success in the allowed staking window', async () => { + const { stakingHbbft, candidateMinStake } = await helpers.loadFixture(deployContractsFixture); + + const pool = await ethers.getSigner(initialStakingAddresses[1]); + + await expect(stakingHbbft.connect(pool).stake(pool.address, { value: candidateMinStake })) + .to.be.revertedWith("Stake: disallowed period"); + }); it('should fail if a candidate stakes less than CANDIDATE_MIN_STAKE', async () => { const { stakingHbbft, candidateMinStake } = await helpers.loadFixture(deployContractsFixture); - const halfOfCandidateMinStake = candidateMinStake.div(BigNumber.from(2)); - await stakingHbbft.connect(await ethers.getSigner(initialStakingAddresses[1])).stake(initialStakingAddresses[1], { value: halfOfCandidateMinStake }).should.be.rejectedWith("Stake: candidateStake less than candidateMinStake"); + const pool = await ethers.getSigner(initialStakingAddresses[1]); + + const halfOfCandidateMinStake = candidateMinStake / 2n; + await expect(stakingHbbft.connect(pool).stake( + pool.address, + { value: halfOfCandidateMinStake } + )).to.be.revertedWith("Stake: candidateStake less than candidateMinStake"); }); it('should fail if a delegator stakes less than DELEGATOR_MIN_STAKE', async () => { const { stakingHbbft, candidateMinStake, delegatorMinStake } = await helpers.loadFixture(deployContractsFixture); - await stakingHbbft.connect(await ethers.getSigner(initialStakingAddresses[1])).stake(initialStakingAddresses[1], { value: candidateMinStake }); - const halfOfDelegatorMinStake = delegatorMinStake.div(BigNumber.from(2)); - await stakingHbbft.connect(delegatorAddress).stake(initialStakingAddresses[1], { value: halfOfDelegatorMinStake }).should.be.rejectedWith("Stake: delegatorStake is less than delegatorMinStake"); + const pool = await ethers.getSigner(initialStakingAddresses[1]); + + await stakingHbbft.connect(pool).stake(pool.address, { value: candidateMinStake }); + const halfOfDelegatorMinStake = delegatorMinStake / 2n; + + await expect(stakingHbbft.connect(delegatorAddress).stake( + pool.address, + { value: halfOfDelegatorMinStake } + )).to.be.revertedWith("Stake: delegatorStake is less than delegatorMinStake"); }); it('should fail if a delegator stakes more than maxStake', async () => { const { stakingHbbft, candidateMinStake } = await helpers.loadFixture(deployContractsFixture); - await stakingHbbft.connect(await ethers.getSigner(initialStakingAddresses[1])).stake(initialStakingAddresses[1], { value: candidateMinStake }); - await stakingHbbft.connect(delegatorAddress).stake(initialStakingAddresses[1], { value: maxStake.add(BigNumber.from(1)) }).should.be.rejectedWith("stake limit has been exceeded"); + const pool = await ethers.getSigner(initialStakingAddresses[1]); + + await stakingHbbft.connect(pool).stake(pool.address, { value: candidateMinStake }); + await expect(stakingHbbft.connect(delegatorAddress).stake( + pool.address, + { value: maxStake + 1n } + )).to.be.revertedWith("stake limit has been exceeded"); }); it('should fail if a delegator stakes into an empty pool', async () => { const { stakingHbbft, delegatorMinStake } = await helpers.loadFixture(deployContractsFixture); - (await stakingHbbft.stakeAmount(initialStakingAddresses[1], initialStakingAddresses[1])).should.be.equal(BigNumber.from(0)); - await stakingHbbft.connect(delegatorAddress).stake(initialStakingAddresses[1], { value: delegatorMinStake }).should.be.rejectedWith("Stake: can't delegate in empty pool"); + const pool = await ethers.getSigner(initialStakingAddresses[1]); + + expect(await stakingHbbft.stakeAmount(pool.address, pool.address)).to.be.equal(0n); + await expect(stakingHbbft.connect(delegatorAddress).stake( + pool.address, + { value: delegatorMinStake } + )).to.be.revertedWith("Stake: can't delegate in empty pool"); }); it('should increase a stake amount', async () => { const { stakingHbbft, candidateMinStake, delegatorMinStake } = await helpers.loadFixture(deployContractsFixture); - await stakingHbbft.connect(await ethers.getSigner(initialStakingAddresses[1])).stake(initialStakingAddresses[1], { value: candidateMinStake }); - (await stakingHbbft.stakeAmount(initialStakingAddresses[1], delegatorAddress.address)).should.be.equal(BigNumber.from(0)); - await stakingHbbft.connect(delegatorAddress).stake(initialStakingAddresses[1], { value: delegatorMinStake }); - (await stakingHbbft.stakeAmount(initialStakingAddresses[1], delegatorAddress.address)).should.be.equal(delegatorMinStake); - await stakingHbbft.connect(delegatorAddress).stake(initialStakingAddresses[1], { value: delegatorMinStake }); - (await stakingHbbft.stakeAmount(initialStakingAddresses[1], delegatorAddress.address)).should.be.equal(delegatorMinStake.mul(BigNumber.from(2))); + const pool = await ethers.getSigner(initialStakingAddresses[1]); + + await stakingHbbft.connect(pool).stake(pool.address, { value: candidateMinStake }); + expect(await stakingHbbft.stakeAmount(pool.address, delegatorAddress.address)).to.be.equal(0n); + + await stakingHbbft.connect(delegatorAddress).stake(pool.address, { value: delegatorMinStake }); + expect(await stakingHbbft.stakeAmount(pool.address, delegatorAddress.address)).to.be.equal(delegatorMinStake); + + await stakingHbbft.connect(delegatorAddress).stake(pool.address, { value: delegatorMinStake }); + expect(await stakingHbbft.stakeAmount(pool.address, delegatorAddress.address)).to.be.equal(delegatorMinStake * 2n); }); it('should increase the stakeAmountByCurrentEpoch', async () => { const { stakingHbbft, candidateMinStake, delegatorMinStake } = await helpers.loadFixture(deployContractsFixture); - await stakingHbbft.connect(await ethers.getSigner(initialStakingAddresses[1])).stake(initialStakingAddresses[1], { value: candidateMinStake }); - (await stakingHbbft.stakeAmountByCurrentEpoch(initialStakingAddresses[1], delegatorAddress.address)).should.be.equal(BigNumber.from(0)); - await stakingHbbft.connect(delegatorAddress).stake(initialStakingAddresses[1], { value: delegatorMinStake }); - (await stakingHbbft.stakeAmountByCurrentEpoch(initialStakingAddresses[1], delegatorAddress.address)).should.be.equal(delegatorMinStake); - await stakingHbbft.connect(delegatorAddress).stake(initialStakingAddresses[1], { value: delegatorMinStake }); - (await stakingHbbft.stakeAmountByCurrentEpoch(initialStakingAddresses[1], delegatorAddress.address)).should.be.equal(delegatorMinStake.mul(BigNumber.from(2))); + const pool = await ethers.getSigner(initialStakingAddresses[1]); + + await stakingHbbft.connect(pool).stake(pool.address, { value: candidateMinStake }); + expect(await stakingHbbft.stakeAmountByCurrentEpoch(pool.address, delegatorAddress.address)).to.be.equal(0n); + + await stakingHbbft.connect(delegatorAddress).stake(pool.address, { value: delegatorMinStake }); + expect(await stakingHbbft.stakeAmountByCurrentEpoch(pool.address, delegatorAddress.address)).to.be.equal(delegatorMinStake); + + await stakingHbbft.connect(delegatorAddress).stake(pool.address, { value: delegatorMinStake }); + expect(await stakingHbbft.stakeAmountByCurrentEpoch(pool.address, delegatorAddress.address)).to.be.equal(delegatorMinStake * 2n); }); it('should increase a total stake amount', async () => { const { stakingHbbft, candidateMinStake, delegatorMinStake } = await helpers.loadFixture(deployContractsFixture); - await stakingHbbft.connect(await ethers.getSigner(initialStakingAddresses[1])).stake(initialStakingAddresses[1], { value: candidateMinStake }); - (await stakingHbbft.stakeAmountTotal(initialStakingAddresses[1])).should.be.equal(candidateMinStake); - await stakingHbbft.connect(delegatorAddress).stake(initialStakingAddresses[1], { value: delegatorMinStake }); - (await stakingHbbft.stakeAmountTotal(initialStakingAddresses[1])).should.be.equal(candidateMinStake.add(delegatorMinStake)); - await stakingHbbft.connect(delegatorAddress).stake(initialStakingAddresses[1], { value: delegatorMinStake }); - (await stakingHbbft.stakeAmountTotal(initialStakingAddresses[1])).should.be.equal(candidateMinStake.add(delegatorMinStake.mul(BigNumber.from(2)))); + const pool = await ethers.getSigner(initialStakingAddresses[1]); + + await stakingHbbft.connect(pool).stake(pool.address, { value: candidateMinStake }); + expect(await stakingHbbft.stakeAmountTotal(pool.address)).to.be.equal(candidateMinStake); + + await stakingHbbft.connect(delegatorAddress).stake(pool.address, { value: delegatorMinStake }); + expect(await stakingHbbft.stakeAmountTotal(pool.address)).to.be.equal(candidateMinStake + delegatorMinStake); + + await stakingHbbft.connect(delegatorAddress).stake(pool.address, { value: delegatorMinStake }); + expect(await stakingHbbft.stakeAmountTotal(pool.address)).to.be.equal(candidateMinStake + delegatorMinStake * 2n); }); it('should add a delegator to the pool', async () => { const { stakingHbbft, candidateMinStake, delegatorMinStake } = await helpers.loadFixture(deployContractsFixture); - await stakingHbbft.connect(await ethers.getSigner(initialStakingAddresses[1])).stake(initialStakingAddresses[1], { value: candidateMinStake }); - (await stakingHbbft.poolDelegators(initialStakingAddresses[1])).length.should.be.equal(0); - await stakingHbbft.connect(delegatorAddress).stake(initialStakingAddresses[1], { value: delegatorMinStake }); - await stakingHbbft.connect(delegatorAddress).stake(initialStakingAddresses[1], { value: delegatorMinStake }); - (await stakingHbbft.poolDelegators(initialStakingAddresses[1])).should.be.deep.equal([delegatorAddress.address]); + const pool = await ethers.getSigner(initialStakingAddresses[1]); + + await stakingHbbft.connect(pool).stake(pool.address, { value: candidateMinStake }); + expect(await stakingHbbft.poolDelegators(pool.address)).to.be.empty; + + await stakingHbbft.connect(delegatorAddress).stake(pool.address, { value: delegatorMinStake }); + await stakingHbbft.connect(delegatorAddress).stake(pool.address, { value: delegatorMinStake }); + + expect(await stakingHbbft.poolDelegators(pool.address)).to.be.deep.equal([delegatorAddress.address]); }); it("should update pool's likelihood", async () => { const { stakingHbbft, candidateMinStake, delegatorMinStake } = await helpers.loadFixture(deployContractsFixture); + const pool = await ethers.getSigner(initialStakingAddresses[1]); + let likelihoodInfo = await stakingHbbft.getPoolsLikelihood(); - likelihoodInfo.likelihoods.length.should.be.equal(0); - likelihoodInfo.sum.should.be.equal(BigNumber.from(0)); - await stakingHbbft.connect(await ethers.getSigner(initialStakingAddresses[1])).stake(initialStakingAddresses[1], { value: candidateMinStake }); + expect(likelihoodInfo.likelihoods).to.be.empty; + expect(likelihoodInfo.sum).to.be.equal(0n); + await stakingHbbft.connect(pool).stake(pool.address, { value: candidateMinStake }); likelihoodInfo = await stakingHbbft.getPoolsLikelihood(); - likelihoodInfo.likelihoods[0].should.be.equal(candidateMinStake); - likelihoodInfo.sum.should.be.equal(candidateMinStake); - await stakingHbbft.connect(delegatorAddress).stake(initialStakingAddresses[1], { value: delegatorMinStake }); + expect(likelihoodInfo.likelihoods[0]).to.be.equal(candidateMinStake); + expect(likelihoodInfo.sum).to.be.equal(candidateMinStake); + await stakingHbbft.connect(delegatorAddress).stake(pool.address, { value: delegatorMinStake }); likelihoodInfo = await stakingHbbft.getPoolsLikelihood(); - likelihoodInfo.likelihoods[0].should.be.equal(candidateMinStake.add(delegatorMinStake)); - likelihoodInfo.sum.should.be.equal(candidateMinStake.add(delegatorMinStake)); - await stakingHbbft.connect(delegatorAddress).stake(initialStakingAddresses[1], { value: delegatorMinStake }); + expect(likelihoodInfo.likelihoods[0]).to.be.equal(candidateMinStake + delegatorMinStake); + expect(likelihoodInfo.sum).to.be.equal(candidateMinStake + delegatorMinStake); + await stakingHbbft.connect(delegatorAddress).stake(pool.address, { value: delegatorMinStake }); likelihoodInfo = await stakingHbbft.getPoolsLikelihood(); - likelihoodInfo.likelihoods[0].should.be.equal(candidateMinStake.add(delegatorMinStake.mul(BigNumber.from(2)))); - likelihoodInfo.sum.should.be.equal(candidateMinStake.add(delegatorMinStake.mul(BigNumber.from(2)))); + expect(likelihoodInfo.likelihoods[0]).to.be.equal(candidateMinStake + delegatorMinStake * 2n); + expect(likelihoodInfo.sum).to.be.equal(candidateMinStake + delegatorMinStake * 2n); }); it('should decrease the balance of the staker and increase the balance of the Staking contract', async () => { const { stakingHbbft, candidateMinStake } = await helpers.loadFixture(deployContractsFixture); - (await ethers.provider.getBalance(stakingHbbft.address)).should.be.equal('0'); - const initialBalance = BigNumber.from(await ethers.provider.getBalance(initialStakingAddresses[1])); - await stakingHbbft.connect(await ethers.getSigner(initialStakingAddresses[1])).stake(initialStakingAddresses[1], { value: candidateMinStake }); - (BigNumber.from(await ethers.provider.getBalance(initialStakingAddresses[1]))).should.be.below(initialBalance.sub(candidateMinStake)); - (BigNumber.from(await ethers.provider.getBalance(stakingHbbft.address))).should.be.equal(candidateMinStake); + const pool = await ethers.getSigner(initialStakingAddresses[1]); + + expect(await ethers.provider.getBalance(await stakingHbbft.getAddress())).to.be.equal(0n); + + const initialBalance = await ethers.provider.getBalance(pool.address); + await stakingHbbft.connect(pool).stake(pool.address, { value: candidateMinStake }); + + expect(await ethers.provider.getBalance(pool.address)).to.be.below(initialBalance - candidateMinStake); + expect(await ethers.provider.getBalance(await stakingHbbft.getAddress())).to.be.equal(candidateMinStake); + }); + + it('should not create stake snapshot on epoch 0', async () => { + const { + stakingHbbft, + validatorSetHbbft, + candidateMinStake, + delegatorMinStake, + } = await helpers.loadFixture(deployContractsFixture); + + const pool = await ethers.getSigner(initialStakingAddresses[1]); + const mining = initialValidators[1]; + const delegator = accounts[11]; + + await stakingHbbft.connect(pool).stake(pool.address, { value: candidateMinStake }); + expect(await stakingHbbft.stakeAmount(pool.address, pool.address)).to.be.equal(candidateMinStake); + + let stakingEpoch = await stakingHbbft.stakingEpoch(); + expect(stakingEpoch).to.equal(0n); + + await stakingHbbft.connect(delegator).stake(pool.address, { value: delegatorMinStake }); + expect(await stakingHbbft.stakeAmount(pool.address, delegator.address)).to.be.equal(delegatorMinStake); + expect(await stakingHbbft.getDelegatorStakeSnapshot(pool.address, delegator.address, stakingEpoch)) + .to.be.equal(0n); + expect(await stakingHbbft.getStakeSnapshotLastEpoch(pool.address, delegator.address)) + .to.be.equal(0n); + + expect(await validatorSetHbbft.isValidatorOrPending(mining)).to.be.true; + + await stakingHbbft.connect(delegator).stake(pool.address, { value: delegatorMinStake * 2n }); + expect(await stakingHbbft.stakeAmount(pool.address, delegator.address)).to.be.equal(delegatorMinStake * 3n); + expect(await stakingHbbft.getDelegatorStakeSnapshot(pool.address, delegator.address, stakingEpoch)) + .to.be.equal(0n); + expect(await stakingHbbft.getStakeSnapshotLastEpoch(pool.address, delegator.address)) + .to.be.equal(0n); + }); + + it('should create stake snapshot if staking on an active validator', async () => { + const { + stakingHbbft, + validatorSetHbbft, + blockRewardHbbft, + candidateMinStake, + delegatorMinStake, + } = await helpers.loadFixture(deployContractsFixture); + + const pool = await ethers.getSigner(initialStakingAddresses[1]); + const mining = initialValidators[1]; + const delegator = accounts[11]; + + await stakingHbbft.connect(pool).stake(pool.address, { value: candidateMinStake }); + expect(await stakingHbbft.stakeAmount(pool.address, pool.address)).to.be.equal(candidateMinStake); + + let stakingEpoch = await stakingHbbft.stakingEpoch(); + await stakingHbbft.connect(delegator).stake(pool.address, { value: delegatorMinStake }); + expect(await stakingHbbft.stakeAmount(pool.address, delegator.address)).to.be.equal(delegatorMinStake); + expect(await stakingHbbft.getDelegatorStakeSnapshot(pool.address, delegator.address, stakingEpoch)) + .to.be.equal(0n); + expect(await stakingHbbft.getStakeSnapshotLastEpoch(pool.address, delegator.address)) + .to.be.equal(0n); + + await callReward(blockRewardHbbft, true); + + expect(await validatorSetHbbft.isValidatorOrPending(mining)).to.be.true; + expect(await stakingHbbft.stakingEpoch()).to.be.gt(0n); + + stakingEpoch = await stakingHbbft.stakingEpoch(); + await stakingHbbft.connect(delegator).stake(pool.address, { value: delegatorMinStake * 2n }); + expect(await stakingHbbft.stakeAmount(pool.address, delegator.address)).to.be.equal(delegatorMinStake * 3n); + expect(await stakingHbbft.getDelegatorStakeSnapshot(pool.address, delegator.address, stakingEpoch)) + .to.be.equal(delegatorMinStake); + expect(await stakingHbbft.getStakeSnapshotLastEpoch(pool.address, delegator.address)) + .to.be.equal(stakingEpoch); }); }); @@ -2351,71 +1376,78 @@ describe('StakingHbbft', () => { it('should remove a pool', async () => { const { stakingHbbft } = await helpers.loadFixture(deployContractsFixture); - (await stakingHbbft.getPools()).should.be.deep.equal(initialStakingAddresses); + expect(await stakingHbbft.getPools()).to.be.deep.equal(initialStakingAddresses); + await stakingHbbft.setValidatorMockSetAddress(accounts[7].address); await stakingHbbft.connect(accounts[7]).removePool(initialStakingAddresses[0]); - (await stakingHbbft.getPools()).should.be.deep.equal([ + + expect(await stakingHbbft.getPools()).to.be.deep.equal([ initialStakingAddresses[2], initialStakingAddresses[1] ]); - (await stakingHbbft.getPoolsInactive()).length.should.be.equal(0); + + expect(await stakingHbbft.getPoolsInactive()).to.be.empty; }); it('can only be called by the ValidatorSetHbbft contract', async () => { const { stakingHbbft } = await helpers.loadFixture(deployContractsFixture); await stakingHbbft.setValidatorMockSetAddress(accounts[7].address); - await stakingHbbft.connect(accounts[8]).removePool(initialStakingAddresses[0]).should.be.rejectedWith("Only ValidatorSet"); + await expect(stakingHbbft.connect(accounts[8]).removePool(initialStakingAddresses[0])) + .to.be.revertedWith("Only ValidatorSet"); }); it("shouldn't fail when removing a nonexistent pool", async () => { const { stakingHbbft } = await helpers.loadFixture(deployContractsFixture); - (await stakingHbbft.getPools()).should.be.deep.equal(initialStakingAddresses); + expect(await stakingHbbft.getPools()).to.be.deep.equal(initialStakingAddresses); + await stakingHbbft.setValidatorMockSetAddress(accounts[7].address); await stakingHbbft.connect(accounts[7]).removePool(accounts[10].address); - (await stakingHbbft.getPools()).should.be.deep.equal(initialStakingAddresses); - }); - - it('should reset pool index', async () => { - const { stakingHbbft } = await helpers.loadFixture(deployContractsFixture); - (await stakingHbbft.poolIndex(initialStakingAddresses[1])).should.be.equal(BigNumber.from(1)); - await stakingHbbft.setValidatorMockSetAddress(accounts[7].address); - await stakingHbbft.connect(accounts[7]).removePool(initialStakingAddresses[1]); - (await stakingHbbft.poolIndex(initialStakingAddresses[1])).should.be.equal(BigNumber.from(0)); + expect(await stakingHbbft.getPools()).to.be.deep.equal(initialStakingAddresses); }); it('should add/remove a pool to/from the utility lists', async () => { const { stakingHbbft } = await helpers.loadFixture(deployContractsFixture); // The first validator places stake for themselves - (await stakingHbbft.getPoolsToBeElected()).length.should.be.deep.equal(0); - (await stakingHbbft.getPoolsToBeRemoved()).should.be.deep.equal(initialStakingAddresses); - await stakingHbbft.connect(await ethers.getSigner(initialStakingAddresses[0])).stake(initialStakingAddresses[0], { value: minStake }); - (await stakingHbbft.stakeAmountTotal(initialStakingAddresses[0])).should.be.equal(minStake); - (await stakingHbbft.getPoolsToBeElected()).should.be.deep.equal([initialStakingAddresses[0]]); - (await stakingHbbft.getPoolsToBeRemoved()).should.be.deep.equal([ + expect(await stakingHbbft.getPoolsToBeElected()).to.be.lengthOf(0); + expect(await stakingHbbft.getPoolsToBeRemoved()).to.be.deep.equal(initialStakingAddresses); + + await stakingHbbft.connect(await ethers.getSigner(initialStakingAddresses[0])).stake( + initialStakingAddresses[0], + { value: minStake } + ); + + expect(await stakingHbbft.stakeAmountTotal(initialStakingAddresses[0])).to.be.equal(minStake); + expect(await stakingHbbft.getPoolsToBeElected()).to.be.deep.equal([initialStakingAddresses[0]]); + expect(await stakingHbbft.getPoolsToBeRemoved()).to.be.deep.equal([ initialStakingAddresses[2], initialStakingAddresses[1] ]); // Remove the pool await stakingHbbft.setValidatorMockSetAddress(accounts[7].address); - (await stakingHbbft.poolInactiveIndex(initialStakingAddresses[0])).should.be.equal(BigNumber.from(0)); await stakingHbbft.connect(accounts[7]).removePool(initialStakingAddresses[0]); - (await stakingHbbft.getPoolsInactive()).should.be.deep.equal([initialStakingAddresses[0]]); - (await stakingHbbft.poolInactiveIndex(initialStakingAddresses[0])).should.be.equal(BigNumber.from(0)); + expect(await stakingHbbft.getPoolsInactive()).to.be.deep.equal([initialStakingAddresses[0]]); - await stakingHbbft.setStakeAmountTotal(initialStakingAddresses[0], 0); await stakingHbbft.connect(accounts[7]).removePool(initialStakingAddresses[0]); - (await stakingHbbft.getPoolsInactive()).length.should.be.equal(0); - (await stakingHbbft.getPoolsToBeElected()).length.should.be.deep.equal(0); + expect(await stakingHbbft.getPoolsInactive()).to.be.deep.equal([initialStakingAddresses[0]]); - (await stakingHbbft.poolToBeRemovedIndex(initialStakingAddresses[1])).should.be.equal(BigNumber.from(1)); await stakingHbbft.connect(accounts[7]).removePool(initialStakingAddresses[1]); - (await stakingHbbft.getPoolsToBeRemoved()).should.be.deep.equal([initialStakingAddresses[2]]); - (await stakingHbbft.poolToBeRemovedIndex(initialStakingAddresses[1])).should.be.equal(BigNumber.from(0)); + expect(await stakingHbbft.getPoolsToBeRemoved()).to.be.deep.equal([initialStakingAddresses[2]]); + }); + + }); + + describe('removePools()', async () => { + it('should restrict calling removePools to validator set contract', async () => { + const { stakingHbbft } = await helpers.loadFixture(deployContractsFixture); + const caller = accounts[10]; + + await expect(stakingHbbft.connect(caller).removePools()) + .to.be.revertedWith("Only ValidatorSet") }); }); @@ -2425,27 +1457,32 @@ describe('StakingHbbft', () => { await stakingHbbft.setValidatorMockSetAddress(accounts[7].address); await stakingHbbft.connect(accounts[7]).incrementStakingEpoch(); - await stakingHbbft.setValidatorMockSetAddress(validatorSetHbbft.address); - await stakingHbbft.connect(await ethers.getSigner(initialStakingAddresses[0])).removeMyPool({ gasPrice: 0 }).should.be.rejectedWith("GasPrice is 0"); + await stakingHbbft.setValidatorMockSetAddress(await validatorSetHbbft.getAddress()); + await expect(stakingHbbft.connect(await ethers.getSigner(initialStakingAddresses[0])).removeMyPool({ gasPrice: 0n })) + .to.be.rejectedWith("GasPrice is 0"); }); it('should fail for initial validator during the initial staking epoch', async () => { const { stakingHbbft, validatorSetHbbft } = await helpers.loadFixture(deployContractsFixture); - (await stakingHbbft.stakingEpoch()).should.be.equal(BigNumber.from(0)); - (await validatorSetHbbft.isValidator(initialValidators[0])).should.be.equal(true); - (await validatorSetHbbft.miningByStakingAddress(initialStakingAddresses[0])).should.be.equal(initialValidators[0]); - await stakingHbbft.connect(await ethers.getSigner(initialStakingAddresses[0])).removeMyPool({}).should.be.rejectedWith("Can't remove pool during 1st staking epoch"); + expect(await stakingHbbft.stakingEpoch()).to.be.equal(0n); + expect(await validatorSetHbbft.isValidator(initialValidators[0])).to.be.true; + expect(await validatorSetHbbft.miningByStakingAddress(initialStakingAddresses[0])).to.be.equal(initialValidators[0]); + + await expect(stakingHbbft.connect(await ethers.getSigner(initialStakingAddresses[0])).removeMyPool({})) + .to.be.revertedWith("Can't remove pool during 1st staking epoch"); + await stakingHbbft.setValidatorMockSetAddress(accounts[7].address); await stakingHbbft.connect(accounts[7]).incrementStakingEpoch(); - await stakingHbbft.setValidatorMockSetAddress(validatorSetHbbft.address); - await stakingHbbft.connect(await ethers.getSigner(initialStakingAddresses[0])).removeMyPool({}).should.be.fulfilled + await stakingHbbft.setValidatorMockSetAddress(await validatorSetHbbft.getAddress()); + + await expect(stakingHbbft.connect(await ethers.getSigner(initialStakingAddresses[0])).removeMyPool({})).to.be.fulfilled }); }); describe('withdraw()', async () => { - const stakeAmount = minStake.mul(BigNumber.from(2)); - let delegatorAddress: SignerWithAddress; + const stakeAmount = minStake * 2n; + let delegatorAddress: HardhatEthersSigner; beforeEach(async () => { delegatorAddress = accounts[7]; @@ -2454,106 +1491,174 @@ describe('StakingHbbft', () => { it('should withdraw a stake', async () => { const { stakingHbbft } = await helpers.loadFixture(deployContractsFixture); - (await stakingHbbft.stakeAmount(initialStakingAddresses[1], initialStakingAddresses[1])).should.be.equal(BigNumber.from(0)); - (await stakingHbbft.stakeAmountByCurrentEpoch(initialStakingAddresses[1], initialStakingAddresses[1])).should.be.equal(BigNumber.from(0)); - (await stakingHbbft.stakeAmount(initialStakingAddresses[1], delegatorAddress.address)).should.be.equal(BigNumber.from(0)); - (await stakingHbbft.stakeAmountByCurrentEpoch(initialStakingAddresses[1], delegatorAddress.address)).should.be.equal(BigNumber.from(0)); + expect(await stakingHbbft.stakeAmount(initialStakingAddresses[1], initialStakingAddresses[1])).to.be.equal(0n); + expect(await stakingHbbft.stakeAmountByCurrentEpoch(initialStakingAddresses[1], initialStakingAddresses[1])).to.be.equal(0n); + expect(await stakingHbbft.stakeAmount(initialStakingAddresses[1], delegatorAddress.address)).to.be.equal(0n); + expect(await stakingHbbft.stakeAmountByCurrentEpoch(initialStakingAddresses[1], delegatorAddress.address)).to.be.equal(0n); + await stakingHbbft.connect(await ethers.getSigner(initialStakingAddresses[1])).stake(initialStakingAddresses[1], { value: stakeAmount }); - (await stakingHbbft.stakeAmount(initialStakingAddresses[1], initialStakingAddresses[1])).should.be.equal(stakeAmount); - (await stakingHbbft.stakeAmountByCurrentEpoch(initialStakingAddresses[1], initialStakingAddresses[1])).should.be.equal(stakeAmount); + expect(await stakingHbbft.stakeAmount(initialStakingAddresses[1], initialStakingAddresses[1])).to.be.equal(stakeAmount); + expect(await stakingHbbft.stakeAmountByCurrentEpoch(initialStakingAddresses[1], initialStakingAddresses[1])).to.be.equal(stakeAmount); await stakingHbbft.connect(delegatorAddress).stake(initialStakingAddresses[1], { value: stakeAmount }); - (await stakingHbbft.stakeAmount(initialStakingAddresses[1], delegatorAddress.address)).should.be.equal(stakeAmount); - (await stakingHbbft.stakeAmountByCurrentEpoch(initialStakingAddresses[1], delegatorAddress.address)).should.be.equal(stakeAmount); - (await stakingHbbft.stakeAmountTotal(initialStakingAddresses[1])).should.be.equal(stakeAmount.mul(BigNumber.from(2))); - - const result = await stakingHbbft.connect(delegatorAddress).withdraw(initialStakingAddresses[1], stakeAmount); - let receipt = await result.wait(); - receipt.events?.[0].event?.should.be.equal("WithdrewStake"); - receipt.events?.[0].args?.fromPoolStakingAddress.should.be.equal(initialStakingAddresses[1]); - receipt.events?.[0].args?.staker.should.be.equal(delegatorAddress.address); - receipt.events?.[0].args?.stakingEpoch.should.be.equal(BigNumber.from(0)); - receipt.events?.[0].args?.amount.should.be.equal(stakeAmount); - (await stakingHbbft.stakeAmount(initialStakingAddresses[1], delegatorAddress.address)).should.be.equal(BigNumber.from(0)); - (await stakingHbbft.stakeAmountByCurrentEpoch(initialStakingAddresses[1], delegatorAddress.address)).should.be.equal(BigNumber.from(0)); - (await stakingHbbft.stakeAmountTotal(initialStakingAddresses[1])).should.be.equal(stakeAmount); + expect(await stakingHbbft.stakeAmount(initialStakingAddresses[1], delegatorAddress.address)).to.be.equal(stakeAmount); + expect(await stakingHbbft.stakeAmountByCurrentEpoch(initialStakingAddresses[1], delegatorAddress.address)).to.be.equal(stakeAmount); + expect(await stakingHbbft.stakeAmountTotal(initialStakingAddresses[1])).to.be.equal(stakeAmount * 2n); + + await expect(stakingHbbft.connect(delegatorAddress).withdraw(initialStakingAddresses[1], stakeAmount)) + .to.emit(stakingHbbft, "WithdrewStake") + .withArgs( + initialStakingAddresses[1], + delegatorAddress.address, + 0n, + stakeAmount + ); + + expect(await stakingHbbft.stakeAmount(initialStakingAddresses[1], delegatorAddress.address)).to.be.equal(0n); + expect(await stakingHbbft.stakeAmountByCurrentEpoch(initialStakingAddresses[1], delegatorAddress.address)).to.be.equal(0n); + expect(await stakingHbbft.stakeAmountTotal(initialStakingAddresses[1])).to.be.equal(stakeAmount); }); it('should fail for zero gas price', async () => { const { stakingHbbft } = await helpers.loadFixture(deployContractsFixture); - await stakingHbbft.connect(await ethers.getSigner(initialStakingAddresses[1])).stake(initialStakingAddresses[1], { value: stakeAmount }); - await stakingHbbft.connect(await ethers.getSigner(initialStakingAddresses[1])).withdraw(initialStakingAddresses[1], stakeAmount, { gasPrice: 0 }).should.be.rejectedWith("GasPrice is 0"); + const staker = await ethers.getSigner(initialStakingAddresses[1]); + + await stakingHbbft.connect(staker).stake(staker.address, { value: stakeAmount }); + await expect(stakingHbbft.connect(staker).withdraw( + staker.address, + stakeAmount, + { gasPrice: 0 } + )).to.be.revertedWith("GasPrice is 0"); }); it('should fail for a zero pool address', async () => { const { stakingHbbft } = await helpers.loadFixture(deployContractsFixture); - await stakingHbbft.connect(await ethers.getSigner(initialStakingAddresses[1])).stake(initialStakingAddresses[1], { value: stakeAmount }); - await stakingHbbft.connect(await ethers.getSigner(initialStakingAddresses[1])).withdraw('0x0000000000000000000000000000000000000000', stakeAmount).should.be.rejectedWith(ERROR_MSG); - await stakingHbbft.connect(await ethers.getSigner(initialStakingAddresses[1])).withdraw(initialStakingAddresses[1], stakeAmount); + const staker = await ethers.getSigner(initialStakingAddresses[1]); + + await stakingHbbft.connect(staker).stake(staker.address, { value: stakeAmount }); + await expect(stakingHbbft.connect(staker).withdraw(ethers.ZeroAddress, stakeAmount)) + .to.be.revertedWith("Withdraw pool staking address must not be null"); + + await stakingHbbft.connect(staker).withdraw(staker.address, stakeAmount); }); it('should fail for a zero amount', async () => { const { stakingHbbft } = await helpers.loadFixture(deployContractsFixture); - await stakingHbbft.connect(await ethers.getSigner(initialStakingAddresses[1])).stake(initialStakingAddresses[1], { value: stakeAmount }); - await stakingHbbft.connect(await ethers.getSigner(initialStakingAddresses[1])).withdraw(initialStakingAddresses[1], BigNumber.from(0)).should.be.rejectedWith(ERROR_MSG); - await stakingHbbft.connect(await ethers.getSigner(initialStakingAddresses[1])).withdraw(initialStakingAddresses[1], stakeAmount); + const staker = await ethers.getSigner(initialStakingAddresses[1]); + + await stakingHbbft.connect(staker).stake(staker.address, { value: stakeAmount }); + await expect(stakingHbbft.connect(staker).withdraw(staker.address, 0n)) + .to.be.revertedWith("amount to withdraw must not be 0"); + + await stakingHbbft.connect(staker).withdraw(staker.address, stakeAmount); }); it("shouldn't allow withdrawing from a banned pool", async () => { const { stakingHbbft, validatorSetHbbft } = await helpers.loadFixture(deployContractsFixture); - await stakingHbbft.connect(await ethers.getSigner(initialStakingAddresses[1])).stake(initialStakingAddresses[1], { value: stakeAmount }); - await stakingHbbft.connect(delegatorAddress).stake(initialStakingAddresses[1], { value: stakeAmount }); + const pool = await ethers.getSigner(initialStakingAddresses[1]); + + await stakingHbbft.connect(pool).stake(pool.address, { value: stakeAmount }); + await stakingHbbft.connect(delegatorAddress).stake(pool.address, { value: stakeAmount }); + await validatorSetHbbft.setBannedUntil(initialValidators[1], '0xffffffffffffffff'); - await stakingHbbft.connect(await ethers.getSigner(initialStakingAddresses[1])).withdraw(initialStakingAddresses[1], stakeAmount).should.be.rejectedWith(ERROR_MSG); - await stakingHbbft.connect(delegatorAddress).withdraw(initialStakingAddresses[1], stakeAmount).should.be.rejectedWith(ERROR_MSG); - await validatorSetHbbft.setBannedUntil(initialValidators[1], 0); - await stakingHbbft.connect(await ethers.getSigner(initialStakingAddresses[1])).withdraw(initialStakingAddresses[1], stakeAmount); - await stakingHbbft.connect(delegatorAddress).withdraw(initialStakingAddresses[1], stakeAmount); - }); - - // it('shouldn\'t allow withdrawing during the stakingWithdrawDisallowPeriod', async () => { - // await stakingHbbft.stake(initialStakingAddresses[1], {from: initialStakingAddresses[1], value: stakeAmount}); - // //await stakingHbbft.setCurrentBlockNumber(117000); - // //await validatorSetHbbft.setCurrentBlockNumber(117000); - // await stakingHbbft.withdraw(initialStakingAddresses[1], stakeAmount, {from: initialStakingAddresses[1]}).should.be.rejectedWith(ERROR_MSG); - // //await stakingHbbft.setCurrentBlockNumber(116000); - // //await validatorSetHbbft.setCurrentBlockNumber(116000); - // await stakingHbbft.withdraw(initialStakingAddresses[1], stakeAmount, {from: initialStakingAddresses[1]}); - // }); + await expect(stakingHbbft.connect(pool).withdraw(pool.address, stakeAmount)) + .to.be.revertedWith("Withdraw: maxWithdrawAllowed exceeded"); + await expect(stakingHbbft.connect(delegatorAddress).withdraw(pool.address, stakeAmount)) + .to.be.revertedWith("Withdraw: maxWithdrawAllowed exceeded"); + + await validatorSetHbbft.setBannedUntil(initialValidators[1], 0n); + await stakingHbbft.connect(pool).withdraw(pool.address, stakeAmount); + await stakingHbbft.connect(delegatorAddress).withdraw(pool.address, stakeAmount); + }); + + it.skip("shouldn't allow withdrawing during the stakingWithdrawDisallowPeriod", async () => { + const { stakingHbbft } = await helpers.loadFixture(deployContractsFixture); + + await stakingHbbft.stake(initialStakingAddresses[1], { from: initialStakingAddresses[1], value: stakeAmount }); + + //await stakingHbbft.setCurrentBlockNumber(117000); + //await validatorSetHbbft.setCurrentBlockNumber(117000); + await expect(stakingHbbft.withdraw( + initialStakingAddresses[1], + stakeAmount, + { from: initialStakingAddresses[1] } + )).to.be.revertedWith("Stake: disallowed period"); + + //await stakingHbbft.setCurrentBlockNumber(116000); + //await validatorSetHbbft.setCurrentBlockNumber(116000); + + await stakingHbbft.withdraw(initialStakingAddresses[1], stakeAmount, { from: initialStakingAddresses[1] }); + }); it('should fail if non-zero residue is less than CANDIDATE_MIN_STAKE', async () => { const { stakingHbbft } = await helpers.loadFixture(deployContractsFixture); const candidateMinStake = await stakingHbbft.candidateMinStake(); + const pool = await ethers.getSigner(initialStakingAddresses[1]); - await stakingHbbft.connect(await ethers.getSigner(initialStakingAddresses[1])).stake(initialStakingAddresses[1], { value: stakeAmount }); - await stakingHbbft.connect(await ethers.getSigner(initialStakingAddresses[1])).withdraw(initialStakingAddresses[1], stakeAmount.sub(candidateMinStake).add(BigNumber.from(1))).should.be.rejectedWith(ERROR_MSG); - await stakingHbbft.connect(await ethers.getSigner(initialStakingAddresses[1])).withdraw(initialStakingAddresses[1], stakeAmount.sub(candidateMinStake)); - await stakingHbbft.connect(await ethers.getSigner(initialStakingAddresses[1])).withdraw(initialStakingAddresses[1], candidateMinStake); + await stakingHbbft.connect(pool).stake(pool.address, { value: stakeAmount }); + await expect(stakingHbbft.connect(pool).withdraw(pool.address, stakeAmount - candidateMinStake + 1n)) + .to.be.revertedWith("newStake amount must be greater equal than the min stake."); + + await stakingHbbft.connect(pool).withdraw(pool.address, stakeAmount - candidateMinStake); + await stakingHbbft.connect(pool).withdraw(pool.address, candidateMinStake); }); it('should fail if non-zero residue is less than DELEGATOR_MIN_STAKE', async () => { const { stakingHbbft } = await helpers.loadFixture(deployContractsFixture); const delegatorMinStake = await stakingHbbft.delegatorMinStake(); + const pool = await ethers.getSigner(initialStakingAddresses[1]); - await stakingHbbft.connect(await ethers.getSigner(initialStakingAddresses[1])).stake(initialStakingAddresses[1], { value: stakeAmount }); - await stakingHbbft.connect(delegatorAddress).stake(initialStakingAddresses[1], { value: stakeAmount }); - await stakingHbbft.connect(delegatorAddress).withdraw(initialStakingAddresses[1], stakeAmount.sub(delegatorMinStake).add(BigNumber.from(1))).should.be.rejectedWith(ERROR_MSG); - await stakingHbbft.connect(delegatorAddress).withdraw(initialStakingAddresses[1], stakeAmount.sub(delegatorMinStake)); - await stakingHbbft.connect(delegatorAddress).withdraw(initialStakingAddresses[1], delegatorMinStake); + await stakingHbbft.connect(pool).stake(pool.address, { value: stakeAmount }); + await stakingHbbft.connect(delegatorAddress).stake(pool.address, { value: stakeAmount }); + await expect(stakingHbbft.connect(delegatorAddress).withdraw(pool.address, stakeAmount - delegatorMinStake + 1n)) + .to.be.revertedWith("newStake amount must be greater equal than the min stake."); + await stakingHbbft.connect(delegatorAddress).withdraw(pool.address, stakeAmount - delegatorMinStake); + await stakingHbbft.connect(delegatorAddress).withdraw(pool.address, delegatorMinStake); }); it('should fail if withdraw more than staked', async () => { const { stakingHbbft } = await helpers.loadFixture(deployContractsFixture); - await stakingHbbft.connect(await ethers.getSigner(initialStakingAddresses[1])).stake(initialStakingAddresses[1], { value: stakeAmount }); - await stakingHbbft.connect(await ethers.getSigner(initialStakingAddresses[1])).withdraw(initialStakingAddresses[1], stakeAmount.add(BigNumber.from(1))).should.be.rejectedWith(ERROR_MSG); - await stakingHbbft.connect(await ethers.getSigner(initialStakingAddresses[1])).withdraw(initialStakingAddresses[1], stakeAmount); + const pool = await ethers.getSigner(initialStakingAddresses[1]); + + await stakingHbbft.connect(pool).stake(pool.address, { value: stakeAmount }); + await expect(stakingHbbft.connect(pool).withdraw(pool.address, stakeAmount + 1n)) + .to.be.revertedWith("Withdraw: maxWithdrawAllowed exceeded"); + await stakingHbbft.connect(pool).withdraw(pool.address, stakeAmount); + }); + + it('should revert orderWithdraw with gasPrice = 0', async () => { + const { stakingHbbft } = await helpers.loadFixture(deployContractsFixture); + + await expect(stakingHbbft.orderWithdraw( + initialStakingAddresses[1], + ethers.parseEther('1'), + { gasPrice: 0n }, + )).to.be.revertedWith("GasPrice is 0"); + }); + + it('should revert orderWithdraw with pool = address(0)', async () => { + const { stakingHbbft } = await helpers.loadFixture(deployContractsFixture); + + await expect(stakingHbbft.orderWithdraw( + ethers.ZeroAddress, + ethers.parseEther('1'), + )).to.be.revertedWith("poolStakingAddress must not be 0x0"); + }); + + it('should revert orderWithdraw with amount = 0', async () => { + const { stakingHbbft } = await helpers.loadFixture(deployContractsFixture); + + await expect(stakingHbbft.orderWithdraw( + initialStakingAddresses[1], + 0n, + )).to.be.revertedWith("ordered withdraw amount must not be 0"); }); it('should fail if withdraw already ordered amount', async () => { @@ -2562,82 +1667,89 @@ describe('StakingHbbft', () => { await validatorSetHbbft.setSystemAddress(owner.address); // Place a stake during the initial staking epoch - (await stakingHbbft.stakingEpoch()).should.be.equal(BigNumber.from(0)); + expect(await stakingHbbft.stakingEpoch()).to.be.equal(0n); await stakingHbbft.connect(await ethers.getSigner(initialStakingAddresses[0])).stake(initialStakingAddresses[0], { value: stakeAmount }); await stakingHbbft.connect(await ethers.getSigner(initialStakingAddresses[1])).stake(initialStakingAddresses[1], { value: stakeAmount }); await stakingHbbft.connect(await ethers.getSigner(initialStakingAddresses[2])).stake(initialStakingAddresses[2], { value: stakeAmount }); await stakingHbbft.connect(delegatorAddress).stake(initialStakingAddresses[1], { value: stakeAmount }); // Finalize a new validator set and change staking epoch - await validatorSetHbbft.setStakingContract(stakingHbbft.address); + await validatorSetHbbft.setStakingContract(await stakingHbbft.getAddress()); + // Set BlockRewardContract await validatorSetHbbft.setBlockRewardContract(accounts[7].address); await validatorSetHbbft.connect(accounts[7]).newValidatorSet(); - await validatorSetHbbft.setBlockRewardContract(blockRewardHbbft.address); + await validatorSetHbbft.setBlockRewardContract(await blockRewardHbbft.getAddress()); // (increases staking epoch) await timeTravelToTransition(blockRewardHbbft, stakingHbbft); await timeTravelToEndEpoch(blockRewardHbbft, stakingHbbft); - (await stakingHbbft.stakingEpoch()).should.be.equal(BigNumber.from(1)); + expect(await stakingHbbft.stakingEpoch()).to.be.equal(1n); // Order withdrawal - const orderedAmount = stakeAmount.div(BigNumber.from(4)); + const orderedAmount = stakeAmount / 4n; await stakingHbbft.connect(delegatorAddress).orderWithdraw(initialStakingAddresses[1], orderedAmount); + // The second validator removes their pool - (await validatorSetHbbft.isValidator(initialValidators[1])).should.be.equal(true); - (await stakingHbbft.getPoolsInactive()).length.should.be.equal(0); + expect(await validatorSetHbbft.isValidator(initialValidators[1])).to.be.true; + expect(await stakingHbbft.getPoolsInactive()).to.be.empty; + await stakingHbbft.connect(await ethers.getSigner(initialStakingAddresses[1])).removeMyPool(); - (await stakingHbbft.getPoolsInactive()).should.be.deep.equal([initialStakingAddresses[1]]); + expect(await stakingHbbft.getPoolsInactive()).to.be.deep.equal([initialStakingAddresses[1]]); // Finalize a new validator set, change staking epoch and enqueue pending validators await validatorSetHbbft.setBlockRewardContract(accounts[7].address); await validatorSetHbbft.connect(accounts[7]).newValidatorSet(); - await validatorSetHbbft.setBlockRewardContract(blockRewardHbbft.address); + await validatorSetHbbft.setBlockRewardContract(await blockRewardHbbft.getAddress()); await timeTravelToTransition(blockRewardHbbft, stakingHbbft); await timeTravelToEndEpoch(blockRewardHbbft, stakingHbbft); - (await stakingHbbft.stakingEpoch()).should.be.equal(BigNumber.from(2)); - (await validatorSetHbbft.isValidator(initialValidators[1])).should.be.equal(false); + expect(await stakingHbbft.stakingEpoch()).to.be.equal(2n); + expect(await validatorSetHbbft.isValidator(initialValidators[1])).to.be.false; // Check withdrawal for a delegator - const restOfAmount = stakeAmount.mul(BigNumber.from(3)).div(BigNumber.from(4)); - (await stakingHbbft.poolDelegators(initialStakingAddresses[1])).should.be.deep.equal([delegatorAddress.address]); - (await stakingHbbft.stakeAmount(initialStakingAddresses[1], delegatorAddress.address)).should.be.equal(restOfAmount); - (await stakingHbbft.stakeAmountByCurrentEpoch(initialStakingAddresses[1], delegatorAddress.address)).should.be.equal(BigNumber.from(0)); - await stakingHbbft.connect(delegatorAddress).withdraw(initialStakingAddresses[1], stakeAmount).should.be.rejectedWith(ERROR_MSG); - await stakingHbbft.connect(delegatorAddress).withdraw(initialStakingAddresses[1], restOfAmount.add(BigNumber.from(1))).should.be.rejectedWith(ERROR_MSG); + const restOfAmount = stakeAmount * 3n / 4n; + + expect(await stakingHbbft.poolDelegators(initialStakingAddresses[1])).to.be.deep.equal([delegatorAddress.address]); + expect(await stakingHbbft.stakeAmount(initialStakingAddresses[1], delegatorAddress.address)).to.be.equal(restOfAmount); + expect(await stakingHbbft.stakeAmountByCurrentEpoch(initialStakingAddresses[1], delegatorAddress.address)).to.be.equal(0n); + + await expect(stakingHbbft.connect(delegatorAddress).withdraw(initialStakingAddresses[1], stakeAmount)) + .to.be.revertedWith("Withdraw: maxWithdrawAllowed exceeded"); + await expect(stakingHbbft.connect(delegatorAddress).withdraw(initialStakingAddresses[1], restOfAmount + 1n)) + .to.be.revertedWith("Withdraw: maxWithdrawAllowed exceeded"); + await stakingHbbft.connect(delegatorAddress).withdraw(initialStakingAddresses[1], restOfAmount); - (await stakingHbbft.stakeAmountByCurrentEpoch(initialStakingAddresses[1], delegatorAddress.address)).should.be.equal(BigNumber.from(0)); - (await stakingHbbft.stakeAmount(initialStakingAddresses[1], delegatorAddress.address)).should.be.equal(BigNumber.from(0)); - (await stakingHbbft.orderedWithdrawAmount(initialStakingAddresses[1], delegatorAddress.address)).should.be.equal(orderedAmount); - (await stakingHbbft.poolDelegators(initialStakingAddresses[1])).length.should.be.equal(0); - (await stakingHbbft.poolDelegatorsInactive(initialStakingAddresses[1])).should.be.deep.equal([delegatorAddress.address]); + expect(await stakingHbbft.stakeAmountByCurrentEpoch(initialStakingAddresses[1], delegatorAddress.address)).to.be.equal(0n); + expect(await stakingHbbft.stakeAmount(initialStakingAddresses[1], delegatorAddress.address)).to.be.equal(0n); + expect(await stakingHbbft.orderedWithdrawAmount(initialStakingAddresses[1], delegatorAddress.address)).to.be.equal(orderedAmount); + expect(await stakingHbbft.poolDelegators(initialStakingAddresses[1])).to.be.empty; + expect(await stakingHbbft.poolDelegatorsInactive(initialStakingAddresses[1])).to.be.deep.equal([delegatorAddress.address]); }); it('should decrease likelihood', async () => { const { stakingHbbft } = await helpers.loadFixture(deployContractsFixture); let likelihoodInfo = await stakingHbbft.getPoolsLikelihood(); - likelihoodInfo.sum.should.be.equal(BigNumber.from(0)); + expect(likelihoodInfo.sum).to.be.equal(0n); await stakingHbbft.connect(await ethers.getSigner(initialStakingAddresses[1])).stake(initialStakingAddresses[1], { value: stakeAmount }); likelihoodInfo = await stakingHbbft.getPoolsLikelihood(); - likelihoodInfo.likelihoods[0].should.be.equal(stakeAmount); - likelihoodInfo.sum.should.be.equal(stakeAmount); + expect(likelihoodInfo.likelihoods[0]).to.be.equal(stakeAmount); + expect(likelihoodInfo.sum).to.be.equal(stakeAmount); - await stakingHbbft.connect(await ethers.getSigner(initialStakingAddresses[1])).withdraw(initialStakingAddresses[1], stakeAmount.div(BigNumber.from(2))); + await stakingHbbft.connect(await ethers.getSigner(initialStakingAddresses[1])).withdraw(initialStakingAddresses[1], stakeAmount / 2n); likelihoodInfo = await stakingHbbft.getPoolsLikelihood(); - likelihoodInfo.likelihoods[0].should.be.equal(stakeAmount.div(BigNumber.from(2))); - likelihoodInfo.sum.should.be.equal(stakeAmount.div(BigNumber.from(2))); + expect(likelihoodInfo.likelihoods[0]).to.be.equal(stakeAmount / 2n); + expect(likelihoodInfo.sum).to.be.equal(stakeAmount / 2n); }); - // TODO: add unit tests for native coin withdrawal }); describe('recoverAbandonedStakes()', async () => { - let stakingPool: SignerWithAddress; - let stakers: SignerWithAddress[]; + let stakingPool: HardhatEthersSigner; + let stakers: HardhatEthersSigner[]; beforeEach(async () => { stakingPool = await ethers.getSigner(initialStakingAddresses[0]); @@ -2648,8 +1760,8 @@ describe('StakingHbbft', () => { async function stake( stakingContract: StakingHbbftMock, poolAddress: string, - amount: BigNumber, - stakers: SignerWithAddress[] + amount: bigint, + stakers: HardhatEthersSigner[] ) { for (let staker of stakers) { expect(await stakingContract.connect(staker).stake(poolAddress, { value: amount })); @@ -2668,9 +1780,16 @@ describe('StakingHbbft', () => { const poolsInactive = await stakingContract.getPoolsInactive(); - expect(poolsInactive.includes(poolAddress)).to.be.true; + expect(poolsInactive).to.include(poolAddress); } + it("should revert with invalid gas price", async () => { + const { stakingHbbft } = await helpers.loadFixture(deployContractsFixture); + + await expect(stakingHbbft.recoverAbandonedStakes({ gasPrice: 0n })) + .to.be.revertedWith("GasPrice is 0"); + }); + it("should revert if there is no inactive pools", async () => { const { stakingHbbft } = await helpers.loadFixture(deployContractsFixture); @@ -2686,7 +1805,7 @@ describe('StakingHbbft', () => { delegatorMinStake } = await helpers.loadFixture(deployContractsFixture); - const expectedTotalStakes = candidateMinStake.add(delegatorMinStake.mul(stakers.length)); + const expectedTotalStakes = candidateMinStake + delegatorMinStake * BigInt(stakers.length); await stake(stakingHbbft, stakingPool.address, candidateMinStake, [stakingPool]) await stake(stakingHbbft, stakingPool.address, delegatorMinStake, stakers); @@ -2711,11 +1830,11 @@ describe('StakingHbbft', () => { await blockRewardHbbft.setGovernanceAddress(owner.address); const governanceAddress = await blockRewardHbbft.governancePotAddress(); - const reinsertAddress = blockRewardHbbft.address; + const reinsertAddress = await blockRewardHbbft.getAddress(); expect(governanceAddress).to.equal(owner.address); - const expectedTotalStakes = candidateMinStake.add(delegatorMinStake.mul(stakers.length)); + const expectedTotalStakes = candidateMinStake + delegatorMinStake * BigInt(stakers.length); const caller = accounts[5]; await stake(stakingHbbft, stakingPool.address, candidateMinStake, [stakingPool]) @@ -2723,23 +1842,25 @@ describe('StakingHbbft', () => { expect(await stakingHbbft.stakeAmountTotal(stakingPool.address)).to.be.equal(expectedTotalStakes); await setValidatorInactive(stakingHbbft, validatorSetHbbft, stakingPool.address); - await helpers.time.increase(validatorInactivityThreshold + 3600); + await helpers.time.increase(validatorInactivityThreshold + 3600n); expect(await validatorSetHbbft.isValidatorAbandoned(stakingPool.address)).to.be.true; - const expectedGovernanceShare = expectedTotalStakes.div(2); - const expectedReinsertShare = expectedTotalStakes.sub(expectedGovernanceShare); + const expectedGovernanceShare = expectedTotalStakes / 2n; + const expectedReinsertShare = expectedTotalStakes - expectedGovernanceShare; + + const tx = stakingHbbft.connect(caller).recoverAbandonedStakes(); - await expect(stakingHbbft.connect(caller).recoverAbandonedStakes()) + await expect(tx) .to.emit(stakingHbbft, "GatherAbandonedStakes") .withArgs(caller.address, stakingPool.address, expectedTotalStakes) .and .to.emit(stakingHbbft, "RecoverAbandonedStakes") .withArgs(caller.address, expectedReinsertShare, expectedGovernanceShare) - .and - .to.changeEtherBalances( - [stakingHbbft.address, reinsertAddress, governanceAddress], - [expectedTotalStakes.mul(-1), expectedReinsertShare, expectedGovernanceShare] - ); + + await expect(tx).to.changeEtherBalances( + [await stakingHbbft.getAddress(), reinsertAddress, governanceAddress], + [-expectedTotalStakes, expectedReinsertShare, expectedGovernanceShare] + ); expect(await stakingHbbft.stakeAmountTotal(stakingPool.address)).to.be.equal(0); }); @@ -2757,15 +1878,13 @@ describe('StakingHbbft', () => { await setValidatorInactive(stakingHbbft, validatorSetHbbft, stakingPool.address); - await helpers.time.increase(validatorInactivityThreshold + 3600); + await helpers.time.increase(validatorInactivityThreshold + 3600n); expect(await validatorSetHbbft.isValidatorAbandoned(stakingPool.address)).to.be.true; await expect(stakingHbbft.recoverAbandonedStakes()) .to.emit(stakingHbbft, "RecoverAbandonedStakes"); - const inactivePools = await stakingHbbft.getPoolsInactive(); - - expect(inactivePools.includes(stakingPool.address)).to.be.false; + expect(await stakingHbbft.getPoolsInactive()).to.not.include(stakingPool.address); expect(await stakingHbbft.abandonedAndRemoved(stakingPool.address)).to.be.true; }); @@ -2782,7 +1901,7 @@ describe('StakingHbbft', () => { await setValidatorInactive(stakingHbbft, validatorSetHbbft, stakingPool.address); - await helpers.time.increase(validatorInactivityThreshold + 3600); + await helpers.time.increase(validatorInactivityThreshold + 3600n); expect(await validatorSetHbbft.isValidatorAbandoned(stakingPool.address)).to.be.true; await expect(stakingHbbft.recoverAbandonedStakes()) @@ -2808,7 +1927,7 @@ describe('StakingHbbft', () => { await setValidatorInactive(stakingHbbft, validatorSetHbbft, stakingPool.address); - await helpers.time.increase(validatorInactivityThreshold + 3600); + await helpers.time.increase(validatorInactivityThreshold + 3600n); expect(await validatorSetHbbft.isValidatorAbandoned(stakingPool.address)).to.be.true; await expect(stakingHbbft.recoverAbandonedStakes()) @@ -2834,7 +1953,7 @@ describe('StakingHbbft', () => { await setValidatorInactive(stakingHbbft, validatorSetHbbft, stakingPool.address); - await helpers.time.increase(validatorInactivityThreshold + 3600); + await helpers.time.increase(validatorInactivityThreshold + 3600n); expect(await validatorSetHbbft.isValidatorAbandoned(stakingPool.address)).to.be.true; await expect(stakingHbbft.recoverAbandonedStakes()) @@ -2852,70 +1971,419 @@ describe('StakingHbbft', () => { }); }); - describe('setStakingTransitionTimeframeLength()', async () => { - it('should set staking transition time frame length', async () => { - const { - stakingHbbft, - } = await helpers.loadFixture(deployContractsFixture); - - // this should succeed. - await stakingHbbft.setStakingTransitionTimeframeLength('300'); - (await stakingHbbft.stakingTransitionTimeframeLength()).should.be.equal('300'); + describe('restake()', async () => { + it('should allow calling only to BlockReward contract', async () => { + const { stakingHbbft } = await helpers.loadFixture(deployContractsFixture); + + const caller = accounts[5]; + await expect(stakingHbbft.connect(caller).restake(ethers.ZeroAddress, 0n)) + .to.be.revertedWith("Only BlockReward"); + }); + + it('should do nothing if zero value provided', async () => { + const { stakingHbbft, blockRewardHbbft } = await helpers.loadFixture(deployContractsFixture); + + const caller = await impersonateAcc(await blockRewardHbbft.getAddress()); + + await expect(stakingHbbft.connect(caller).restake( + initialStakingAddresses[1], + 0n, + { value: 0n } + )).to.not.emit(stakingHbbft, "RestakeReward"); }); - it('should not set staking transition time frame length to low value', async () => { + it('should restake all rewards to validator without delegators', async () => { const { stakingHbbft, + blockRewardHbbft, + validatorSetHbbft, + candidateMinStake } = await helpers.loadFixture(deployContractsFixture); - await expect(stakingHbbft.setStakingTransitionTimeframeLength('9')).be.revertedWith("The transition timeframe must be longer than 10"); + + expect(await ethers.provider.getBalance(await blockRewardHbbft.getAddress())).to.be.equal(0n); + + for (let i = 0; i < initialStakingAddresses.length; ++i) { + const pool = await ethers.getSigner(initialStakingAddresses[i]); + + await stakingHbbft.connect(pool).stake(pool.address, { value: candidateMinStake }); + expect(await stakingHbbft.stakeAmountTotal(pool.address)).to.be.eq(candidateMinStake); + } + + let systemSigner = await impersonateAcc(SystemAccountAddress); + + await blockRewardHbbft.connect(systemSigner).reward(true); + await blockRewardHbbft.connect(systemSigner).reward(true); + + await helpers.stopImpersonatingAccount(SystemAccountAddress); + + const fixedEpochEndTime = await stakingHbbft.stakingFixedEpochEndTime(); + await helpers.time.increaseTo(fixedEpochEndTime + 1n); + await helpers.mine(1); + + const deltaPotValue = ethers.parseEther('50'); + await blockRewardHbbft.addToDeltaPot({ value: deltaPotValue }); + expect(await blockRewardHbbft.deltaPot()).to.be.equal(deltaPotValue); + + const validators = await validatorSetHbbft.getValidators(); + const potsShares = await blockRewardHbbft.getPotsShares(validators.length); + + const validatorRewards = potsShares.totalRewards - potsShares.governancePotAmount; + const poolReward = validatorRewards / BigInt(validators.length); + + systemSigner = await impersonateAcc(SystemAccountAddress); + await blockRewardHbbft.connect(systemSigner).reward(true); + await helpers.stopImpersonatingAccount(SystemAccountAddress); + + for (let i = 0; i < initialStakingAddresses.length; ++i) { + const pool = await ethers.getSigner(initialStakingAddresses[i]); + + expect(await stakingHbbft.stakeAmountTotal(pool.address)).to.be.eq(candidateMinStake + poolReward); + } }); - it('should not set staking transition time frame length to high value', async () => { + it('should restake delegators rewards according to stakes', async () => { const { stakingHbbft, + blockRewardHbbft, + validatorSetHbbft, + candidateMinStake, } = await helpers.loadFixture(deployContractsFixture); - await expect(stakingHbbft.setStakingTransitionTimeframeLength('100000')).be.revertedWith("The transition timeframe must be smaller than the epoch duration"); + + expect(await ethers.provider.getBalance(await blockRewardHbbft.getAddress())).to.be.equal(0n); + + for (let i = 0; i < initialStakingAddresses.length; ++i) { + const pool = await ethers.getSigner(initialStakingAddresses[i]); + + await stakingHbbft.connect(pool).stake(pool.address, { value: candidateMinStake }); + expect(await stakingHbbft.stakeAmountTotal(pool.address)).to.be.eq(candidateMinStake); + } + + let systemSigner = await impersonateAcc(SystemAccountAddress); + await blockRewardHbbft.connect(systemSigner).reward(true); + await helpers.stopImpersonatingAccount(SystemAccountAddress); + + interface StakeRecord { + delegator: string; + pool: string; + stake: bigint; + } + + const delegators = accounts.slice(15, 20); + const stakeRecords = new Array(); + const poolTotalStakes = new Map(); + + for (const _pool of initialStakingAddresses) { + let _poolTotalStake = candidateMinStake; + + for (const _delegator of delegators) { + const stake = ethers.parseEther(_.random(1, 10).toString()); + + stakeRecords.push({ delegator: _delegator.address, pool: _pool, stake: stake }); + + _poolTotalStake += stake; + + await stakingHbbft.connect(_delegator).stake(_pool, { value: stake }); + expect(await stakingHbbft.stakeAmount(_pool, _delegator.address)).to.equal(stake); + } + + poolTotalStakes.set(_pool, _poolTotalStake); + + expect(await stakingHbbft.stakeAmountTotal(_pool)).to.be.eq(_poolTotalStake); + } + + systemSigner = await impersonateAcc(SystemAccountAddress); + await blockRewardHbbft.connect(systemSigner).reward(true); + await helpers.stopImpersonatingAccount(SystemAccountAddress); + + const fixedEpochEndTime = await stakingHbbft.stakingFixedEpochEndTime(); + await helpers.time.increaseTo(fixedEpochEndTime + 1n); + await helpers.mine(1); + + const epoch = await stakingHbbft.stakingEpoch(); + + const deltaPotValue = ethers.parseEther('10'); + await blockRewardHbbft.addToDeltaPot({ value: deltaPotValue }); + expect(await blockRewardHbbft.deltaPot()).to.be.equal(deltaPotValue); + + const validators = await validatorSetHbbft.getValidators(); + const potsShares = await blockRewardHbbft.getPotsShares(validators.length); + + const validatorRewards = potsShares.totalRewards - potsShares.governancePotAmount; + const poolReward = validatorRewards / BigInt(validators.length); + + systemSigner = await impersonateAcc(SystemAccountAddress); + await blockRewardHbbft.connect(systemSigner).reward(true); + await helpers.stopImpersonatingAccount(SystemAccountAddress); + + const validatorMinRewardPercent = await blockRewardHbbft.validatorMinRewardPercent(epoch); + + for (const _stakeRecord of stakeRecords) { + let validatorShare = 0n; + let delegatorShare = 0n; + + const poolTotalStake = poolTotalStakes.get(_stakeRecord.pool)!; + const delegatorsStake = poolTotalStake - candidateMinStake; + + const minRewardPercentExceeded = candidateMinStake * (100n - validatorMinRewardPercent) + > delegatorsStake * validatorMinRewardPercent; + + if (minRewardPercentExceeded) { + validatorShare = (poolReward * candidateMinStake) / poolTotalStake; + delegatorShare = (poolReward * _stakeRecord.stake) / poolTotalStake; + } else { + validatorShare = (poolReward * validatorMinRewardPercent) / 100n; + delegatorShare = (poolReward * _stakeRecord.stake * (100n - validatorMinRewardPercent)) + / (delegatorsStake * 100n); + } + + expect( + await stakingHbbft.stakeAmount(_stakeRecord.pool, _stakeRecord.pool) + ).to.be.closeTo(candidateMinStake + validatorShare, 100n); + + expect( + await stakingHbbft.stakeAmount(_stakeRecord.pool, _stakeRecord.delegator) + ).to.be.closeTo(_stakeRecord.stake + delegatorShare, 100n); + } + }); + }); + + describe('setStakingTransitionTimeframeLength()', async () => { + it('should allow calling only to contract owner', async () => { + const { stakingHbbft } = await helpers.loadFixture(deployContractsFixture); + + const caller = accounts[5]; + await expect(stakingHbbft.connect(caller).setStakingTransitionTimeframeLength(300n)) + .to.be.revertedWith("Ownable: caller is not the owner"); + }); + + it('should set staking transition time frame length', async () => { + const { stakingHbbft } = await helpers.loadFixture(deployContractsFixture); + + await stakingHbbft.setStakingTransitionTimeframeLength(300n); + expect(await stakingHbbft.stakingTransitionTimeframeLength()).to.be.equal(300n); + }); + + it('should not set staking transition time frame length to low value', async () => { + const { stakingHbbft } = await helpers.loadFixture(deployContractsFixture); + + await expect(stakingHbbft.setStakingTransitionTimeframeLength(9n)) + .to.be.revertedWith("The transition timeframe must be longer than 10"); + }); + + it('should not set staking transition time frame length to high value', async () => { + const { stakingHbbft } = await helpers.loadFixture(deployContractsFixture); + + await expect(stakingHbbft.setStakingTransitionTimeframeLength(100000n)) + .to.be.revertedWith("The transition timeframe must be smaller than the epoch duration"); }); }); - + describe('setStakingFixedEpochDuration()', async () => { + it('should allow calling only to contract owner', async () => { + const { stakingHbbft } = await helpers.loadFixture(deployContractsFixture); - describe('setStakingFixedEpochDuration()', async () => { - it('should set staking fixed epoch transition', async () => { - const { - stakingHbbft, - } = await helpers.loadFixture(deployContractsFixture); - - // this should succeed. - await stakingHbbft.setStakingFixedEpochDuration('600000'); - (await stakingHbbft.stakingFixedEpochDuration()).should.be.equal('600000'); + const caller = accounts[5]; + await expect(stakingHbbft.connect(caller).setStakingFixedEpochDuration(600000n)) + .to.be.revertedWith("Ownable: caller is not the owner"); + }); + + it('should set staking fixed epoch transition', async () => { + const { stakingHbbft } = await helpers.loadFixture(deployContractsFixture); + + await stakingHbbft.setStakingFixedEpochDuration(600000n); + expect(await stakingHbbft.stakingFixedEpochDuration()).to.be.equal(600000n); + }); + + it('should not set staking transition time frame length to low value', async () => { + const { stakingHbbft } = await helpers.loadFixture(deployContractsFixture); + + let tranitionTimeFrame = await stakingHbbft.stakingTransitionTimeframeLength(); + await expect(stakingHbbft.setStakingFixedEpochDuration(tranitionTimeFrame)) + .to.be.revertedWith("The fixed epoch duration timeframe must be greater than the transition timeframe length"); + }); + }); + + describe('setCandidateMinStake()', async () => { + it('should allow calling only to contract owner', async () => { + const { stakingHbbft } = await helpers.loadFixture(deployContractsFixture); + + const caller = accounts[5]; + await expect(stakingHbbft.connect(caller).setCandidateMinStake(ethers.parseEther('10'))) + .to.be.revertedWith("Ownable: caller is not the owner"); + }); + + it('should set candidate min stake', async () => { + const { stakingHbbft } = await helpers.loadFixture(deployContractsFixture); + + const minStakeValue = ethers.parseEther('15') + await stakingHbbft.setCandidateMinStake(minStakeValue); + expect(await stakingHbbft.candidateMinStake()).to.be.equal(minStakeValue); + }); + }); + + describe('setDelegatorMinStake()', async () => { + it('should allow calling only to contract owner', async () => { + const { stakingHbbft } = await helpers.loadFixture(deployContractsFixture); + + const caller = accounts[5]; + await expect(stakingHbbft.connect(caller).setDelegatorMinStake(ethers.parseEther('10'))) + .to.be.revertedWith("Ownable: caller is not the owner"); + }); + + it('should set delegator min stake', async () => { + const { stakingHbbft } = await helpers.loadFixture(deployContractsFixture); + + const minStakeValue = ethers.parseEther('15') + await stakingHbbft.setDelegatorMinStake(minStakeValue); + expect(await stakingHbbft.delegatorMinStake()).to.be.equal(minStakeValue); + }); + }); + + describe('snapshotPoolStakeAmounts()', async () => { + it('should allow calling only by BlockReward contract', async () => { + const { stakingHbbft } = await helpers.loadFixture(deployContractsFixture); + + const caller = accounts[5]; + await expect(stakingHbbft.connect(caller).snapshotPoolStakeAmounts(0n, initialStakingAddresses[1])) + .to.be.revertedWith("Only BlockReward"); }); - it('should not set staking transition time frame length to low value', async () => { + it('should create validator stake snapshot after epoch close', async () => { const { stakingHbbft, + blockRewardHbbft, + candidateMinStake, + delegatorMinStake } = await helpers.loadFixture(deployContractsFixture); - let tranitionTimeFrame = await stakingHbbft.stakingTransitionTimeframeLength(); - await expect(stakingHbbft.setStakingFixedEpochDuration(tranitionTimeFrame)).be.revertedWith("The fixed epoch duration timeframe must be greater than the transition timeframe length"); + const delegator = accounts[10]; + + let stakingEpoch = await stakingHbbft.stakingEpoch(); + for (let i = 0; i < initialStakingAddresses.length; ++i) { + const pool = await ethers.getSigner(initialStakingAddresses[i]); + const stakeAmount = BigInt(i + 1) * delegatorMinStake; + + await stakingHbbft.connect(pool).stake(pool.address, { value: candidateMinStake }); + + await stakingHbbft.connect(delegator).stake(pool, { value: stakeAmount }); + expect(await stakingHbbft.stakeAmountTotal(pool)).to.be.equal(candidateMinStake + stakeAmount); + expect(await stakingHbbft.snapshotPoolTotalStakeAmount(stakingEpoch, pool)).to.be.eq(0n); + expect(await stakingHbbft.snapshotPoolValidatorStakeAmount(stakingEpoch, pool.address)).to.be.eq(0n); + } + + await callReward(blockRewardHbbft, true); + stakingEpoch = await stakingHbbft.stakingEpoch(); + + for (let i = 0; i < initialStakingAddresses.length; ++i) { + const pool = await ethers.getSigner(initialStakingAddresses[i]); + const stakeAmount = BigInt(i + 1) * delegatorMinStake; + + expect(await stakingHbbft.stakeAmountTotal(pool)).to.be.equal(candidateMinStake + stakeAmount); + expect(await stakingHbbft.snapshotPoolTotalStakeAmount(stakingEpoch, pool)).to.be.eq(candidateMinStake + stakeAmount); + expect(await stakingHbbft.getPoolValidatorStakeAmount(stakingEpoch, pool.address)).to.be.eq(candidateMinStake); + } }); }); - // TODO: ...add other tests... + describe('other functions', async () => { + it('should restrict calling notifyKeyGenFailed to validator set contract', async () => { + const { stakingHbbft } = await helpers.loadFixture(deployContractsFixture); + const caller = accounts[10]; + + await expect(stakingHbbft.connect(caller).notifyKeyGenFailed()) + .to.be.revertedWith("Only ValidatorSet"); + }); + + it('should restrict calling notifyNetworkOfftimeDetected to validator set contract', async () => { + const { stakingHbbft } = await helpers.loadFixture(deployContractsFixture); + const caller = accounts[10]; + + await expect(stakingHbbft.connect(caller).notifyNetworkOfftimeDetected(0n)) + .to.be.revertedWith("Only ValidatorSet"); + }); + + it('should restrict calling notifyAvailability to validator set contract', async () => { + const { stakingHbbft } = await helpers.loadFixture(deployContractsFixture); + const caller = accounts[10]; + + await expect(stakingHbbft.connect(caller).notifyAvailability(initialStakingAddresses[1])) + .to.be.revertedWith("Only ValidatorSet"); + }); + + it('should restrict calling setStakingEpochStartTime to validator set contract', async () => { + const { stakingHbbft } = await helpers.loadFixture(deployContractsFixture); + const caller = accounts[10]; + + await expect(stakingHbbft.connect(caller).setStakingEpochStartTime(0n)) + .to.be.revertedWith("Only ValidatorSet"); + }); + + it('should restrict calling setValidatorInternetAddress to validator set contract', async () => { + const { stakingHbbft } = await helpers.loadFixture(deployContractsFixture); + const caller = accounts[10]; + + await expect(stakingHbbft.connect(caller).setValidatorInternetAddress( + ethers.ZeroAddress, + ZeroIpAddress, + '0x6987', + )).to.be.revertedWith("Only ValidatorSet"); + }); + + it('should update validator ip:port using setValidatorInternetAddress', async () => { + const { stakingHbbft, validatorSetHbbft } = await helpers.loadFixture(deployContractsFixture); + + const validator = initialValidators[1]; + const ipAddress = ethers.zeroPadBytes("0xfe", 16); + const port = '0x6987'; + + const validatorSetSigner = await impersonateAcc(await validatorSetHbbft.getAddress()); + expect(await stakingHbbft.connect(validatorSetSigner).setValidatorInternetAddress(validator, ipAddress, port)); + await helpers.stopImpersonatingAccount(validatorSetSigner.address); + + const poolInfo = await stakingHbbft.poolInfo(validator); + expect(poolInfo.internetAddress).to.equal(ipAddress); + expect(poolInfo.port).to.equal(port); + }); + + it('should update own pool info using setPoolInfo', async () => { + const { stakingHbbft } = await helpers.loadFixture(deployContractsFixture); + + const validator = await ethers.getSigner(initialValidators[1]); + const publicKey = ethers.zeroPadBytes("0xdeadbeef", 64); + const ipAddress = ethers.zeroPadBytes("0xfe", 16); + const port = '0x6987'; + + expect(await stakingHbbft.connect(validator).setPoolInfo( + publicKey, + ipAddress, + port, + )); + + const poolInfo = await stakingHbbft.poolInfo(validator); + expect(poolInfo.publicKey).to.equal(publicKey); + expect(poolInfo.internetAddress).to.equal(ipAddress); + expect(poolInfo.port).to.equal(port); + }); + }); async function callReward(blockRewardContract: BlockRewardHbbftMock, isEpochEndBlock: boolean) { - await blockRewardContract.setSystemAddress(owner.address); + const systemSigner = await impersonateAcc(SystemAccountAddress); + + const tx = await blockRewardContract.connect(systemSigner).reward(isEpochEndBlock); + const receipt = await tx.wait(); - const { events } = await (await blockRewardContract.connect(owner).reward(isEpochEndBlock)).wait(); - if (events!.length > 0) { + await helpers.stopImpersonatingAccount(SystemAccountAddress); + + if (receipt!.logs.length > 0) { // Emulate minting native coins - events?.[0].event?.should.be.equal("CoinsRewarded"); - const totalReward = events?.[0].args?.rewards; + const event = blockRewardContract.interface.parseLog(receipt!.logs[0]); + + expect(event!.name).to.be.equal("CoinsRewarded"); + + const totalReward = event!.args.rewards; await blockRewardContract.connect(owner).sendCoins({ value: totalReward }); } - - await blockRewardContract.setSystemAddress('0xffffFFFfFFffffffffffffffFfFFFfffFFFfFFfE'); } // time travels forward to the beginning of the next transition, @@ -2939,7 +2407,7 @@ describe('StakingHbbft', () => { // console.log('tsBefore:', tsBeforeTimeTravel.toString()); // console.log('endTimeOfCurrentEpoch:', endTimeOfCurrentEpoch.toString()); - if (endTimeOfCurrentEpoch.lt(tsBeforeTimeTravel)) { + if (endTimeOfCurrentEpoch < tsBeforeTimeTravel) { console.error('Trying to timetravel back in time !!'); } @@ -2948,10 +2416,6 @@ describe('StakingHbbft', () => { } }); -function random(low: number, high: number) { - return Math.floor(Math.random() * (high - low) + low); -} - function shuffle(a: number[]) { var j, x, i; for (i = a.length - 1; i > 0; i--) { diff --git a/test/TransferUtils.ts b/test/TransferUtils.ts new file mode 100644 index 00000000..50f1c6cc --- /dev/null +++ b/test/TransferUtils.ts @@ -0,0 +1,95 @@ +import { ethers } from "hardhat"; +import { expect } from "chai"; +import { HardhatEthersSigner } from "@nomicfoundation/hardhat-ethers/signers"; +import * as helpers from "@nomicfoundation/hardhat-network-helpers"; + +describe("Transfer utils library", function () { + let users: HardhatEthersSigner[]; + + before(async function () { + users = await ethers.getSigners(); + }); + + async function deployContracts() { + const transferUtilsFactory = await ethers.getContractFactory("TransferUtilsMock"); + const transferUtils = await transferUtilsFactory.deploy(); + await transferUtils.waitForDeployment(); + + const mockReceiverFactory = await ethers.getContractFactory("EtherReceiverMock"); + const mockReceiver = await mockReceiverFactory.deploy(); + await mockReceiver.waitForDeployment(); + + const balance = ethers.parseEther("10") + + await users[1].sendTransaction({ + to: await transferUtils.getAddress(), + value: balance, + }); + + await mockReceiver.toggleReceive(false); + + return { transferUtils, mockReceiver, balance }; + } + + it("should revert transferNative with insufficient contract balance", async function () { + const { transferUtils, balance } = await helpers.loadFixture(deployContracts); + + const transferReceiver = users[1]; + + await expect( + transferUtils.transferNative( + transferReceiver.address, + balance * 2n, + ) + ).revertedWithCustomError(transferUtils, "InsufficientBalance"); + }); + + it("should revert transferNative if low level call failed", async function () { + const { transferUtils, mockReceiver, balance } = await helpers.loadFixture(deployContracts); + + expect(await mockReceiver.toggleReceive(false)); + + await expect(transferUtils.transferNative(await mockReceiver.getAddress(), balance)) + .revertedWithCustomError(transferUtils, "TransferFailed") + .withArgs(await mockReceiver.getAddress(), balance); + }); + + it("should transfer ether using transferNative", async function () { + const { transferUtils, mockReceiver, balance } = await helpers.loadFixture(deployContracts); + const receiverAddress = await mockReceiver.getAddress(); + + expect(await mockReceiver.toggleReceive(true)); + + await expect(() => transferUtils.transferNative(receiverAddress, balance)) + .to.changeEtherBalances( + [transferUtils, mockReceiver], + [-balance, balance] + ); + }); + + it("should transfer using transferNativeEnsure", async function () { + const { transferUtils, mockReceiver, balance } = await helpers.loadFixture(deployContracts); + const receiverAddress = await mockReceiver.getAddress(); + + expect(await mockReceiver.toggleReceive(true)); + + await expect(() => transferUtils.transferNativeEnsure(receiverAddress, balance)) + .to.changeEtherBalances( + [transferUtils, mockReceiver], + [-balance, balance] + ); + }); + + it("should ensure token transfer using Sacrifice contract", async function () { + const { transferUtils, mockReceiver, balance } = await helpers.loadFixture(deployContracts); + const receiverAddress = await mockReceiver.getAddress(); + + expect(await mockReceiver.toggleReceive(false)); + + await expect(() => transferUtils.transferNativeEnsure(receiverAddress, balance)) + .to.changeEtherBalances( + [transferUtils, mockReceiver], + [-balance, balance] + ); + }); +}); diff --git a/test/TxPermissionHbbft.ts b/test/TxPermissionHbbft.ts index 1ed3a463..387c226d 100644 --- a/test/TxPermissionHbbft.ts +++ b/test/TxPermissionHbbft.ts @@ -1,8 +1,8 @@ import { ethers, upgrades } from "hardhat"; -import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers"; import { expect } from "chai"; +import { HardhatEthersSigner } from "@nomicfoundation/hardhat-ethers/signers"; import * as helpers from "@nomicfoundation/hardhat-network-helpers"; -import fp from 'lodash/fp'; +import fp from "lodash/fp"; import { CertifierHbbft, @@ -13,13 +13,14 @@ import { ConnectivityTrackerHbbft } from "../src/types"; -const testdata = require('./testhelpers/data'); +import { getTestPartNAcks } from './testhelpers/data'; -const validatorInactivityThreshold = 365 * 86400 // 1 year -const minReportAgeBlocks = 10; +const EmptyBytes = ethers.hexlify(new Uint8Array()); +const validatorInactivityThreshold = BigInt(365 * 86400); // 1 year +const minReportAgeBlocks = 10n; const contractName = "TX_PERMISSION_CONTRACT"; -const contractNameHash = ethers.utils.keccak256(ethers.utils.toUtf8Bytes(contractName)); +const contractNameHash = ethers.keccak256(ethers.toUtf8Bytes(contractName)); const contractVersion = 3; enum AllowedTxTypeMask { @@ -41,8 +42,8 @@ enum KeyGenMode { } describe('TxPermissionHbbft', () => { - let owner: SignerWithAddress; - let accounts: SignerWithAddress[]; + let owner: HardhatEthersSigner; + let accounts: HardhatEthersSigner[]; let allowedSenders: string[]; let accountAddresses: string[]; @@ -53,10 +54,10 @@ describe('TxPermissionHbbft', () => { async function deployContractsFixture() { const stubAddress = accountAddresses[0]; - const { parts, acks } = testdata.getTestPartNAcks(); + const { parts, acks } = getTestPartNAcks(); const ValidatorSetFactory = await ethers.getContractFactory("ValidatorSetHbbftMock"); - const validatorSetHbbft = await upgrades.deployProxy( + const validatorSetHbbftProxy = await upgrades.deployProxy( ValidatorSetFactory, [ owner.address, @@ -69,25 +70,27 @@ describe('TxPermissionHbbft', () => { initialStakingAddresses, // _initialStakingAddresses ], { initializer: 'initialize' } - ) as ValidatorSetHbbftMock; + ); + + await validatorSetHbbftProxy.waitForDeployment(); let stakingParams = { - _validatorSetContract: validatorSetHbbft.address, + _validatorSetContract: await validatorSetHbbftProxy.getAddress(), _initialStakingAddresses: initialStakingAddresses, - _delegatorMinStake: ethers.utils.parseEther('1'), - _candidateMinStake: ethers.utils.parseEther('1'), - _maxStake: ethers.utils.parseEther('100000'), - _stakingFixedEpochDuration: 86400, - _stakingTransitionTimeframeLength: 3600, - _stakingWithdrawDisallowPeriod: 1 + _delegatorMinStake: ethers.parseEther('1'), + _candidateMinStake: ethers.parseEther('1'), + _maxStake: ethers.parseEther('100000'), + _stakingFixedEpochDuration: 86400n, + _stakingTransitionTimeframeLength: 3600n, + _stakingWithdrawDisallowPeriod: 1n }; let initialValidatorsPubKeys: string[] = []; let initialValidatorsIpAddresses: string[] = []; for (let i = 0; i < initialStakingAddresses.length; i++) { - initialValidatorsPubKeys.push(ethers.Wallet.createRandom().publicKey); - initialValidatorsIpAddresses.push('0x00000000000000000000000000000000'); + initialValidatorsPubKeys.push(ethers.Wallet.createRandom().signingKey.publicKey); + initialValidatorsIpAddresses.push(ethers.zeroPadBytes("0x00", 16)); } let initialValidatorsPubKeysSplit = fp.flatMap((x: string) => [x.substring(0, 66), '0x' + x.substring(66, 130)]) @@ -95,7 +98,7 @@ describe('TxPermissionHbbft', () => { const StakingHbbftFactory = await ethers.getContractFactory("StakingHbbftMock"); //Deploy StakingHbbft contract - const stakingHbbft = await upgrades.deployProxy( + const stakingHbbftProxy = await upgrades.deployProxy( StakingHbbftFactory, [ owner.address, @@ -104,76 +107,101 @@ describe('TxPermissionHbbft', () => { initialValidatorsIpAddresses // _internetAddresses ], { initializer: 'initialize' } - ) as StakingHbbftMock; + ); + + await stakingHbbftProxy.waitForDeployment(); const KeyGenFactory = await ethers.getContractFactory("KeyGenHistory"); - const keyGenHistory = await upgrades.deployProxy( + const keyGenHistoryProxy = await upgrades.deployProxy( KeyGenFactory, [ owner.address, - validatorSetHbbft.address, + await validatorSetHbbftProxy.getAddress(), initialValidators, parts, acks ], { initializer: 'initialize' } - ) as KeyGenHistory; + ); + + await keyGenHistoryProxy.waitForDeployment(); const CertifierFactory = await ethers.getContractFactory("CertifierHbbft"); - const certifier = await upgrades.deployProxy( + const certifierProxy = await upgrades.deployProxy( CertifierFactory, [ [owner.address], - validatorSetHbbft.address, + await validatorSetHbbftProxy.getAddress(), owner.address ], { initializer: 'initialize' } - ) as CertifierHbbft; + ); + + await certifierProxy.waitForDeployment(); const BlockRewardHbbftFactory = await ethers.getContractFactory("BlockRewardHbbftMock"); - const blockRewardHbbft = await upgrades.deployProxy( + const blockRewardHbbftProxy = await upgrades.deployProxy( BlockRewardHbbftFactory, [ owner.address, - validatorSetHbbft.address, + await validatorSetHbbftProxy.getAddress(), stubAddress ], { initializer: 'initialize' } ); - await blockRewardHbbft.deployed(); + await blockRewardHbbftProxy.waitForDeployment(); const ConnectivityTrackerFactory = await ethers.getContractFactory("ConnectivityTrackerHbbft"); - const connectivityTracker = await upgrades.deployProxy( + const connectivityTrackerProxy = await upgrades.deployProxy( ConnectivityTrackerFactory, [ owner.address, - validatorSetHbbft.address, - stakingHbbft.address, - blockRewardHbbft.address, + await validatorSetHbbftProxy.getAddress(), + await stakingHbbftProxy.getAddress(), + await blockRewardHbbftProxy.getAddress(), minReportAgeBlocks, ], { initializer: 'initialize' } - ) as ConnectivityTrackerHbbft; + ); - await blockRewardHbbft.setConnectivityTracker(connectivityTracker.address); + await connectivityTrackerProxy.waitForDeployment(); const TxPermissionFactory = await ethers.getContractFactory("TxPermissionHbbftMock"); - const txPermission = await upgrades.deployProxy( + const txPermissionProxy = await upgrades.deployProxy( TxPermissionFactory, [ allowedSenders, - certifier.address, - validatorSetHbbft.address, - keyGenHistory.address, - connectivityTracker.address, + await certifierProxy.getAddress(), + await validatorSetHbbftProxy.getAddress(), + await keyGenHistoryProxy.getAddress(), + await connectivityTrackerProxy.getAddress(), owner.address ], { initializer: 'initialize' } - ) as TxPermissionHbbftMock; + ); - await validatorSetHbbft.setKeyGenHistoryContract(keyGenHistory.address); - await validatorSetHbbft.setStakingContract(stakingHbbft.address); + await txPermissionProxy.waitForDeployment(); + + const txPermission = TxPermissionFactory.attach(await txPermissionProxy.getAddress()) as TxPermissionHbbftMock; + const keyGenHistory = KeyGenFactory.attach(await keyGenHistoryProxy.getAddress()) as KeyGenHistory; + const certifier = CertifierFactory.attach(await certifierProxy.getAddress()) as CertifierHbbft; + + const validatorSetHbbft = ValidatorSetFactory.attach( + await validatorSetHbbftProxy.getAddress() + ) as ValidatorSetHbbftMock; + + const stakingHbbft = StakingHbbftFactory.attach( + await stakingHbbftProxy.getAddress() + ) as StakingHbbftMock; + + const connectivityTracker = ConnectivityTrackerFactory.attach( + await connectivityTrackerProxy.getAddress() + ) as ConnectivityTrackerHbbft; + + await blockRewardHbbftProxy.setConnectivityTracker(await connectivityTrackerProxy.getAddress()); + await validatorSetHbbftProxy.setKeyGenHistoryContract(await keyGenHistoryProxy.getAddress()); + await validatorSetHbbftProxy.setStakingContract(await stakingHbbftProxy.getAddress()); return { txPermission, validatorSetHbbft, certifier, keyGenHistory, stakingHbbft, connectivityTracker }; } @@ -207,9 +235,9 @@ describe('TxPermissionHbbft', () => { owner.address ], { initializer: 'initialize' } - ) as TxPermissionHbbftMock; + ); - expect(await txPermission.deployed()); + await txPermission.waitForDeployment(); expect(await txPermission.certifierContract()).to.equal(certifierAddress); expect(await txPermission.keyGenHistoryContract()).to.equal(keyGenHistoryAddress); @@ -228,7 +256,7 @@ describe('TxPermissionHbbft', () => { TxPermissionFactory, [ allowedSenders, - ethers.constants.AddressZero, + ethers.ZeroAddress, stubAddress, stubAddress, stubAddress, @@ -247,7 +275,7 @@ describe('TxPermissionHbbft', () => { [ allowedSenders, stubAddress, - ethers.constants.AddressZero, + ethers.ZeroAddress, stubAddress, stubAddress, owner.address @@ -266,7 +294,7 @@ describe('TxPermissionHbbft', () => { allowedSenders, stubAddress, stubAddress, - ethers.constants.AddressZero, + ethers.ZeroAddress, stubAddress, owner.address ], @@ -285,7 +313,7 @@ describe('TxPermissionHbbft', () => { stubAddress, stubAddress, stubAddress, - ethers.constants.AddressZero, + ethers.ZeroAddress, owner.address ], { initializer: 'initialize' } @@ -304,7 +332,7 @@ describe('TxPermissionHbbft', () => { stubAddress, stubAddress, stubAddress, - ethers.constants.AddressZero, + ethers.ZeroAddress, ], { initializer: 'initialize' } )).to.be.revertedWith('Owner address must not be 0'); @@ -327,7 +355,7 @@ describe('TxPermissionHbbft', () => { { initializer: 'initialize' } ); - expect(await contract.deployed()); + await contract.waitForDeployment(); await expect(contract.initialize( allowedSenders, @@ -374,7 +402,7 @@ describe('TxPermissionHbbft', () => { const { txPermission } = await helpers.loadFixture(deployContractsFixture); await expect( - txPermission.connect(owner).addAllowedSender(ethers.constants.AddressZero) + txPermission.connect(owner).addAllowedSender(ethers.ZeroAddress) ).to.be.reverted; }); @@ -517,10 +545,10 @@ describe('TxPermissionHbbft', () => { const result = await txPermission.allowedTxTypes( sender.address, - ethers.constants.AddressZero, - 0, - 1, - '0x00', + ethers.ZeroAddress, + 0n, + 1n, + EmptyBytes, ); expect(result.typesMask).to.equal(AllowedTxTypeMask.All); @@ -536,10 +564,10 @@ describe('TxPermissionHbbft', () => { const result = await txPermission.allowedTxTypes( sender.address, - ethers.constants.AddressZero, - 0, - 0, - '0x00', + ethers.ZeroAddress, + 0n, + 0n, + EmptyBytes, ); expect(result.typesMask).to.equal(AllowedTxTypeMask.None); @@ -557,10 +585,10 @@ describe('TxPermissionHbbft', () => { const result = await txPermission.allowedTxTypes( sender.address, - ethers.constants.AddressZero, + ethers.ZeroAddress, 0, 0, - '0x00', + EmptyBytes, ); expect(result.typesMask).to.equal(AllowedTxTypeMask.All); @@ -578,7 +606,7 @@ describe('TxPermissionHbbft', () => { const result = await txPermission.allowedTxTypes( sender.address, - ethers.constants.AddressZero, + ethers.ZeroAddress, 0, Number(minGasPrice) / 2, '0x00', @@ -599,10 +627,10 @@ describe('TxPermissionHbbft', () => { const result = await txPermission.allowedTxTypes( sender.address, - ethers.constants.AddressZero, + ethers.ZeroAddress, 0, minGasPrice, - '0x00', + EmptyBytes, ); expect(result.typesMask).to.equal(AllowedTxTypeMask.All); @@ -621,7 +649,7 @@ describe('TxPermissionHbbft', () => { validator, 0, gasPrice, - '0x00', + EmptyBytes, ); expect(result.typesMask).to.equal(AllowedTxTypeMask.None); @@ -637,10 +665,10 @@ describe('TxPermissionHbbft', () => { for (let validator of initialValidators) { const result = await txPermission.allowedTxTypes( validator, - ethers.constants.AddressZero, + ethers.ZeroAddress, 0, gasPrice, - '0x00', + EmptyBytes, ); expect(result.typesMask).to.equal(AllowedTxTypeMask.Basic); @@ -658,10 +686,10 @@ describe('TxPermissionHbbft', () => { const result = await txPermission.allowedTxTypes( validator, - ethers.constants.AddressZero, - 0, + ethers.ZeroAddress, + 0n, gasPrice, - '0x00', + EmptyBytes, ); expect(result.typesMask).to.equal(AllowedTxTypeMask.None); @@ -679,10 +707,10 @@ describe('TxPermissionHbbft', () => { const result = await txPermission.allowedTxTypes( validator, - ethers.constants.AddressZero, + ethers.ZeroAddress, 0, gasPrice, - '0x00', + EmptyBytes, ); expect(result.typesMask).to.equal(AllowedTxTypeMask.None); @@ -704,20 +732,20 @@ describe('TxPermissionHbbft', () => { const latestBlock = await helpers.time.latestBlock(); const calldata = validatorSetHbbft.interface.encodeFunctionData( - 'reportMalicious', + "reportMalicious", [ malicious, latestBlock - 1, - [] + EmptyBytes, ] ); const result = await txPermission.allowedTxTypes( reporter.address, - validatorSetHbbft.address, - 0, + await validatorSetHbbft.getAddress(), + 0n, gasPrice, - ethers.utils.arrayify(calldata), + ethers.hexlify(calldata), ); expect(result.typesMask).to.equal(AllowedTxTypeMask.Call); @@ -738,7 +766,7 @@ describe('TxPermissionHbbft', () => { [ malicious, latestBlock - 1, - [] + EmptyBytes ] ); @@ -746,10 +774,10 @@ describe('TxPermissionHbbft', () => { const result = await txPermission.allowedTxTypes( reporter.address, - validatorSetHbbft.address, - 0, + await validatorSetHbbft.getAddress(), + 0n, gasPrice, - ethers.utils.arrayify(slicedCalldata), + ethers.hexlify(slicedCalldata), ); expect(result.typesMask).to.equal(AllowedTxTypeMask.Call); @@ -772,16 +800,16 @@ describe('TxPermissionHbbft', () => { [ malicious, latestBlock - 1, - [] + EmptyBytes ] ); const result = await txPermission.allowedTxTypes( reporter.address, - validatorSetHbbft.address, + await validatorSetHbbft.getAddress(), 0, gasPrice, - ethers.utils.arrayify(calldata), + ethers.hexlify(calldata), ); expect(result.typesMask).to.equal(AllowedTxTypeMask.None); @@ -799,17 +827,17 @@ describe('TxPermissionHbbft', () => { const calldata = validatorSetHbbft.interface.encodeFunctionData( 'announceAvailability', [ - latestBlock.number, - latestBlock.hash + latestBlock!.number, + latestBlock!.hash! ] ); const result = await txPermission.allowedTxTypes( initialValidators[0], - validatorSetHbbft.address, + await validatorSetHbbft.getAddress(), 0, gasPrice, - ethers.utils.arrayify(calldata), + ethers.hexlify(calldata), ); expect(result.typesMask).to.equal(AllowedTxTypeMask.Call); @@ -825,17 +853,17 @@ describe('TxPermissionHbbft', () => { const calldata = validatorSetHbbft.interface.encodeFunctionData( 'announceAvailability', [ - latestBlock.number, - latestBlock.hash + latestBlock!.number, + latestBlock!.hash! ] ); const result = await txPermission.allowedTxTypes( accounts[8].address, - validatorSetHbbft.address, + await validatorSetHbbft.getAddress(), 0, gasPrice, - ethers.utils.arrayify(calldata), + ethers.hexlify(calldata), ); expect(result.typesMask).to.equal(AllowedTxTypeMask.None); @@ -853,10 +881,10 @@ describe('TxPermissionHbbft', () => { const result = await txPermission.allowedTxTypes( initialValidators[1], - validatorSetHbbft.address, + await validatorSetHbbft.getAddress(), 0, gasPrice, - ethers.utils.arrayify(calldata), + ethers.hexlify(calldata), ); expect(result.typesMask).to.equal(AllowedTxTypeMask.Call); @@ -868,7 +896,7 @@ describe('TxPermissionHbbft', () => { await stakingHbbft.setValidatorSetAddress(owner.address); await stakingHbbft.removePool(initialStakingAddresses[0]); - await stakingHbbft.setValidatorSetAddress(validatorSetHbbft.address); + await stakingHbbft.setValidatorSetAddress(await validatorSetHbbft.getAddress()); const gasPrice = await txPermission.minimumGasPrice(); const calldata = validatorSetHbbft.interface.encodeFunctionData( @@ -878,10 +906,10 @@ describe('TxPermissionHbbft', () => { const result = await txPermission.allowedTxTypes( initialValidators[0], - validatorSetHbbft.address, + await validatorSetHbbft.getAddress(), 0, gasPrice, - ethers.utils.arrayify(calldata), + ethers.hexlify(calldata), ); expect(result.typesMask).to.equal(AllowedTxTypeMask.None); @@ -892,7 +920,6 @@ describe('TxPermissionHbbft', () => { const { txPermission, validatorSetHbbft } = await helpers.loadFixture(deployContractsFixture); const gasPrice = await txPermission.minimumGasPrice(); - const calldata = validatorSetHbbft.interface.encodeFunctionData( 'setValidatorInternetAddress', [ipAddress, port] @@ -900,10 +927,10 @@ describe('TxPermissionHbbft', () => { const result = await txPermission.allowedTxTypes( accounts[8].address, - validatorSetHbbft.address, + await validatorSetHbbft.getAddress(), 0, gasPrice, - ethers.utils.arrayify(calldata), + ethers.hexlify(calldata), ); expect(result.typesMask).to.equal(AllowedTxTypeMask.None); @@ -914,15 +941,14 @@ describe('TxPermissionHbbft', () => { const { txPermission, validatorSetHbbft } = await helpers.loadFixture(deployContractsFixture); const gasPrice = await txPermission.minimumGasPrice(); - const calldata = validatorSetHbbft.interface.encodeFunctionData('newValidatorSet'); const result = await txPermission.allowedTxTypes( initialValidators[0], - validatorSetHbbft.address, + await validatorSetHbbft.getAddress(), 0, gasPrice, - ethers.utils.arrayify(calldata), + ethers.hexlify(calldata), ); expect(result.typesMask).to.equal(AllowedTxTypeMask.None); @@ -938,10 +964,10 @@ describe('TxPermissionHbbft', () => { const result = await txPermission.allowedTxTypes( accounts[8].address, - validatorSetHbbft.address, + await validatorSetHbbft.getAddress(), 0, gasPrice, - ethers.utils.arrayify(calldata), + ethers.hexlify(calldata), ); expect(result.typesMask).to.equal(AllowedTxTypeMask.Call); @@ -955,10 +981,10 @@ describe('TxPermissionHbbft', () => { const result = await txPermission.allowedTxTypes( owner.address, - validatorSetHbbft.address, + await validatorSetHbbft.getAddress(), 0, 0, - ethers.utils.arrayify(calldata), + ethers.hexlify(calldata), ); expect(result.typesMask).to.equal(AllowedTxTypeMask.All); @@ -970,13 +996,13 @@ describe('TxPermissionHbbft', () => { async function deployMocks() { const mockStakingFactory = await ethers.getContractFactory("MockStaking"); const mockStaking = await mockStakingFactory.deploy(); - await mockStaking.deployed(); + await mockStaking.waitForDeployment(); const mockValidatorSetFactory = await ethers.getContractFactory("MockValidatorSet"); const mockValidatorSet = await mockValidatorSetFactory.deploy(); - await mockValidatorSet.deployed(); + await mockValidatorSet.waitForDeployment(); - await mockValidatorSet.setStakingContract(mockStaking.address); + await mockValidatorSet.setStakingContract(await mockStaking.getAddress()); return { mockValidatorSet, mockStaking }; } @@ -986,17 +1012,17 @@ describe('TxPermissionHbbft', () => { const calldata = keyGenHistory.interface.encodeFunctionData( 'writePart', - [0, 0, []] + [0, 0, EmptyBytes] ); const caller = accounts[8]; const result = await txPermission.allowedTxTypes( caller.address, - keyGenHistory.address, + await keyGenHistory.getAddress(), 0, 0, - ethers.utils.arrayify(calldata), + ethers.hexlify(calldata), ); expect(result.typesMask).to.equal(AllowedTxTypeMask.None); @@ -1007,12 +1033,12 @@ describe('TxPermissionHbbft', () => { const { txPermission, keyGenHistory } = await helpers.loadFixture(deployContractsFixture); const { mockValidatorSet } = await deployMocks(); - await txPermission.setValidatorSetContract(mockValidatorSet.address); + await txPermission.setValidatorSetContract(await mockValidatorSet.getAddress()); await mockValidatorSet.setKeyGenMode(KeyGenMode.WritePart); const calldata = keyGenHistory.interface.encodeFunctionData( 'writePart', - [0, 0, []] + [0, 0, EmptyBytes] ); const slicedCalladata = calldata.slice(0, 10); @@ -1020,10 +1046,10 @@ describe('TxPermissionHbbft', () => { const result = await txPermission.allowedTxTypes( caller.address, - keyGenHistory.address, + await keyGenHistory.getAddress(), 0, 0, - ethers.utils.arrayify(slicedCalladata), + ethers.hexlify(slicedCalladata), ); expect(result.typesMask).to.equal(AllowedTxTypeMask.None); @@ -1036,23 +1062,23 @@ describe('TxPermissionHbbft', () => { const epoch = 10; - await txPermission.setValidatorSetContract(mockValidatorSet.address); + await txPermission.setValidatorSetContract(await mockValidatorSet.getAddress()); await mockValidatorSet.setKeyGenMode(KeyGenMode.WritePart); await mockStaking.setStakingEpoch(epoch); const calldata = keyGenHistory.interface.encodeFunctionData( 'writePart', - [epoch - 1, 0, []] + [epoch - 1, 0, EmptyBytes] ); const caller = accounts[8]; const result = await txPermission.allowedTxTypes( caller.address, - keyGenHistory.address, + await keyGenHistory.getAddress(), 0, 0, - ethers.utils.arrayify(calldata), + ethers.hexlify(calldata), ); expect(result.typesMask).to.equal(AllowedTxTypeMask.None); @@ -1065,23 +1091,23 @@ describe('TxPermissionHbbft', () => { const epoch = 10; - await txPermission.setValidatorSetContract(mockValidatorSet.address); + await txPermission.setValidatorSetContract(await mockValidatorSet.getAddress()); await mockValidatorSet.setKeyGenMode(KeyGenMode.WritePart); await mockStaking.setStakingEpoch(epoch); const calldata = keyGenHistory.interface.encodeFunctionData( 'writePart', - [epoch + 1, 0, []] + [epoch + 1, 0, EmptyBytes] ); const caller = accounts[8]; const result = await txPermission.allowedTxTypes( caller.address, - keyGenHistory.address, + await keyGenHistory.getAddress(), 0, 0, - ethers.utils.arrayify(calldata), + ethers.hexlify(calldata), ); expect(result.typesMask).to.equal(AllowedTxTypeMask.Call); @@ -1093,17 +1119,17 @@ describe('TxPermissionHbbft', () => { const calldata = keyGenHistory.interface.encodeFunctionData( 'writeAcks', - [0, 0, [[]]] + [0, 0, [EmptyBytes]] ); const caller = accounts[8]; const result = await txPermission.allowedTxTypes( caller.address, - keyGenHistory.address, + await keyGenHistory.getAddress(), 0, 0, - ethers.utils.arrayify(calldata), + ethers.hexlify(calldata), ); expect(result.typesMask).to.equal(AllowedTxTypeMask.None); @@ -1112,14 +1138,14 @@ describe('TxPermissionHbbft', () => { it("should not allow writeAck transaction with data size < 36", async function () { const { txPermission, keyGenHistory } = await helpers.loadFixture(deployContractsFixture); - const { mockValidatorSet, mockStaking } = await deployMocks(); + const { mockValidatorSet } = await deployMocks(); - await txPermission.setValidatorSetContract(mockValidatorSet.address); + await txPermission.setValidatorSetContract(await mockValidatorSet.getAddress()); await mockValidatorSet.setKeyGenMode(KeyGenMode.WriteAck); const calldata = keyGenHistory.interface.encodeFunctionData( 'writeAcks', - [0, 0, [[]]] + [0, 0, [EmptyBytes]] ); const caller = accounts[8]; @@ -1128,10 +1154,10 @@ describe('TxPermissionHbbft', () => { const result = await txPermission.allowedTxTypes( caller.address, - keyGenHistory.address, + await keyGenHistory.getAddress(), 0, 0, - ethers.utils.arrayify(slicedCalldata), + ethers.hexlify(slicedCalldata), ); expect(result.typesMask).to.equal(AllowedTxTypeMask.None); @@ -1144,23 +1170,23 @@ describe('TxPermissionHbbft', () => { const epoch = 10; - await txPermission.setValidatorSetContract(mockValidatorSet.address); + await txPermission.setValidatorSetContract(await mockValidatorSet.getAddress()); await mockValidatorSet.setKeyGenMode(KeyGenMode.WriteAck); await mockStaking.setStakingEpoch(epoch); const calldata = keyGenHistory.interface.encodeFunctionData( 'writeAcks', - [epoch - 1, epoch - 2, [[]]] + [epoch - 1, epoch - 2, [EmptyBytes]] ); const caller = accounts[8]; const result = await txPermission.allowedTxTypes( caller.address, - keyGenHistory.address, + await keyGenHistory.getAddress(), 0, 0, - ethers.utils.arrayify(calldata), + ethers.hexlify(calldata), ); expect(result.typesMask).to.equal(AllowedTxTypeMask.None); @@ -1173,23 +1199,23 @@ describe('TxPermissionHbbft', () => { const epoch = 10; - await txPermission.setValidatorSetContract(mockValidatorSet.address); + await txPermission.setValidatorSetContract(await mockValidatorSet.getAddress()); await mockValidatorSet.setKeyGenMode(KeyGenMode.WriteAck); await mockStaking.setStakingEpoch(epoch); const calldata = keyGenHistory.interface.encodeFunctionData( 'writeAcks', - [epoch + 1, 0, [[]]] + [epoch + 1, 0, [EmptyBytes]] ); const caller = accounts[8]; const result = await txPermission.allowedTxTypes( caller.address, - keyGenHistory.address, + await keyGenHistory.getAddress(), 0, 0, - ethers.utils.arrayify(calldata), + ethers.hexlify(calldata), ); expect(result.typesMask).to.equal(AllowedTxTypeMask.Call); @@ -1202,23 +1228,23 @@ describe('TxPermissionHbbft', () => { const epoch = 10; - await txPermission.setValidatorSetContract(mockValidatorSet.address); + await txPermission.setValidatorSetContract(await mockValidatorSet.getAddress()); await mockValidatorSet.setKeyGenMode(KeyGenMode.WriteAck); await mockStaking.setStakingEpoch(epoch); const calldata = keyGenHistory.interface.encodeFunctionData( 'writeAcks', - [epoch - 1, epoch + 1, [[]]] + [epoch - 1, epoch + 1, [EmptyBytes]] ); const caller = accounts[8]; const result = await txPermission.allowedTxTypes( caller.address, - keyGenHistory.address, + await keyGenHistory.getAddress(), 0, 0, - ethers.utils.arrayify(calldata), + ethers.hexlify(calldata), ); expect(result.typesMask).to.equal(AllowedTxTypeMask.Call); @@ -1233,7 +1259,7 @@ describe('TxPermissionHbbft', () => { const gasPrice = await txPermission.minimumGasPrice(); const reporter = await ethers.getSigner(initialValidators[0]); - await helpers.mine(minReportAgeBlocks + 1); + await helpers.mine(minReportAgeBlocks + 1n); const latestBlockNum = await helpers.time.latestBlock(); const block = await ethers.provider.getBlock(latestBlockNum - 1); @@ -1242,17 +1268,17 @@ describe('TxPermissionHbbft', () => { 'reportMissingConnectivity', [ initialValidators[1], - block.number, - block.hash + block!.number, + block!.hash! ] ); const result = await txPermission.allowedTxTypes( reporter.address, - connectivityTracker.address, + await connectivityTracker.getAddress(), 0, gasPrice, - ethers.utils.arrayify(calldata), + ethers.hexlify(calldata), ); expect(result.typesMask).to.equal(AllowedTxTypeMask.Call); @@ -1265,7 +1291,7 @@ describe('TxPermissionHbbft', () => { const gasPrice = await txPermission.minimumGasPrice(); const reporter = await ethers.getSigner(initialValidators[0]); - await helpers.mine(minReportAgeBlocks + 1); + await helpers.mine(minReportAgeBlocks + 1n); const latestBlockNum = await helpers.time.latestBlock(); const block = await ethers.provider.getBlock(latestBlockNum - 1); @@ -1274,17 +1300,17 @@ describe('TxPermissionHbbft', () => { 'reportMissingConnectivity', [ initialValidators[1], - block.number, - ethers.constants.HashZero + block!.number, + ethers.ZeroHash ] ); const result = await txPermission.allowedTxTypes( reporter.address, - connectivityTracker.address, + await connectivityTracker.getAddress(), 0, gasPrice, - ethers.utils.arrayify(calldata), + ethers.hexlify(calldata), ); expect(result.typesMask).to.equal(AllowedTxTypeMask.None); @@ -1298,15 +1324,15 @@ describe('TxPermissionHbbft', () => { const reporter = await ethers.getSigner(initialValidators[0]); const validator = initialValidators[1]; - await helpers.mine(minReportAgeBlocks + 1); + await helpers.mine(minReportAgeBlocks + 1n); let latestBlockNum = await helpers.time.latestBlock(); let block = await ethers.provider.getBlock(latestBlockNum - 1); expect(await connectivityTracker.connect(reporter).reportMissingConnectivity( validator, - block.number, - block.hash + block!.number, + block!.hash! )); latestBlockNum = await helpers.time.latestBlock(); @@ -1316,17 +1342,17 @@ describe('TxPermissionHbbft', () => { 'reportReconnect', [ initialValidators[1], - block.number, - block.hash + block!.number, + block!.hash! ] ); const result = await txPermission.allowedTxTypes( reporter.address, - connectivityTracker.address, + await connectivityTracker.getAddress(), 0, gasPrice, - ethers.utils.arrayify(calldata), + ethers.hexlify(calldata), ); expect(result.typesMask).to.equal(AllowedTxTypeMask.Call); @@ -1339,7 +1365,7 @@ describe('TxPermissionHbbft', () => { const gasPrice = await txPermission.minimumGasPrice(); const reporter = await ethers.getSigner(initialValidators[0]); - await helpers.mine(minReportAgeBlocks + 1); + await helpers.mine(minReportAgeBlocks + 1n); const latestBlockNum = await helpers.time.latestBlock(); const block = await ethers.provider.getBlock(latestBlockNum - 1); @@ -1348,17 +1374,17 @@ describe('TxPermissionHbbft', () => { 'reportReconnect', [ initialValidators[1], - block.number, - ethers.constants.HashZero + block!.number, + ethers.ZeroHash ] ); const result = await txPermission.allowedTxTypes( reporter.address, - connectivityTracker.address, + await connectivityTracker.getAddress(), 0, gasPrice, - ethers.utils.arrayify(calldata), + ethers.hexlify(calldata), ); expect(result.typesMask).to.equal(AllowedTxTypeMask.None); diff --git a/test/ValidatorSetHbbft.ts b/test/ValidatorSetHbbft.ts index 7f3e308d..ed8f87d0 100644 --- a/test/ValidatorSetHbbft.ts +++ b/test/ValidatorSetHbbft.ts @@ -1,6 +1,9 @@ import { ethers, network, upgrades } from "hardhat"; - +import { TransactionResponse } from "ethers"; +import { expect } from "chai"; +import { HardhatEthersSigner } from "@nomicfoundation/hardhat-ethers/signers"; import * as helpers from "@nomicfoundation/hardhat-network-helpers"; +import fp from "lodash/fp"; import { BlockRewardHbbftMock, @@ -8,87 +11,52 @@ import { ValidatorSetHbbftMock, StakingHbbftMock, KeyGenHistory, - TxPermissionHbbft, + TxPermissionHbbftMock, CertifierHbbft, - ConnectivityTrackerHbbftMock, + TxPermissionHbbft, } from "../src/types"; -import fp from 'lodash/fp'; -import { BigNumber} from "ethers"; -import { TransactionResponse } from '@ethersproject/providers' -import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers"; import { Permission } from "./testhelpers/Permission"; -import { expect } from "chai"; - -require('chai') - .use(require('chai-as-promised')) - .use(require('chai-bn')(BigNumber)) - .should(); - -//smart contracts -let vaidatorSetPermission: Permission - -//addresses -let owner: SignerWithAddress; -let accounts: SignerWithAddress[]; +import { random } from "./utils/utils"; +import { getNValidatorsPartNAcks } from "./testhelpers/data"; - -//consts // one epoch in 1 day. -const stakingFixedEpochDuration = BigNumber.from(86400); +const stakingFixedEpochDuration = 86400n; + // the transition time window is 1 hour. -const stakingTransitionTimeframeLength = BigNumber.from(3600); -const stakingWithdrawDisallowPeriod = BigNumber.from(1); -const MIN_STAKE = BigNumber.from(ethers.utils.parseEther('1')); -const MAX_STAKE = BigNumber.from(ethers.utils.parseEther('100000')); +const stakingTransitionTimeframeLength = 3600n; +const stakingWithdrawDisallowPeriod = 1n; +const MIN_STAKE = ethers.parseEther('1'); +const MAX_STAKE = ethers.parseEther('100000'); -const validatorInactivityThreshold = 365 * 86400 // 1 year +const validatorInactivityThreshold = BigInt(365 * 86400) // 1 year const SystemAccountAddress = "0xffffFFFfFFffffffffffffffFfFFFfffFFFfFFfE"; - -let initialValidatorsPubKeys: string[]; -let initialValidatorsIpAddresses: string[]; - -let initialValidators: string[]; -let initialStakingAddresses: string[]; - -let accountAddresses: string[]; +const EmptyBytes = ethers.hexlify(new Uint8Array()); describe('ValidatorSetHbbft', () => { - async function deployContractsFixture() { - [owner, ...accounts] = await ethers.getSigners(); + let owner: HardhatEthersSigner; + let accounts: HardhatEthersSigner[]; - accountAddresses = accounts.map(item => item.address); - initialValidators = accountAddresses.slice(1, 3 + 1); // accounts[1...3] - initialStakingAddresses = accountAddresses.slice(4, 6 + 1); // accounts[4...6] + let initialValidatorsPubKeys: string[]; + let initialValidatorsIpAddresses: string[]; - const stubAddress = owner.address; + let initialValidators: string[]; + let initialStakingAddresses: string[]; - // The following private keys belong to the accounts 1-3, fixed by using the "--mnemonic" option when starting ganache. - // const initialValidatorsPrivKeys = ["0x272b8400a202c08e23641b53368d603e5fec5c13ea2f438bce291f7be63a02a7", "0xa8ea110ffc8fe68a069c8a460ad6b9698b09e21ad5503285f633b3ad79076cf7", "0x5da461ff1378256f69cb9a9d0a8b370c97c460acbe88f5d897cb17209f891ffc"]; - // Public keys corresponding to the three private keys above. - initialValidatorsPubKeys = fp.flatMap((x: string) => [x.substring(0, 66), '0x' + x.substring(66, 130)]) - ([ - '0x52be8f332b0404dff35dd0b2ba44993a9d3dc8e770b9ce19a849dff948f1e14c57e7c8219d522c1a4cce775adbee5330f222520f0afdabfdb4a4501ceeb8dcee', - '0x99edf3f524a6f73e7f5d561d0030fc6bcc3e4bd33971715617de7791e12d9bdf6258fa65b74e7161bbbf7ab36161260f56f68336a6f65599dc37e7f2e397f845', - '0xa255fd7ad199f0ee814ee00cce44ef2b1fa1b52eead5d8013ed85eade03034ae4c246658946c2e1d7ded96394a1247fb4d093c32474317ae388e8d25692a0f56' - ]); - // The IP addresses are irrelevant for these unit test, just initialize them to 0. - initialValidatorsIpAddresses = [ - '0x00000000000000000000000000000000', - '0x00000000000000000000000000000000', - '0x00000000000000000000000000000000' - ]; + let accountAddresses: string[]; - const parts = [[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 181, 129, 31, 84, 186, 242, 5, 151, 59, 35, 196, 140, 106, 29, 40, 112, 142, 156, 132, 158, 47, 223, 253, 185, 227, 249, 190, 96, 5, 99, 239, 213, 127, 29, 136, 115, 71, 164, 202, 44, 6, 171, 131, 251, 147, 159, 54, 49, 1, 0, 0, 0, 0, 0, 0, 0, 153, 0, 0, 0, 0, 0, 0, 0, 4, 177, 133, 61, 18, 58, 222, 74, 65, 5, 126, 253, 181, 113, 165, 43, 141, 56, 226, 132, 208, 218, 197, 119, 179, 128, 30, 162, 251, 23, 33, 73, 38, 120, 246, 223, 233, 11, 104, 60, 154, 241, 182, 147, 219, 81, 45, 134, 239, 69, 169, 198, 188, 152, 95, 254, 170, 108, 60, 166, 107, 254, 204, 195, 170, 234, 154, 134, 26, 91, 9, 139, 174, 178, 248, 60, 65, 196, 218, 46, 163, 218, 72, 1, 98, 12, 109, 186, 152, 148, 159, 121, 254, 34, 112, 51, 70, 121, 51, 167, 35, 240, 5, 134, 197, 125, 252, 3, 213, 84, 70, 176, 160, 36, 73, 140, 104, 92, 117, 184, 80, 26, 240, 106, 230, 241, 26, 79, 46, 241, 195, 20, 106, 12, 186, 49, 254, 168, 233, 25, 179, 96, 62, 104, 118, 153, 95, 53, 127, 160, 237, 246, 41], [0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 181, 129, 31, 84, 186, 242, 5, 151, 59, 35, 196, 140, 106, 29, 40, 112, 142, 156, 132, 158, 47, 223, 253, 185, 227, 249, 190, 96, 5, 99, 239, 213, 127, 29, 136, 115, 71, 164, 202, 44, 6, 171, 131, 251, 147, 159, 54, 49, 1, 0, 0, 0, 0, 0, 0, 0, 153, 0, 0, 0, 0, 0, 0, 0, 4, 177, 133, 61, 18, 58, 222, 74, 65, 5, 126, 253, 181, 113, 165, 43, 141, 56, 226, 132, 208, 218, 197, 119, 179, 128, 30, 162, 251, 23, 33, 73, 38, 120, 246, 223, 233, 11, 104, 60, 154, 241, 182, 147, 219, 81, 45, 134, 239, 69, 169, 198, 188, 152, 95, 254, 170, 108, 60, 166, 107, 254, 204, 195, 170, 234, 154, 134, 26, 91, 9, 139, 174, 178, 248, 60, 65, 196, 218, 46, 163, 218, 72, 1, 98, 12, 109, 186, 152, 148, 159, 121, 254, 34, 112, 51, 70, 121, 51, 167, 35, 240, 5, 134, 197, 125, 252, 3, 213, 84, 70, 176, 160, 36, 73, 140, 104, 92, 117, 184, 80, 26, 240, 106, 230, 241, 26, 79, 46, 241, 195, 20, 106, 12, 186, 49, 254, 168, 233, 25, 179, 96, 62, 104, 118, 153, 95, 53, 127, 160, 237, 246, 41], [0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 181, 129, 31, 84, 186, 242, 5, 151, 59, 35, 196, 140, 106, 29, 40, 112, 142, 156, 132, 158, 47, 223, 253, 185, 227, 249, 190, 96, 5, 99, 239, 213, 127, 29, 136, 115, 71, 164, 202, 44, 6, 171, 131, 251, 147, 159, 54, 49, 1, 0, 0, 0, 0, 0, 0, 0, 153, 0, 0, 0, 0, 0, 0, 0, 4, 177, 133, 61, 18, 58, 222, 74, 65, 5, 126, 253, 181, 113, 165, 43, 141, 56, 226, 132, 208, 218, 197, 119, 179, 128, 30, 162, 251, 23, 33, 73, 38, 120, 246, 223, 233, 11, 104, 60, 154, 241, 182, 147, 219, 81, 45, 134, 239, 69, 169, 198, 188, 152, 95, 254, 170, 108, 60, 166, 107, 254, 204, 195, 170, 234, 154, 134, 26, 91, 9, 139, 174, 178, 248, 60, 65, 196, 218, 46, 163, 218, 72, 1, 98, 12, 109, 186, 152, 148, 159, 121, 254, 34, 112, 51, 70, 121, 51, 167, 35, 240, 5, 134, 197, 125, 252, 3, 213, 84, 70, 176, 160, 36, 73, 140, 104, 92, 117, 184, 80, 26, 240, 106, 230, 241, 26, 79, 46, 241, 195, 20, 106, 12, 186, 49, 254, 168, 233, 25, 179, 96, 62, 104, 118, 153, 95, 53, 127, 160, 237, 246, 41]]; - const acks = [[[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 145, 0, 0, 0, 0, 0, 0, 0, 4, 239, 1, 112, 13, 13, 251, 103, 186, 212, 78, 44, 47, 250, 221, 84, 118, 88, 7, 64, 206, 186, 11, 2, 8, 204, 140, 106, 179, 52, 251, 237, 19, 53, 74, 187, 217, 134, 94, 66, 68, 89, 42, 85, 207, 155, 220, 101, 223, 51, 199, 37, 38, 203, 132, 13, 77, 78, 114, 53, 219, 114, 93, 21, 25, 164, 12, 43, 252, 160, 16, 23, 111, 79, 230, 121, 95, 223, 174, 211, 172, 231, 0, 52, 25, 49, 152, 79, 128, 39, 117, 216, 85, 201, 237, 242, 151, 219, 149, 214, 77, 233, 145, 47, 10, 184, 175, 162, 174, 237, 177, 131, 45, 126, 231, 32, 147, 227, 170, 125, 133, 36, 123, 164, 232, 129, 135, 196, 136, 186, 45, 73, 226, 179, 169, 147, 42, 41, 140, 202, 191, 12, 73, 146, 2]], [[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 145, 0, 0, 0, 0, 0, 0, 0, 4, 239, 1, 112, 13, 13, 251, 103, 186, 212, 78, 44, 47, 250, 221, 84, 118, 88, 7, 64, 206, 186, 11, 2, 8, 204, 140, 106, 179, 52, 251, 237, 19, 53, 74, 187, 217, 134, 94, 66, 68, 89, 42, 85, 207, 155, 220, 101, 223, 51, 199, 37, 38, 203, 132, 13, 77, 78, 114, 53, 219, 114, 93, 21, 25, 164, 12, 43, 252, 160, 16, 23, 111, 79, 230, 121, 95, 223, 174, 211, 172, 231, 0, 52, 25, 49, 152, 79, 128, 39, 117, 216, 85, 201, 237, 242, 151, 219, 149, 214, 77, 233, 145, 47, 10, 184, 175, 162, 174, 237, 177, 131, 45, 126, 231, 32, 147, 227, 170, 125, 133, 36, 123, 164, 232, 129, 135, 196, 136, 186, 45, 73, 226, 179, 169, 147, 42, 41, 140, 202, 191, 12, 73, 146, 2]], [[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 145, 0, 0, 0, 0, 0, 0, 0, 4, 239, 1, 112, 13, 13, 251, 103, 186, 212, 78, 44, 47, 250, 221, 84, 118, 88, 7, 64, 206, 186, 11, 2, 8, 204, 140, 106, 179, 52, 251, 237, 19, 53, 74, 187, 217, 134, 94, 66, 68, 89, 42, 85, 207, 155, 220, 101, 223, 51, 199, 37, 38, 203, 132, 13, 77, 78, 114, 53, 219, 114, 93, 21, 25, 164, 12, 43, 252, 160, 16, 23, 111, 79, 230, 121, 95, 223, 174, 211, 172, 231, 0, 52, 25, 49, 152, 79, 128, 39, 117, 216, 85, 201, 237, 242, 151, 219, 149, 214, 77, 233, 145, 47, 10, 184, 175, 162, 174, 237, 177, 131, 45, 126, 231, 32, 147, 227, 170, 125, 133, 36, 123, 164, 232, 129, 135, 196, 136, 186, 45, 73, 226, 179, 169, 147, 42, 41, 140, 202, 191, 12, 73, 146, 2]]]; + let stubAddress: string; + + async function deployContractsFixture() { + const { parts, acks } = getNValidatorsPartNAcks(initialValidators.length); const ConnectivityTrackerFactory = await ethers.getContractFactory("ConnectivityTrackerHbbftMock"); - const connectivityTracker = await upgrades.deployProxy(ConnectivityTrackerFactory) as ConnectivityTrackerHbbftMock; - await connectivityTracker.deployed(); + const connectivityTracker = await ConnectivityTrackerFactory.deploy(); + await connectivityTracker.waitForDeployment(); const ValidatorSetFactory = await ethers.getContractFactory("ValidatorSetHbbftMock"); - const validatorSetHbbft = await upgrades.deployProxy( + const validatorSetHbbftProxy = await upgrades.deployProxy( ValidatorSetFactory, [ owner.address, @@ -101,80 +69,92 @@ describe('ValidatorSetHbbft', () => { initialStakingAddresses, // _initialStakingAddresses ], { initializer: 'initialize' } - ) as ValidatorSetHbbftMock; + ); + + await validatorSetHbbftProxy.waitForDeployment(); const RandomHbbftFactory = await ethers.getContractFactory("RandomHbbft"); - const randomHbbft = await upgrades.deployProxy( + const randomHbbftProxy = await upgrades.deployProxy( RandomHbbftFactory, [ owner.address, - validatorSetHbbft.address + await validatorSetHbbftProxy.getAddress() ], { initializer: 'initialize' }, - ) as RandomHbbft; + ); + + await randomHbbftProxy.waitForDeployment(); const KeyGenFactory = await ethers.getContractFactory("KeyGenHistory"); - const keyGenHistory = await upgrades.deployProxy( + const keyGenHistoryProxy = await upgrades.deployProxy( KeyGenFactory, [ owner.address, - validatorSetHbbft.address, + await validatorSetHbbftProxy.getAddress(), initialValidators, parts, acks ], { initializer: 'initialize' } - ) as KeyGenHistory; + ); + + await keyGenHistoryProxy.waitForDeployment(); const CertifierFactory = await ethers.getContractFactory("CertifierHbbft"); - const certifier = await upgrades.deployProxy( + const certifierProxy = await upgrades.deployProxy( CertifierFactory, [ [owner.address], - validatorSetHbbft.address, + await validatorSetHbbftProxy.getAddress(), owner.address ], { initializer: 'initialize' } - ) as CertifierHbbft; + ); + + await certifierProxy.waitForDeployment(); const TxPermissionFactory = await ethers.getContractFactory("TxPermissionHbbft"); - const txPermission = await upgrades.deployProxy( + const txPermissionProxy = await upgrades.deployProxy( TxPermissionFactory, [ [owner.address], - certifier.address, - validatorSetHbbft.address, - keyGenHistory.address, + await certifierProxy.getAddress(), + await validatorSetHbbftProxy.getAddress(), + await keyGenHistoryProxy.getAddress(), stubAddress, owner.address ], { initializer: 'initialize' } - ) as TxPermissionHbbft; + ); + + await txPermissionProxy.waitForDeployment(); const BlockRewardHbbftFactory = await ethers.getContractFactory("BlockRewardHbbftMock"); - const blockRewardHbbft = await upgrades.deployProxy( + const blockRewardHbbftProxy = await upgrades.deployProxy( BlockRewardHbbftFactory, [ owner.address, - validatorSetHbbft.address, - connectivityTracker.address + await validatorSetHbbftProxy.getAddress(), + await connectivityTracker.getAddress(), ], { initializer: 'initialize' } - ) as BlockRewardHbbftMock; + ); + + await blockRewardHbbftProxy.waitForDeployment(); let stakingParams = { - _validatorSetContract: validatorSetHbbft.address, + _validatorSetContract: await validatorSetHbbftProxy.getAddress(), _initialStakingAddresses: initialStakingAddresses, - _delegatorMinStake: ethers.utils.parseEther('1'), - _candidateMinStake: ethers.utils.parseEther('1'), - _maxStake: ethers.utils.parseEther('100000'), + _delegatorMinStake: ethers.parseEther('1'), + _candidateMinStake: ethers.parseEther('1'), + _maxStake: MAX_STAKE, _stakingFixedEpochDuration: stakingFixedEpochDuration, _stakingTransitionTimeframeLength: stakingTransitionTimeframeLength, _stakingWithdrawDisallowPeriod: stakingWithdrawDisallowPeriod }; const StakingHbbftFactory = await ethers.getContractFactory("StakingHbbftMock"); - const stakingHbbft = await upgrades.deployProxy( + const stakingHbbftProxy = await upgrades.deployProxy( StakingHbbftFactory, [ owner.address, @@ -183,12 +163,31 @@ describe('ValidatorSetHbbft', () => { initialValidatorsIpAddresses // _internetAddresses ], { initializer: 'initialize' } + ); + + await stakingHbbftProxy.waitForDeployment(); + + const txPermission = TxPermissionFactory.attach(await txPermissionProxy.getAddress()) as TxPermissionHbbftMock; + const keyGenHistory = KeyGenFactory.attach(await keyGenHistoryProxy.getAddress()) as KeyGenHistory; + const certifier = CertifierFactory.attach(await certifierProxy.getAddress()) as CertifierHbbft; + const randomHbbft = RandomHbbftFactory.attach(await randomHbbftProxy.getAddress()) as RandomHbbft + + const validatorSetHbbft = ValidatorSetFactory.attach( + await validatorSetHbbftProxy.getAddress() + ) as ValidatorSetHbbftMock; + + const stakingHbbft = StakingHbbftFactory.attach( + await stakingHbbftProxy.getAddress() ) as StakingHbbftMock; - await validatorSetHbbft.setBlockRewardContract(blockRewardHbbft.address); - await validatorSetHbbft.setRandomContract(randomHbbft.address); - await validatorSetHbbft.setStakingContract(stakingHbbft.address); - await validatorSetHbbft.setKeyGenHistoryContract(keyGenHistory.address); + const blockRewardHbbft = BlockRewardHbbftFactory.attach( + await blockRewardHbbftProxy.getAddress() + ) as BlockRewardHbbftMock + + await validatorSetHbbft.setBlockRewardContract(await blockRewardHbbft.getAddress()); + await validatorSetHbbft.setRandomContract(await randomHbbft.getAddress()); + await validatorSetHbbft.setStakingContract(await stakingHbbft.getAddress()); + await validatorSetHbbft.setKeyGenHistoryContract(await keyGenHistory.getAddress()); return { validatorSetHbbft, blockRewardHbbft, stakingHbbft, randomHbbft, keyGenHistory, certifier, txPermission }; } @@ -198,7 +197,7 @@ describe('ValidatorSetHbbft', () => { await owner.sendTransaction({ to: SystemAccountAddress, - value: ethers.utils.parseEther('10'), + value: ethers.parseEther('10'), }); return await ethers.getSigner(SystemAccountAddress); @@ -208,8 +207,22 @@ describe('ValidatorSetHbbft', () => { [owner, ...accounts] = await ethers.getSigners(); accountAddresses = accounts.map(item => item.address); + stubAddress = accountAddresses[1]; + initialValidators = accountAddresses.slice(1, 3 + 1); // accounts[1...3] initialStakingAddresses = accountAddresses.slice(4, 6 + 1); // accounts[4...6] + + // The following private keys belong to the accounts 1-3, fixed by using the "--mnemonic" option when starting ganache. + // const initialValidatorsPrivKeys = ["0x272b8400a202c08e23641b53368d603e5fec5c13ea2f438bce291f7be63a02a7", "0xa8ea110ffc8fe68a069c8a460ad6b9698b09e21ad5503285f633b3ad79076cf7", "0x5da461ff1378256f69cb9a9d0a8b370c97c460acbe88f5d897cb17209f891ffc"]; + // Public keys corresponding to the three private keys above. + initialValidatorsPubKeys = fp.flatMap((x: string) => [x.substring(0, 66), '0x' + x.substring(66, 130)])([ + '0x52be8f332b0404dff35dd0b2ba44993a9d3dc8e770b9ce19a849dff948f1e14c57e7c8219d522c1a4cce775adbee5330f222520f0afdabfdb4a4501ceeb8dcee', + '0x99edf3f524a6f73e7f5d561d0030fc6bcc3e4bd33971715617de7791e12d9bdf6258fa65b74e7161bbbf7ab36161260f56f68336a6f65599dc37e7f2e397f845', + '0xa255fd7ad199f0ee814ee00cce44ef2b1fa1b52eead5d8013ed85eade03034ae4c246658946c2e1d7ded96394a1247fb4d093c32474317ae388e8d25692a0f56' + ]); + + // The IP addresses are irrelevant for these unit test, just initialize them to 0. + initialValidatorsIpAddresses = Array(3).fill(ethers.zeroPadBytes("0x00", 16)); }); describe('initialize()', async () => { @@ -219,10 +232,10 @@ describe('ValidatorSetHbbft', () => { const keyGenHistoryContractAddress = '0x8000000000000000000000000000000000000001'; beforeEach(async () => { - initialValidators.length.should.be.equal(3); - initialValidators[0].should.not.be.equal('0x0000000000000000000000000000000000000000'); - initialValidators[1].should.not.be.equal('0x0000000000000000000000000000000000000000'); - initialValidators[2].should.not.be.equal('0x0000000000000000000000000000000000000000'); + expect(initialValidators.length).to.be.equal(3); + expect(initialValidators[0]).to.not.be.equal(ethers.ZeroAddress); + expect(initialValidators[1]).to.not.be.equal(ethers.ZeroAddress); + expect(initialValidators[2]).to.not.be.equal(ethers.ZeroAddress); }); it('should initialize successfully', async () => { @@ -240,9 +253,9 @@ describe('ValidatorSetHbbft', () => { initialStakingAddresses, ], { initializer: 'initialize' } - ) as ValidatorSetHbbftMock; + ); - expect(await validatorSetHbbft.deployed()); + expect(await validatorSetHbbft.waitForDeployment()); expect(await validatorSetHbbft.blockRewardContract()).to.equal(blockRewardContractAddress); expect(await validatorSetHbbft.randomContract()).to.equal(randomContractAddress); @@ -258,7 +271,7 @@ describe('ValidatorSetHbbft', () => { expect(await validatorSetHbbft.stakingByMiningAddress(initialValidators[i])).to.be.equal(initialStakingAddresses[i]); } - expect(await validatorSetHbbft.isValidator(ethers.constants.AddressZero)).to.be.false; + expect(await validatorSetHbbft.isValidator(ethers.ZeroAddress)).to.be.false; expect(await validatorSetHbbft.validatorInactivityThreshold()).to.be.equal(validatorInactivityThreshold); }); @@ -268,7 +281,7 @@ describe('ValidatorSetHbbft', () => { ValidatorSetFactory, [ owner.address, - ethers.constants.AddressZero, + ethers.ZeroAddress, randomContractAddress, stakingContractAddress, keyGenHistoryContractAddress, @@ -287,7 +300,7 @@ describe('ValidatorSetHbbft', () => { [ owner.address, blockRewardContractAddress, - ethers.constants.AddressZero, + ethers.ZeroAddress, stakingContractAddress, keyGenHistoryContractAddress, validatorInactivityThreshold, @@ -306,7 +319,7 @@ describe('ValidatorSetHbbft', () => { owner.address, blockRewardContractAddress, randomContractAddress, - ethers.constants.AddressZero, + ethers.ZeroAddress, keyGenHistoryContractAddress, validatorInactivityThreshold, initialValidators, @@ -325,7 +338,7 @@ describe('ValidatorSetHbbft', () => { blockRewardContractAddress, randomContractAddress, stakingContractAddress, - ethers.constants.AddressZero, + ethers.ZeroAddress, validatorInactivityThreshold, initialValidators, initialStakingAddresses, @@ -369,7 +382,7 @@ describe('ValidatorSetHbbft', () => { { initializer: 'initialize' } ); - await validatorSetHbbft.initialize( + await expect(validatorSetHbbft.initialize( owner.address, blockRewardContractAddress, randomContractAddress, @@ -378,7 +391,7 @@ describe('ValidatorSetHbbft', () => { validatorInactivityThreshold, initialValidators, initialStakingAddresses, - ).should.be.revertedWith("Initializable: contract is already initialized"); + )).to.be.revertedWith("Initializable: contract is already initialized"); }); it('should fail if the number of mining addresses is not the same as the number of staking ones', async () => { @@ -420,7 +433,7 @@ describe('ValidatorSetHbbft', () => { }); it('should fail if some mining address is 0', async () => { - initialValidators[0] = '0x0000000000000000000000000000000000000000'; + initialValidators[0] = ethers.ZeroAddress; const ValidatorSetFactory = await ethers.getContractFactory("ValidatorSetHbbftMock"); await expect(upgrades.deployProxy( @@ -440,7 +453,7 @@ describe('ValidatorSetHbbft', () => { }); it('should fail if some staking address is 0', async () => { - initialStakingAddresses[0] = '0x0000000000000000000000000000000000000000'; + initialStakingAddresses[0] = ethers.ZeroAddress; const ValidatorSetFactory = await ethers.getContractFactory("ValidatorSetHbbftMock"); await expect(upgrades.deployProxy( @@ -544,7 +557,7 @@ describe('ValidatorSetHbbft', () => { it('can only be called by BlockReward contract', async () => { const { validatorSetHbbft } = await helpers.loadFixture(deployContractsFixture); - await validatorSetHbbft.connect(owner).newValidatorSet().should.be.rejectedWith("Only BlockReward contract"); + await expect(validatorSetHbbft.connect(owner).newValidatorSet()).to.be.revertedWith("Only BlockReward contract"); await validatorSetHbbft.setBlockRewardContract(accounts[4].address); await validatorSetHbbft.connect(accounts[4]).newValidatorSet(); }); @@ -553,31 +566,31 @@ describe('ValidatorSetHbbft', () => { const { validatorSetHbbft } = await helpers.loadFixture(deployContractsFixture); // Check the returned value of the pending validators; it should be an empty list - (await validatorSetHbbft.getPendingValidators()).length.should.be.equal(0); + expect(await validatorSetHbbft.getPendingValidators()).to.be.empty; // Emulate calling `newValidatorSet()` at the last block of the fixed epoch duration await validatorSetHbbft.setBlockRewardContract(accounts[4].address); await validatorSetHbbft.connect(accounts[4]).newValidatorSet(); // Check the returned value of the pending validators; it should be an empty list - (await validatorSetHbbft.getPendingValidators()).length.should.be.equal(3); - (await validatorSetHbbft.getPendingValidators()).should.be.deep.equal(initialValidators); + expect(await validatorSetHbbft.getPendingValidators()).to.have.lengthOf(3); + expect(await validatorSetHbbft.getPendingValidators()).to.deep.equal(initialValidators); }); it('should enqueue only one validator which has non-empty pool', async () => { const { validatorSetHbbft, stakingHbbft } = await helpers.loadFixture(deployContractsFixture); // Emulate staking: the first validator stakes into their own pool - const stakeAmount = BigNumber.from(ethers.utils.parseEther('1')); + const stakeAmount = ethers.parseEther('1'); await stakingHbbft.connect(await ethers.getSigner(initialStakingAddresses[0])).stake(initialStakingAddresses[0], { value: stakeAmount }); - stakeAmount.should.be.equal(await stakingHbbft.stakeAmount(initialStakingAddresses[0], initialStakingAddresses[0])); + expect(await stakingHbbft.stakeAmount(initialStakingAddresses[0], initialStakingAddresses[0])).to.equal(stakeAmount); // Emulate calling `newValidatorSet()` at the last block of the fixed epoch duration await validatorSetHbbft.setBlockRewardContract(accounts[4].address); await validatorSetHbbft.connect(accounts[4]).newValidatorSet(); // Check the returned value of `getPendingValidators()` - (await validatorSetHbbft.getPendingValidators()).should.be.deep.equal([initialValidators[0]]); + expect(await validatorSetHbbft.getPendingValidators()).to.deep.equal([initialValidators[0]]); }); it('should choose validators randomly', async () => { @@ -599,40 +612,40 @@ describe('ValidatorSetHbbft', () => { miningAddresses.push(candidateMiningAddress.toLowerCase()); } - const stakeUnit = BigNumber.from(ethers.utils.parseEther('1')); + const stakeUnit = ethers.parseEther('1'); // Emulate staking by the candidates into their own pool for (let i = 0; i < stakingAddresses.length; i++) { - const stakeAmount = stakeUnit.mul(BigNumber.from(i + 1)); + const stakeAmount = stakeUnit * BigInt(i + 1); await stakingHbbft.connect(await ethers.getSigner(stakingAddresses[i])).addPool( miningAddresses[i], - '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - '0x00000000000000000000000000000000', + ethers.zeroPadBytes("0x00", 64), + ethers.zeroPadBytes("0x00", 16), { value: stakeAmount } ); - stakeAmount.should.be.equal(await stakingHbbft.stakeAmount(stakingAddresses[i], stakingAddresses[i])); + expect(await stakingHbbft.stakeAmount(stakingAddresses[i], stakingAddresses[i])).to.equal(stakeAmount); } // Check pools of the new candidates - (await stakingHbbft.getPoolsToBeElected()).should.be.deep.equal(stakingAddresses); + expect(await stakingHbbft.getPoolsToBeElected()).to.be.deep.equal(stakingAddresses); const poolsLikelihood = await stakingHbbft.getPoolsLikelihood(); - let likelihoodSum = BigNumber.from(0); + + let likelihoodSum = 0n; for (let i = 0; i < stakingAddresses.length; i++) { - const poolLikelihood = stakeUnit.mul(BigNumber.from(i + 1)); - poolsLikelihood[0][i].should.be.equal(BigNumber.from(poolLikelihood)); - likelihoodSum = likelihoodSum.add(poolLikelihood); + const poolLikelihood = stakeUnit * BigInt(i + 1); + + expect(poolsLikelihood[0][i]).to.be.equal(poolLikelihood); + likelihoodSum = likelihoodSum + poolLikelihood; } - poolsLikelihood[1].should.be.equal(BigNumber.from(likelihoodSum)); - // Generate a random seed - (await randomHbbft.currentSeed()).should.be.equal(BigNumber.from(0)); + expect(poolsLikelihood[1]).to.be.equal(likelihoodSum); + expect(await randomHbbft.currentSeed()).to.be.equal(0n); const seed = random(1000000, 2000000); - const systemSigner = await impersonateSystemAcc(); - await randomHbbft.connect(systemSigner).setCurrentSeed(BigNumber.from(seed)); // .should.be.fulfilled; - (await randomHbbft.currentSeed()).should.be.equal(BigNumber.from(seed)); + await randomHbbft.connect(systemSigner).setCurrentSeed(seed); + expect(await randomHbbft.currentSeed()).to.be.equal(seed); await helpers.stopImpersonatingAccount(SystemAccountAddress); @@ -642,10 +655,10 @@ describe('ValidatorSetHbbft', () => { const newValidators = await validatorSetHbbft.getPendingValidators(); - newValidators.length.should.be.equal((await validatorSetHbbft.maxValidators()).toNumber()); + expect(await validatorSetHbbft.maxValidators()).to.be.equal(newValidators.length) for (let i = 0; i < newValidators.length; i++) { - miningAddresses.indexOf(newValidators[i].toLowerCase()).should.be.gte(0); + expect(miningAddresses.indexOf(newValidators[i].toLowerCase())).to.be.gte(0n); } }); }); @@ -661,8 +674,8 @@ describe('ValidatorSetHbbft', () => { const expectedLastWriteTimestamp = await helpers.time.latest(); - (await validatorSetHbbft.validatorAvailableSince(validator)).should.be.equal(availableSince); - (await validatorSetHbbft.validatorAvailableSinceLastWrite(validator)).should.be.equal(expectedLastWriteTimestamp); + expect(await validatorSetHbbft.validatorAvailableSince(validator)).to.be.equal(availableSince); + expect(await validatorSetHbbft.validatorAvailableSinceLastWrite(validator)).to.be.equal(expectedLastWriteTimestamp); }); it('should set validatorAvailableSince=0 and update last write timestamp', async () => { @@ -674,8 +687,8 @@ describe('ValidatorSetHbbft', () => { const expectedLastWriteTimestamp = await helpers.time.latest(); - (await validatorSetHbbft.validatorAvailableSince(validator)).should.be.equal(0); - (await validatorSetHbbft.validatorAvailableSinceLastWrite(validator)).should.be.equal(expectedLastWriteTimestamp); + expect(await validatorSetHbbft.validatorAvailableSince(validator)).to.be.equal(0n); + expect(await validatorSetHbbft.validatorAvailableSinceLastWrite(validator)).to.be.equal(expectedLastWriteTimestamp); }); it('should return false from isValidatorAbandoned for active validator', async () => { @@ -688,10 +701,10 @@ describe('ValidatorSetHbbft', () => { const availableSince = currentTimestamp; await validatorSetHbbft.setValidatorAvailableSince(validator, availableSince); - (await validatorSetHbbft.isValidatorAbandoned(staking)).should.be.equal(false); + expect(await validatorSetHbbft.isValidatorAbandoned(staking)).to.be.false; - await helpers.time.increase(validatorInactivityThreshold + 3600); - (await validatorSetHbbft.isValidatorAbandoned(staking)).should.be.equal(false); + await helpers.time.increase(validatorInactivityThreshold + 3600n); + expect(await validatorSetHbbft.isValidatorAbandoned(staking)).to.be.false; }); it('should return true from isValidatorAbandoned for abandoned validator', async () => { @@ -701,13 +714,13 @@ describe('ValidatorSetHbbft', () => { const staking = await validatorSetHbbft.stakingByMiningAddress(validator); await validatorSetHbbft.setValidatorAvailableSince(validator, 0); - (await validatorSetHbbft.isValidatorAbandoned(staking)).should.be.equal(false); + expect(await validatorSetHbbft.isValidatorAbandoned(staking)).to.be.false; - await helpers.time.increase(validatorInactivityThreshold - 1); - (await validatorSetHbbft.isValidatorAbandoned(staking)).should.be.equal(false); + await helpers.time.increase(validatorInactivityThreshold - 1n); + expect(await validatorSetHbbft.isValidatorAbandoned(staking)).to.be.false; await helpers.time.increase(1); - (await validatorSetHbbft.isValidatorAbandoned(staking)).should.be.equal(true); + expect(await validatorSetHbbft.isValidatorAbandoned(staking)).to.be.true; }); }); @@ -723,8 +736,8 @@ describe('ValidatorSetHbbft', () => { const additionalValidators = accountAddresses.slice(7, 52 + 1); // accounts[7...32] const additionalStakingAddresses = accountAddresses.slice(53, 99 + 1); // accounts[33...59] - additionalValidators.length.should.be.equal(46); - additionalStakingAddresses.length.should.be.equal(46); + expect(additionalValidators).to.be.lengthOf(46); + expect(additionalStakingAddresses).to.be.lengthOf(46); await network.provider.send("evm_setIntervalMining", [8]); @@ -734,8 +747,8 @@ describe('ValidatorSetHbbft', () => { await stakingHbbft.connect(stakingAddress).addPool( miningAddress.address, - '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', - '0x00000000000000000000000000000000', + ethers.zeroPadBytes("0x00", 64), + ethers.zeroPadBytes("0x00", 16), { value: MIN_STAKE } ); await announceAvailability(validatorSetHbbftContract, miningAddress.address); @@ -744,8 +757,9 @@ describe('ValidatorSetHbbft', () => { await validatorSetHbbftContract.setBlockRewardContract(accounts[4].address); await validatorSetHbbftContract.connect(accounts[4]).newValidatorSet(); await validatorSetHbbftContract.connect(accounts[4]).finalizeChange(); + // after epoch was finalized successfully, validator set length is healthy - (await validatorSetHbbft.getValidators()).length.should.be.eq(25); + expect(await validatorSetHbbft.getValidators()).to.be.lengthOf(25); }); it("Should be able to increase max amount of active validators", async () => { @@ -754,8 +768,9 @@ describe('ValidatorSetHbbft', () => { await validatorSetHbbftContract.setBlockRewardContract(accounts[4].address); await validatorSetHbbftContract.connect(accounts[4]).newValidatorSet(); await validatorSetHbbftContract.connect(accounts[4]).finalizeChange(); + // after epoch was finalized successfully, validator set length is healthy - (await validatorSetHbbftContract.getValidators()).length.should.be.eq(30); + expect(await validatorSetHbbftContract.getValidators()).to.be.lengthOf(30); }) it("Should be able to report a malicious validator", async () => { @@ -763,8 +778,15 @@ describe('ValidatorSetHbbft', () => { let maliciousMiningAddress = (await validatorSetHbbftContract.getValidators())[0]; let reportingMiningAddress = await ethers.getSigner((await validatorSetHbbftContract.getValidators())[1]) - await validatorSetHbbftContract.connect(reportingMiningAddress).reportMalicious(maliciousMiningAddress, reportBlock, []); - (await validatorSetHbbftContract.maliceReportedForBlock(maliciousMiningAddress, reportBlock))[0].should.be.eq(reportingMiningAddress.address); + await validatorSetHbbftContract.connect(reportingMiningAddress).reportMalicious( + maliciousMiningAddress, + reportBlock, + EmptyBytes, + ); + + const reportsForBlock = await validatorSetHbbftContract.maliceReportedForBlock(maliciousMiningAddress, reportBlock); + + expect(reportsForBlock[0]).to.be.eq(reportingMiningAddress.address); }) it("Shouldn't be able to report a malicious validator in a future block", async () => { @@ -772,8 +794,13 @@ describe('ValidatorSetHbbft', () => { let maliciousMiningAddress = (await validatorSetHbbftContract.getValidators())[0]; let reportingMiningAddress = await ethers.getSigner((await validatorSetHbbftContract.getValidators())[1]) - await validatorSetHbbftContract.connect(reportingMiningAddress).reportMalicious(maliciousMiningAddress, reportBlock, []); - (await validatorSetHbbftContract.maliceReportedForBlock(maliciousMiningAddress, reportBlock)).should.be.an("array").that.is.empty; + await validatorSetHbbftContract.connect(reportingMiningAddress).reportMalicious( + maliciousMiningAddress, + reportBlock, + EmptyBytes, + ); + + expect(await validatorSetHbbftContract.maliceReportedForBlock(maliciousMiningAddress, reportBlock)).to.be.empty; }) it("Should ban validator after 17 reports", async () => { @@ -783,24 +810,34 @@ describe('ValidatorSetHbbft', () => { for (let i = 1; i < currentValidatorSet.length; i++) { let reportingMiningAddress = await ethers.getSigner(currentValidatorSet[i]) - await validatorSetHbbftContract.connect(reportingMiningAddress).reportMalicious(maliciousMiningAddress, reportBlock, []); + await validatorSetHbbftContract.connect(reportingMiningAddress).reportMalicious( + maliciousMiningAddress, + reportBlock, + EmptyBytes, + ); } - (await validatorSetHbbftContract.maliceReportedForBlock(maliciousMiningAddress, reportBlock)).length.should.be.eq(17); - (await validatorSetHbbftContract.isValidatorBanned(maliciousMiningAddress)).should.be.eq(true); + expect(await validatorSetHbbftContract.maliceReportedForBlock(maliciousMiningAddress, reportBlock)).to.be.lengthOf(17); + expect(await validatorSetHbbftContract.isValidatorBanned(maliciousMiningAddress)).to.be.true; }) it("Validator should get banned if spamming reports (50*maxValidators)", async () => { let currentValidatorSet = await validatorSetHbbftContract.getValidators() let reportBlock = (await ethers.provider.getBlockNumber()) - 1; let reportingMiningAddress = await ethers.getSigner((await validatorSetHbbftContract.getValidators())[0]) + for (let i = 1; i < 54; i++) { for (let j = 1; j < currentValidatorSet.length; j++) { let maliciousMiningAddress = currentValidatorSet[j] - await validatorSetHbbftContract.connect(reportingMiningAddress).reportMalicious(maliciousMiningAddress, reportBlock - i, []); + await validatorSetHbbftContract.connect(reportingMiningAddress).reportMalicious( + maliciousMiningAddress, + reportBlock - i, + EmptyBytes, + ); } } - (await validatorSetHbbftContract.isValidatorBanned(reportingMiningAddress.address)).should.be.eq(true); + + expect(await validatorSetHbbftContract.isValidatorBanned(reportingMiningAddress.address)).to.be.true; }) }); @@ -808,8 +845,11 @@ describe('ValidatorSetHbbft', () => { it('should return an adjusted index for defined inputs', async () => { const { validatorSetHbbft } = await helpers.loadFixture(deployContractsFixture); - const likelihood = [100, 200, 300, 400, 500, 600, 700]; - const likelihoodSum = 2800; + const likelihood = [100n, 200n, 300n, 400n, 500n, 600n, 700n]; + const likelihoodSum = likelihood.reduce( + (accumulator, currentValue) => accumulator + currentValue, + 0n + ); const randomNumbers = [ '102295698372522486450340395642197401505767984240419462599162533279732332782651', @@ -921,17 +961,17 @@ describe('ValidatorSetHbbft', () => { 1, 5, 4, 5, 5, 5, 1, 4, 6, 6, 6, 3, 4, 1, 3, 5, 4, 4, 4, 6, 4, 4, 2, 5, 6 ]; - let results = []; + let results = new Array(); for (let i = 0; i < randomNumbers.length; i++) { const index = await validatorSetHbbft.getRandomIndex( likelihood, likelihoodSum, randomNumbers[i] ); - results.push(index.toNumber()); + results.push(index); } - results.should.be.deep.equal(sampleIndexes); + expect(results).to.deep.equal(sampleIndexes); }); it('should always return an index within the input array size', async () => { @@ -940,8 +980,8 @@ describe('ValidatorSetHbbft', () => { for (let i = 0; i < 100; i++) { const size = random(19, 100); - let likelihood = []; - let likelihoodSum = 0; + let likelihood = new Array(); + let likelihoodSum = 0n; for (let j = 0; j < size; j++) { const randomLikelihood = random(100, 1000); likelihood.push(randomLikelihood); @@ -949,18 +989,22 @@ describe('ValidatorSetHbbft', () => { } let currentSize = size; - let randomNumber = BigNumber.from(random(0, Number.MAX_SAFE_INTEGER)); + let randomNumber = random(0, Number.MAX_SAFE_INTEGER); + for (let j = 0; j < size; j++) { - const index: BigNumber = (await validatorSetHbbft.getRandomIndex( + const index = (await validatorSetHbbft.getRandomIndex( likelihood, likelihoodSum, randomNumber )); - (index.lt(currentSize)).should.be.equal(true); - likelihoodSum -= likelihood[index.toNumber()]; - likelihood[index.toNumber()] = likelihood[currentSize - 1]; + + expect(index).to.be.lt(currentSize); + + likelihoodSum -= likelihood[Number(index)]; + likelihood[Number(index)] = likelihood[Number(currentSize - 1n)]; currentSize--; - randomNumber = BigNumber.from(ethers.utils.soliditySha256(["uint256"], [randomNumber])) + + randomNumber = BigInt(ethers.solidityPackedSha256(["uint256"], [randomNumber])) } } }); @@ -1026,23 +1070,23 @@ describe('ValidatorSetHbbft', () => { const maxFluctuation = 2; // percents, +/- const stakeAmounts = [ - 170000, // 17% - 130000, // 13% - 10000, // 1% - 210000, // 21% - 90000, // 9% - 60000, // 6% - 0, // 0% - 100000, // 10% - 40000, // 4% - 140000, // 14% - 30000, // 3% - 0, // 0% - 20000 // 2% + 170000n, // 17% + 130000n, // 13% + 10000n, // 1% + 210000n, // 21% + 90000n, // 9% + 60000n, // 6% + 0n, // 0% + 100000n, // 10% + 40000n, // 4% + 140000n, // 14% + 30000n, // 3% + 0n, // 0% + 20000n // 2% ]; const stakeAmountsTotal = stakeAmounts.reduce((accumulator, value) => accumulator + value); - const stakeAmountsExpectedShares = stakeAmounts.map((value) => Math.round(value / stakeAmountsTotal * 100)); + const stakeAmountsExpectedShares = stakeAmounts.map((value) => Math.round(Number(value * 100n) / Number(stakeAmountsTotal))); let indexesStats = stakeAmounts.map(() => 0); for (let i = 0; i < repeats; i++) { @@ -1051,54 +1095,52 @@ describe('ValidatorSetHbbft', () => { stakeAmountsTotal, random(0, Number.MAX_SAFE_INTEGER) ); - indexesStats[index.toNumber()]++; + indexesStats[Number(index)]++; } const stakeAmountsRandomShares = indexesStats.map((value) => Math.round(value / repeats * 100)); - //console.log(stakeAmountsExpectedShares); - //console.log(stakeAmountsRandomShares); - stakeAmountsRandomShares.forEach((value, index) => { if (stakeAmountsExpectedShares[index] == 0) { - value.should.be.equal(0); + expect(value).to.equal(0); } else { - Math.abs(stakeAmountsExpectedShares[index] - value).should.be.most(maxFluctuation); + expect(Math.abs(stakeAmountsExpectedShares[index] - value)).to.be.at.most(maxFluctuation); } }); }); }); - describe('getValidatorCountSweetSpot()', async() => { + describe('getValidatorCountSweetSpot()', async () => { it('hbbft sweet spots are calculated correct. getValidatorCountSweetSpot', async () => { const { validatorSetHbbft } = await helpers.loadFixture(deployContractsFixture); const expectedResults = - [1, 2, 3, - 4, 4, 4, - 7, 7, 7, - 10, 10, 10, - 13, 13, 13, - 16, 16, 16, - 19, 19, 19, - 22, 22, 22, - 25 + [ + 1n, 2n, 3n, + 4n, 4n, 4n, + 7n, 7n, 7n, + 10n, 10n, 10n, + 13n, 13n, 13n, + 16n, 16n, 16n, + 19n, 19n, 19n, + 22n, 22n, 22n, + 25n ]; for (let i = 0; i < expectedResults.length; i++) { const expected = expectedResults[i]; const result = await validatorSetHbbft.getValidatorCountSweetSpot(i + 1); - // console.log(`i: ${i}, expected: ${expected}, result: ${result}`); - BigNumber.from(result).should.be.equal(BigNumber.from(expected)); + expect(result).to.equal(expected); } - }); }); - describe('setValidatorInternetAddress()', async() => { + describe('setValidatorInternetAddress()', async () => { + let validatorSetPermission: Permission + it('Validator Candidates can write and read their IP Address', async () => { - let validators = accounts.slice(1,5); - let pools = accounts.slice(5,9); + let validators = accounts.slice(1, 5); + let pools = accounts.slice(5, 9); let initialMiningAddr = [validators[0].address]; let initialStakingAddr = [pools[0].address]; @@ -1106,7 +1148,7 @@ describe('ValidatorSetHbbft', () => { const stubAddress = owner.address; const ValidatorSetFactory = await ethers.getContractFactory("ValidatorSetHbbftMock"); - const validatorSetHbbft = await upgrades.deployProxy( + const validatorSetHbbftProxy = await upgrades.deployProxy( ValidatorSetFactory, [ owner.address, @@ -1119,47 +1161,54 @@ describe('ValidatorSetHbbft', () => { initialStakingAddr, // _initialStakingAddresses ], { initializer: 'initialize' } - ) as ValidatorSetHbbftMock; + ); + + await validatorSetHbbftProxy.waitForDeployment(); const BlockRewardHbbftFactory = await ethers.getContractFactory("BlockRewardHbbftMock"); const blockRewardHbbft = await upgrades.deployProxy( BlockRewardHbbftFactory, [ owner.address, - validatorSetHbbft.address, + await validatorSetHbbftProxy.getAddress(), stubAddress ], { initializer: 'initialize' } - ) as BlockRewardHbbftMock; + ); + + await blockRewardHbbft.waitForDeployment(); const CertifierFactory = await ethers.getContractFactory("CertifierHbbft"); const certifier = await upgrades.deployProxy( CertifierFactory, [ [owner.address], - validatorSetHbbft.address, + await validatorSetHbbftProxy.getAddress(), owner.address ], { initializer: 'initialize' } - ) as CertifierHbbft; + ); + + await certifier.waitForDeployment(); const keyGenHistoryFake = "0x8000000000000000000000000000000000000001"; const TxPermissionFactory = await ethers.getContractFactory("TxPermissionHbbft"); - const txPermission = await upgrades.deployProxy( + const txPermissionProxy = await upgrades.deployProxy( TxPermissionFactory, [ [owner.address], - certifier.address, - validatorSetHbbft.address, + await certifier.getAddress(), + await validatorSetHbbftProxy.getAddress(), keyGenHistoryFake, stubAddress, owner.address ], { initializer: 'initialize' } - ) as TxPermissionHbbft; + ); + + await txPermissionProxy.waitForDeployment(); - vaidatorSetPermission = new Permission(txPermission, validatorSetHbbft, false); let stakingParams = { _candidateMinStake: 1000, @@ -1169,14 +1218,14 @@ describe('ValidatorSetHbbft', () => { _maxStake: 5000, _stakingTransitionTimeframeLength: 10, _stakingWithdrawDisallowPeriod: 10, - _validatorSetContract: validatorSetHbbft.address, + _validatorSetContract: await validatorSetHbbftProxy.getAddress(), }; const fakePK = "0xa255fd7ad199f0ee814ee00cce44ef2b1fa1b52eead5d8013ed85eade03034ae"; const fakeIP = "0x00000000000000000000000000000001" const StakingHbbftFactory = await ethers.getContractFactory("StakingHbbftMock"); - const stakingHbbft = await upgrades.deployProxy( + const stakingHbbftProxy = await upgrades.deployProxy( StakingHbbftFactory, [ owner.address, @@ -1185,97 +1234,101 @@ describe('ValidatorSetHbbft', () => { [fakeIP] // _internetAddresses ], { initializer: 'initialize' } + ); + + await stakingHbbftProxy.waitForDeployment(); + + const txPermission = TxPermissionFactory.attach( + await txPermissionProxy.getAddress() + ) as TxPermissionHbbft; + + const validatorSetHbbft = ValidatorSetFactory.attach( + await validatorSetHbbftProxy.getAddress() + ) as ValidatorSetHbbftMock; + + const stakingHbbft = StakingHbbftFactory.attach( + await stakingHbbftProxy.getAddress() ) as StakingHbbftMock; - await validatorSetHbbft.setBlockRewardContract(blockRewardHbbft.address); - await validatorSetHbbft.setStakingContract(stakingHbbft.address); + validatorSetPermission = new Permission(txPermission, validatorSetHbbft, false); - blockRewardHbbft.address.should.be.equal( - await validatorSetHbbft.blockRewardContract() - ); - '0x3000000000000000000000000000000000000001'.should.be.equal( - await validatorSetHbbft.randomContract() - ); - stakingHbbft.address.should.be.equal( - await validatorSetHbbft.getStakingContract() - ); - '0x8000000000000000000000000000000000000001'.should.be.equal( - await validatorSetHbbft.keyGenHistoryContract() - ); + await validatorSetHbbft.setBlockRewardContract(await blockRewardHbbft.getAddress()); + await validatorSetHbbft.setStakingContract(await stakingHbbft.getAddress()); + + expect(await validatorSetHbbft.blockRewardContract()).to.equal(await blockRewardHbbft.getAddress()); + expect(await validatorSetHbbft.getStakingContract()).to.equal(await stakingHbbft.getAddress()); + expect(await validatorSetHbbft.randomContract()).to.equal('0x3000000000000000000000000000000000000001'); + expect(await validatorSetHbbft.keyGenHistoryContract()).to.equal('0x8000000000000000000000000000000000000001') - const poolsFromContract = await stakingHbbft.getPools(); - poolsFromContract.length.should.be.not.equal(0); - let ip_last = 1; + expect(await stakingHbbft.getPools()).to.be.not.empty; - //const activePools = []; + let ipLast = 1; for (let pool of pools) { if (await stakingHbbft.isPoolActive(pool.address)) { const validatorAddress = await validatorSetHbbft.miningByStakingAddress(pool.address); - const ipAddress = [0,0,0,0,0,0,0,0,0,0,0,0,192, 168, 0, ip_last]; - const port = 30303; - // console.log(`Setting IP address for pool ${pool.address}( validator: ) ${validatorAddress} to ${ipAddress}`); - await setValidatorInternetAddress(validatorAddress, ipAddress, port); + const ipAddress = new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 192, 168, 0, ipLast]); + const port = 30303; + + await setValidatorInternetAddress(validatorSetPermission, validatorAddress, ipAddress, port); const writtenIP = await getValidatorInternetAddress(stakingHbbft, pool.address); - // console.log(`read IP Address is:`, writtenIP.ipAddress); - writtenIP.ipAddress.should.be.deep.equal(ipAddress); - writtenIP.port.should.be.equal(port); + + expect(writtenIP).to.deep.equal({ ipAddress: ipAddress, port: BigInt(port) }); } - ip_last++; + ipLast++; } }); }); - - describe('setValidatorInactivityThreshold()', async() => { - it('fail on small value', async () => { + + describe('setValidatorInactivityThreshold()', async () => { + it('fail on small value', async () => { const { validatorSetHbbft } = await helpers.loadFixture(deployContractsFixture); await expect(validatorSetHbbft.setValidatorInactivityThreshold(100)).to.be.revertedWith("_seconds value must be less then a week."); + }); - }); - - it('correct value is set', async () => { + it('correct value is set', async () => { const { validatorSetHbbft } = await helpers.loadFixture(deployContractsFixture); - let value30Days = 2592000; - await validatorSetHbbft.setValidatorInactivityThreshold(value30Days); + let value30Days = 2592000; + await validatorSetHbbft.setValidatorInactivityThreshold(value30Days); expect(await validatorSetHbbft.validatorInactivityThreshold()).to.be.equal(value30Days); - }); + }); - it('only owner should be able to change value', async () => { + it('only owner should be able to change value', async () => { const { validatorSetHbbft } = await helpers.loadFixture(deployContractsFixture); - let nobody = (await ethers.getSigners())[42]; - let value30Days = 2592000; - await expect(validatorSetHbbft.connect(nobody).setValidatorInactivityThreshold(value30Days)).to.be.revertedWith("Ownable: caller is not the owner"); + let nobody = (await ethers.getSigners())[42]; + let value30Days = 2592000; + + await expect(validatorSetHbbft.connect(nobody).setValidatorInactivityThreshold(value30Days)) + .to.be.revertedWith("Ownable: caller is not the owner"); }); }); }); -function convertToBigEndian(number: number): number[] { +function convertToBigEndian(number: number): Uint8Array { const byte1 = number & 0xFF; const byte2 = (number >> 8) & 0xFF; - return [byte2, byte1]; - + return new Uint8Array([byte2, byte1]); } interface InternetAddress { - ipAddress: number[]; - port: number; + ipAddress: Uint8Array; + port: bigint; } -async function getValidatorInternetAddress(stakingHbbft: StakingHbbftMock, pool: string) : Promise { +async function getValidatorInternetAddress(stakingHbbft: StakingHbbftMock, pool: string): Promise { const call_result = await stakingHbbft.getPoolInternetAddress(pool); - const portBN = BigNumber.from(call_result[1]); + const port = call_result[1]; const ipArray = parseHexString(call_result[0]); return { ipAddress: ipArray, - port: portBN.toNumber() + port: BigInt(port) } } -function parseHexString(str: string) : number[] { - +function parseHexString(str: string): Uint8Array { // remove leading 0x if present. if (str.substring(0, 2) == "0x") { str = str.substring(2, str.length); @@ -1287,36 +1340,37 @@ function parseHexString(str: string) : number[] { str = str.substring(2, str.length); } - return result; + return new Uint8Array(result); } -async function setValidatorInternetAddress(miner: string, ipAddress: number[], port: number) : Promise { +async function setValidatorInternetAddress( + validatorSetPermission: Permission, + miner: string, + ipAddress: Uint8Array, + port: number +): Promise { if (port > 65535) { throw new Error('Port number is too big'); } // transform the Port number into a 2 bytes little endian number Array. let portArray = convertToBigEndian(port); - return vaidatorSetPermission.callFunction("setValidatorInternetAddress", miner, [ipAddress, portArray]); -} - -function random(low: number, high: number) { - return Math.floor((Math.random() * (high - low) + low)); + return validatorSetPermission.callFunction("setValidatorInternetAddress", miner, [ipAddress, portArray]); } async function announceAvailability(validatorSetHbbft: ValidatorSetHbbftMock, pool: string) { const blockNumber = await ethers.provider.getBlockNumber() const block = await ethers.provider.getBlock(blockNumber); - const asEncoded = validatorSetHbbft.interface.encodeFunctionData("announceAvailability", [blockNumber, block.hash]); + + const asEncoded = validatorSetHbbft.interface.encodeFunctionData( + "announceAvailability", + [blockNumber, block!.hash!] + ); // we know now, that this call is allowed. // so we can execute it. - await (await ethers.getSigner(pool)).sendTransaction({ to: validatorSetHbbft.address, data: asEncoded }); -} - -async function getCurrentGovernancePotValue(blockRewardHbbft: BlockRewardHbbftMock) { - const governnancePotAddress = await blockRewardHbbft.governancePotAddress(); - (BigNumber.from(governnancePotAddress)).should.be.gt(BigNumber.from(0)); - const result = BigNumber.from(await ethers.provider.getBalance(governnancePotAddress)); - return result; + await (await ethers.getSigner(pool)).sendTransaction({ + to: await validatorSetHbbft.getAddress(), + data: asEncoded + }); } diff --git a/test/testhelpers/Permission.ts b/test/testhelpers/Permission.ts index 2e5e450b..372cf1a9 100644 --- a/test/testhelpers/Permission.ts +++ b/test/testhelpers/Permission.ts @@ -1,22 +1,13 @@ import { ethers } from "hardhat"; -import { BaseContract, BigNumber } from "ethers"; -import { TransactionResponse } from "@ethersproject/abstract-provider"; +import { BaseContract, TransactionResponse } from "ethers"; -import { - TxPermissionHbbft, -} from "../../src/types"; +import { TxPermissionHbbft } from "../../src/types"; +import { expect } from "chai"; +export class Permission { + public constructor(public permissionContract: TxPermissionHbbft, public contract: T, public logOutput = false) { } -export class Permission -{ - public constructor(public permissionContract: TxPermissionHbbft, public contract: T, public logOutput = false) { - - } - - - public async callFunction(functionName: string, from: string, params: any[]) : Promise { - - + public async callFunction(functionName: string, from: string, params: any[]): Promise { //keyGenHistory.interface.encodeFunctionData() const asEncoded = this.contract.interface.encodeFunctionData(functionName, params); if (this.logOutput) { @@ -32,21 +23,30 @@ export class Permission //console.log('numberFromContract2', numberFromContract2.toString()); - const allowedTxType = await this.permissionContract.allowedTxTypes(from, this.contract.address, '0x0' /* value */, '0x0' /* gas price */, asEncoded); + const allowedTxType = await this.permissionContract.allowedTxTypes( + from, + await this.contract.getAddress(), + 0n /* value */, + 0n /* gas price */, + asEncoded + ); //console.log(allowedTxType.typesMask.toString()); // don't ask to cache this result. - allowedTxType.cache.should.be.equal(false); + expect(allowedTxType.cache).to.be.false; /// 0x01 - basic transaction (e.g. ether transferring to user wallet); /// 0x02 - contract call; /// 0x04 - contract creation; /// 0x08 - private transaction. - allowedTxType.typesMask.should.be.equal(BigNumber.from('2'), 'Transaction should be allowed according to TxPermission Contract.'); + expect(allowedTxType.typesMask).to.be.equal(2n, 'Transaction should be allowed according to TxPermission Contract.'); // we know now, that this call is allowed. // so we can execute it. - return (await ethers.getSigner(from)).sendTransaction({ to: this.contract.address, data: asEncoded }); + return (await ethers.getSigner(from)).sendTransaction({ + to: await this.contract.getAddress(), + data: asEncoded + }); } -} \ No newline at end of file +} diff --git a/test/testhelpers/data.js b/test/testhelpers/data.js deleted file mode 100644 index ccada1f1..00000000 --- a/test/testhelpers/data.js +++ /dev/null @@ -1,20 +0,0 @@ - -/// gets a set of 3 real Acks and Parts for testing purposes -function getTestPartNAcks() { - - const partsRaw = [[0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,162,238,181,164,119,226,238,142,43,227,179,139,95,25,108,237,11,190,84,64,234,22,245,210,187,24,142,145,31,26,197,119,92,171,182,30,182,191,151,218,208,96,103,110,14,170,189,220,3,0,0,0,0,0,0,0,153,0,0,0,0,0,0,0,4,21,73,242,168,17,236,103,137,92,198,188,151,185,9,174,175,170,174,57,210,222,4,81,210,164,8,69,148,77,228,38,240,153,232,223,247,87,154,182,186,84,25,66,211,40,191,201,51,82,23,210,22,213,222,200,8,206,218,143,128,49,28,60,223,37,52,95,47,33,245,72,158,241,216,97,244,234,136,89,239,199,11,252,232,95,18,174,135,13,237,240,213,206,206,85,52,124,247,123,199,87,112,132,42,136,94,223,15,75,137,122,27,20,92,167,40,222,99,160,147,245,251,242,221,134,74,193,248,249,246,54,58,185,109,78,212,36,101,241,65,82,183,246,62,156,217,247,255,92,205,160,220,153,0,0,0,0,0,0,0,4,249,64,230,166,97,82,165,124,79,27,92,167,19,229,52,40,203,120,236,87,142,125,122,227,174,162,64,228,170,35,46,169,74,119,13,26,126,67,141,151,3,86,253,135,156,100,60,42,68,245,201,4,66,216,34,29,88,229,82,88,171,213,215,25,96,245,193,33,229,228,139,233,239,14,164,187,39,151,82,164,72,181,215,161,64,167,181,169,96,89,32,93,180,176,201,116,8,190,99,179,132,43,11,107,59,223,207,173,43,197,181,169,127,184,189,122,220,159,133,133,17,192,5,149,159,97,197,143,104,103,252,93,120,213,56,242,193,4,27,187,151,60,172,129,55,69,23,243,110,119,16,151,153,0,0,0,0,0,0,0,4,144,226,236,244,137,245,236,219,56,172,227,38,22,176,15,182,184,184,45,175,169,208,170,150,182,129,76,191,47,255,123,213,136,70,214,129,234,24,96,55,181,159,73,123,96,55,238,104,140,106,39,86,194,82,217,229,245,194,114,78,33,192,217,137,147,141,230,183,211,227,236,196,102,226,30,247,198,211,117,159,70,135,219,249,232,158,39,102,214,42,163,97,67,172,10,15,53,212,46,69,144,227,87,81,113,248,238,229,74,78,4,158,139,125,42,181,220,208,108,188,71,4,193,66,135,63,246,180,166,251,117,160,133,3,14,154,17,254,34,215,98,212,107,3,219,145,162,81,154,129,98,30],[0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,178,73,138,14,3,78,162,102,191,223,232,10,81,96,118,193,17,245,152,100,177,160,138,30,241,144,254,80,221,191,133,251,43,252,251,55,111,234,36,30,11,227,3,209,11,29,97,12,3,0,0,0,0,0,0,0,153,0,0,0,0,0,0,0,4,190,190,139,180,190,148,3,35,23,114,210,184,188,37,29,84,197,247,58,199,180,139,151,50,108,72,160,72,104,120,177,113,88,114,102,35,83,214,49,107,226,189,62,146,134,227,121,204,221,170,229,103,242,35,66,174,12,222,96,244,80,109,177,162,22,173,241,253,188,107,213,119,32,142,210,120,23,6,255,53,195,183,16,224,211,157,34,76,41,196,121,60,10,124,231,193,177,178,201,176,242,10,34,30,74,16,76,255,101,225,104,179,5,15,231,147,247,214,103,172,127,161,226,217,18,140,93,42,235,252,105,19,214,191,80,37,230,77,82,122,248,38,124,30,68,164,81,129,51,162,87,154,153,0,0,0,0,0,0,0,4,45,167,32,19,176,115,181,244,240,144,71,62,123,234,47,139,101,220,132,48,31,222,255,194,15,65,214,103,75,68,161,78,40,143,28,242,143,191,87,76,169,19,24,217,145,231,90,139,69,34,90,12,175,146,173,49,116,34,148,58,62,142,168,154,1,79,76,99,59,135,153,22,213,9,80,206,179,110,110,123,8,42,101,53,36,241,202,64,203,169,148,175,0,2,217,163,109,89,248,214,243,66,44,69,11,100,90,132,74,218,16,240,20,157,154,134,8,63,131,18,59,157,105,93,133,47,166,97,196,160,48,54,218,118,46,146,224,36,123,226,204,171,215,17,73,92,147,55,1,41,54,32,153,0,0,0,0,0,0,0,4,116,101,44,65,60,102,230,141,166,221,113,19,43,220,253,67,27,109,103,171,33,42,189,108,84,229,139,200,63,218,76,180,101,159,208,102,117,168,34,185,211,61,12,143,250,49,210,194,39,135,64,150,174,159,196,254,136,138,229,53,214,85,228,119,125,222,201,207,137,10,57,88,233,155,50,94,50,238,174,188,71,119,14,67,50,222,24,92,82,87,126,120,5,30,112,40,106,216,120,181,16,197,44,52,86,129,181,241,249,91,31,253,24,42,106,14,5,175,226,29,226,200,218,97,99,81,125,219,133,214,228,198,138,241,41,193,138,218,51,168,61,46,35,86,144,153,99,180,150,11,4,112],[0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,170,254,25,182,81,8,235,232,45,133,72,208,54,10,151,224,33,250,175,154,155,189,139,187,155,22,199,114,11,221,65,195,66,45,57,81,129,41,252,72,173,189,241,122,193,176,97,209,3,0,0,0,0,0,0,0,153,0,0,0,0,0,0,0,4,106,140,219,6,75,230,222,99,131,82,163,144,68,231,71,69,7,214,27,149,103,189,152,156,32,231,59,113,140,92,46,178,144,219,172,255,183,225,111,161,65,244,242,135,6,223,69,149,189,167,16,27,107,145,136,2,12,12,243,105,75,232,172,184,119,164,14,223,101,219,182,114,55,189,158,72,194,84,185,46,74,77,128,16,2,195,132,20,78,189,141,196,64,145,81,196,15,182,249,21,181,205,247,242,35,208,150,216,84,254,243,5,232,211,110,196,137,93,18,176,42,201,176,20,114,94,139,48,60,113,173,246,59,152,54,204,22,124,81,29,86,57,176,80,68,85,253,54,169,193,165,91,153,0,0,0,0,0,0,0,4,104,82,218,8,57,188,206,90,232,210,234,64,176,216,102,167,61,82,75,197,47,186,148,82,186,148,182,186,30,33,232,250,130,0,204,228,25,63,7,21,157,244,225,15,53,251,119,149,11,45,150,165,213,162,59,248,44,174,177,88,128,38,11,228,110,198,243,237,199,79,167,252,11,250,131,140,109,122,89,181,115,128,198,25,153,196,196,248,72,212,208,54,32,102,7,208,238,103,32,125,62,111,222,83,6,5,148,59,10,74,29,64,4,251,189,34,108,226,206,8,77,109,181,121,208,54,82,193,89,132,22,238,147,160,28,88,39,32,50,147,222,138,153,191,243,96,34,218,212,51,159,23,153,0,0,0,0,0,0,0,4,20,112,232,10,136,250,15,177,137,89,249,144,240,199,202,172,135,49,130,254,98,208,175,191,151,185,180,168,51,4,128,163,66,75,212,151,21,75,144,199,45,191,89,166,90,109,221,74,10,97,171,7,180,219,192,127,71,90,221,87,223,233,110,232,90,245,107,197,138,136,222,206,16,139,147,205,107,117,53,190,36,204,74,112,199,210,123,131,71,199,95,6,181,165,60,186,116,116,46,203,91,155,5,187,22,95,215,92,2,77,79,204,34,75,118,213,76,78,37,180,26,63,220,229,190,164,60,155,245,136,80,165,197,44,64,108,99,152,129,80,83,235,94,234,233,252,49,252,182,182,178,2]] - - const acks = [[[0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,145,0,0,0,0,0,0,0,4,49,56,206,120,208,7,197,245,119,88,166,31,191,100,103,74,94,140,184,31,111,69,189,192,100,241,203,205,189,66,172,233,179,112,132,219,243,78,177,183,108,34,50,65,27,107,63,176,91,62,117,81,36,102,5,36,26,45,216,19,213,65,150,109,205,225,150,94,35,42,219,196,29,193,159,197,151,197,236,146,233,109,92,114,132,158,253,177,201,2,138,19,105,71,220,139,123,226,74,75,79,151,109,146,250,223,71,240,101,163,100,232,34,18,27,190,42,160,240,234,71,10,190,225,42,86,126,84,180,104,163,30,81,152,217,249,46,39,75,180,37,174,25,146,145,0,0,0,0,0,0,0,4,209,118,244,76,61,65,111,73,69,38,163,50,120,117,116,225,140,206,177,188,80,71,117,111,112,177,119,120,97,192,129,63,57,10,114,60,228,137,64,189,13,184,18,147,153,76,28,166,129,11,39,164,61,116,170,155,126,161,25,67,121,213,137,1,248,133,179,141,36,108,52,127,4,2,206,60,231,133,30,94,38,184,209,145,138,230,43,82,129,228,215,42,47,192,240,126,84,97,60,129,195,203,232,81,192,119,161,187,1,255,141,201,188,35,19,205,98,234,206,113,235,15,84,88,223,168,79,142,139,113,138,109,198,168,166,134,84,148,62,238,107,210,58,184,145,0,0,0,0,0,0,0,4,169,49,88,116,160,40,158,158,37,164,106,95,107,236,212,41,98,167,202,51,165,245,162,176,162,13,27,94,205,72,164,85,128,234,178,50,240,91,53,79,54,43,208,184,144,253,54,115,5,143,67,187,222,154,181,174,39,92,120,202,117,148,241,147,163,105,150,75,56,172,215,31,143,93,13,100,27,25,52,111,206,176,55,61,33,42,77,189,94,69,182,212,97,111,43,129,38,216,218,117,64,250,128,254,104,165,160,72,205,2,142,157,116,95,218,49,143,85,160,190,195,205,97,21,77,85,58,4,94,3,253,167,237,55,75,101,200,198,97,122,46,153,85,104],[1,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,145,0,0,0,0,0,0,0,4,23,51,20,34,33,38,160,91,243,39,211,84,188,187,32,88,121,194,65,132,6,33,255,93,159,16,49,126,232,121,180,244,229,106,87,125,60,156,166,70,125,207,203,103,115,212,153,133,130,108,248,22,122,230,95,106,74,90,123,120,171,33,102,115,12,56,14,171,238,173,226,146,136,62,60,201,28,178,216,162,107,163,48,76,227,28,104,85,33,252,28,249,108,249,27,72,213,44,161,33,253,20,154,127,29,27,84,76,10,232,211,60,248,37,50,100,210,125,71,109,155,165,246,47,85,219,71,51,28,163,219,240,253,113,156,131,70,148,248,187,146,135,167,165,145,0,0,0,0,0,0,0,4,192,60,165,5,196,71,96,49,93,153,135,242,152,67,254,94,244,186,64,132,128,112,67,102,177,240,181,105,170,39,57,176,247,119,207,134,253,249,122,30,151,118,91,107,16,88,156,112,214,181,199,115,246,190,173,85,153,49,13,107,64,173,3,76,236,221,54,120,163,47,192,242,19,35,90,153,37,202,166,22,33,252,250,218,68,80,197,134,147,230,72,107,239,119,69,53,177,53,92,248,15,154,177,116,202,54,140,118,62,188,103,36,5,160,74,145,223,101,251,190,96,122,191,34,227,47,66,152,165,238,80,210,237,104,71,158,119,13,105,141,144,0,178,141,145,0,0,0,0,0,0,0,4,225,41,255,228,45,231,42,88,201,191,196,69,54,108,214,0,203,113,53,203,41,155,102,29,59,80,28,21,199,78,156,141,205,214,137,150,105,116,44,164,70,53,174,153,241,100,139,87,176,6,39,38,21,0,186,0,126,67,56,61,179,90,176,124,223,224,160,121,228,119,98,103,241,178,118,96,137,223,193,235,135,196,83,1,81,221,201,242,238,155,66,12,221,16,213,18,198,232,69,253,82,230,12,212,83,137,100,18,169,241,101,21,135,126,201,168,200,16,209,248,169,108,55,250,131,104,64,209,203,142,56,15,250,225,253,236,25,208,180,120,9,110,234,184],[2,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,145,0,0,0,0,0,0,0,4,100,13,69,238,212,63,79,226,98,251,16,122,85,165,126,121,80,111,42,109,158,70,24,38,38,111,158,79,150,173,105,34,161,225,200,179,88,218,70,23,237,26,224,110,79,152,70,59,118,103,5,164,71,141,68,50,222,235,190,144,52,217,236,70,228,228,120,58,4,140,229,232,184,37,120,151,84,2,188,45,166,166,161,187,131,248,99,81,88,35,244,114,124,35,188,35,226,110,116,96,22,200,7,218,13,242,120,227,18,75,233,181,235,133,22,176,183,146,218,62,35,32,39,72,51,200,142,43,139,0,30,41,253,158,80,250,68,109,221,189,177,28,230,134,145,0,0,0,0,0,0,0,4,230,16,43,212,214,93,133,200,66,103,14,32,84,113,112,209,67,34,129,26,136,225,228,116,249,229,195,82,36,247,52,191,165,171,143,36,78,7,95,249,100,75,104,11,108,10,125,197,38,196,120,79,205,57,54,20,100,210,169,117,30,216,101,211,1,65,202,100,146,162,231,241,5,28,237,106,82,140,136,157,60,156,166,30,139,215,218,54,192,91,26,101,227,29,219,61,209,239,219,79,194,67,158,79,171,209,46,25,90,148,156,228,253,187,118,109,190,207,97,190,225,163,65,76,250,34,125,135,80,183,141,21,182,39,53,50,53,17,231,237,74,203,174,220,145,0,0,0,0,0,0,0,4,49,229,95,158,235,69,183,126,193,92,120,197,77,79,151,132,150,130,123,226,27,226,253,204,82,95,181,114,206,239,142,232,86,117,230,232,39,123,255,21,227,52,86,154,154,217,229,4,14,111,147,103,147,193,202,157,166,220,177,1,38,93,150,126,205,238,236,213,7,187,40,13,219,11,219,121,36,90,202,159,30,159,62,6,87,109,210,169,62,53,162,10,41,238,83,97,148,23,65,146,115,98,52,29,241,192,189,6,150,174,21,123,176,123,226,75,128,104,115,68,6,217,1,159,67,121,20,198,240,72,151,231,217,154,29,120,64,123,232,14,202,99,231,251]],[[0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,145,0,0,0,0,0,0,0,4,184,101,147,79,192,143,119,143,72,141,194,218,23,81,123,6,94,214,88,150,139,211,68,135,97,69,29,94,41,91,26,204,61,24,91,217,137,202,97,9,18,148,103,186,213,187,223,230,25,110,175,110,90,114,194,73,165,219,155,212,227,186,187,166,92,183,23,67,2,63,180,17,40,8,93,62,100,159,223,39,225,254,172,23,104,91,22,115,192,67,106,71,6,46,27,2,222,129,174,89,183,59,187,198,112,18,17,54,82,144,204,17,210,245,97,214,176,33,220,17,74,18,178,66,43,250,173,88,181,106,91,105,221,54,26,223,99,64,50,20,108,139,245,104,145,0,0,0,0,0,0,0,4,103,215,2,70,67,85,254,117,92,62,181,133,48,134,52,71,18,106,60,87,218,85,75,223,233,176,92,120,124,200,214,185,85,234,88,94,29,171,232,194,5,189,88,126,173,116,216,3,98,168,191,124,33,154,219,4,137,156,101,110,139,4,173,100,212,241,251,197,120,8,220,188,12,228,174,113,167,127,4,97,115,155,57,38,93,245,5,3,114,61,38,194,193,33,48,196,239,88,116,63,24,255,62,246,73,77,234,138,136,93,133,105,9,29,172,52,46,101,13,129,147,75,39,25,160,179,25,88,185,85,81,240,130,180,145,12,165,206,127,142,31,233,182,117,145,0,0,0,0,0,0,0,4,125,157,244,235,22,158,28,67,94,19,16,164,238,104,224,161,47,190,216,231,249,164,129,25,238,142,145,219,48,178,181,190,209,90,107,218,157,54,101,107,81,249,140,245,169,31,47,89,39,165,99,119,87,179,112,49,81,69,2,25,227,202,37,246,115,211,85,250,25,127,52,13,228,153,108,11,47,65,133,2,45,120,125,202,166,126,113,98,185,21,91,152,3,189,240,11,253,38,225,249,239,93,239,187,102,106,145,78,99,42,15,190,254,157,170,114,170,142,108,108,67,172,246,3,209,238,143,155,254,156,246,121,30,86,133,136,214,44,31,156,211,224,222,237],[1,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,145,0,0,0,0,0,0,0,4,245,37,118,90,114,11,69,85,13,113,7,10,46,220,128,237,70,201,68,71,248,182,116,96,130,201,35,161,178,141,45,55,39,87,44,21,118,135,5,60,194,1,216,148,24,127,129,234,172,95,202,131,157,77,245,198,63,183,33,45,123,242,220,247,20,196,159,155,204,250,69,161,10,93,189,70,10,97,122,141,22,61,77,21,49,86,64,137,21,43,221,154,68,7,38,203,241,208,207,125,144,211,255,135,247,27,211,203,6,189,88,198,161,156,15,58,244,254,58,171,120,239,1,83,22,236,178,245,156,59,10,11,21,33,121,227,47,25,62,160,193,73,252,123,145,0,0,0,0,0,0,0,4,50,105,164,252,224,42,30,14,83,98,248,84,249,220,134,92,208,38,53,131,214,224,87,147,147,185,212,9,134,64,43,50,28,108,234,96,14,107,243,170,216,151,162,163,208,7,198,253,12,236,16,203,174,4,48,135,216,146,175,253,10,35,203,153,123,20,105,163,223,250,166,82,141,225,134,94,27,124,157,123,110,174,31,240,203,25,146,16,101,147,74,70,107,68,78,61,178,42,126,11,177,157,18,109,54,194,124,160,236,96,187,113,162,0,68,209,93,80,239,239,73,177,74,163,97,248,138,157,21,225,77,71,152,208,192,109,19,49,222,147,105,230,187,26,145,0,0,0,0,0,0,0,4,196,48,14,64,241,20,121,45,118,108,242,220,188,251,9,107,149,237,200,167,223,80,201,104,246,181,10,255,48,238,65,55,250,9,224,197,155,166,88,92,243,71,134,100,103,55,215,124,201,181,48,208,69,30,86,179,107,38,74,80,138,169,30,221,251,16,192,12,161,130,59,65,116,91,186,37,161,54,141,67,221,161,216,44,175,218,171,197,177,244,193,164,192,140,196,90,171,162,210,100,194,164,195,189,249,124,97,79,250,133,185,89,174,62,150,155,35,87,33,82,61,38,232,43,228,126,92,91,225,253,240,28,91,77,191,108,152,75,154,244,98,221,191,41],[2,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,145,0,0,0,0,0,0,0,4,208,125,51,24,222,224,29,26,2,119,35,43,81,99,219,140,237,96,92,48,25,35,74,4,122,119,52,55,237,99,4,144,36,224,73,174,186,0,12,39,68,103,42,134,94,0,103,107,106,211,95,98,195,248,225,183,114,52,180,10,14,36,107,238,92,93,0,121,27,201,235,125,8,100,243,73,198,214,4,217,47,60,70,194,237,149,25,135,181,31,69,97,89,42,189,55,78,56,5,104,213,119,91,115,37,201,144,98,167,187,33,253,113,207,76,20,178,24,214,144,89,186,166,135,14,51,107,97,144,163,139,211,32,17,212,27,207,155,228,3,232,99,29,60,145,0,0,0,0,0,0,0,4,234,91,111,181,233,101,114,213,130,88,131,151,254,87,194,245,250,230,67,44,21,75,113,99,35,227,123,228,175,10,249,92,34,132,237,153,77,82,121,49,55,152,228,11,46,181,146,34,5,3,138,34,124,85,0,224,9,106,36,210,163,56,94,235,72,252,235,77,30,179,248,61,123,143,39,120,163,112,18,35,141,62,143,237,22,9,66,21,3,62,100,5,46,255,142,248,160,235,218,215,209,249,65,40,221,198,201,113,8,223,82,78,41,189,237,58,52,36,237,29,112,210,54,79,232,40,100,68,151,113,155,194,127,109,170,203,56,80,214,156,160,169,170,185,145,0,0,0,0,0,0,0,4,144,88,183,137,94,77,106,60,58,106,25,131,143,146,102,70,96,101,51,196,134,213,70,185,103,71,239,116,121,157,246,50,143,242,178,108,249,215,239,222,147,243,250,216,14,192,52,246,247,244,232,119,186,159,2,36,114,163,241,82,32,197,173,98,98,42,126,14,241,129,221,106,67,41,115,178,175,34,150,92,28,40,189,70,225,15,81,134,167,214,149,173,118,25,166,226,7,163,125,124,193,175,36,163,136,128,131,86,62,64,56,176,251,4,91,42,46,167,97,141,136,49,137,96,99,124,173,113,76,33,36,202,116,5,0,254,78,198,243,113,77,124,227,174]],[[0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,145,0,0,0,0,0,0,0,4,23,250,79,243,54,117,62,80,179,97,221,176,136,63,222,209,236,75,87,159,246,168,252,213,57,22,96,252,27,160,103,102,80,93,78,34,182,54,109,189,204,137,210,232,139,103,3,147,219,189,217,31,68,104,247,120,169,69,79,85,180,196,118,81,189,161,132,143,123,51,43,132,220,79,82,247,160,134,243,153,40,54,207,158,51,52,168,105,127,210,129,206,119,10,251,112,225,3,181,153,204,171,86,17,102,145,81,48,60,27,219,84,8,200,15,236,158,110,58,86,225,242,33,43,29,211,190,141,197,77,250,211,84,108,189,249,186,15,248,239,126,130,47,1,145,0,0,0,0,0,0,0,4,99,232,72,81,216,83,82,177,113,154,101,171,191,102,16,53,2,147,223,165,79,243,190,113,10,157,206,135,222,5,217,65,54,23,177,200,142,189,10,163,50,96,137,158,37,217,106,216,161,158,201,42,218,173,255,223,107,187,10,160,246,209,49,119,13,79,24,62,83,44,18,75,41,113,40,151,246,166,179,165,214,223,80,188,97,80,58,155,38,155,47,74,248,20,67,155,5,160,238,98,158,83,194,190,67,77,157,214,254,231,184,219,107,52,77,127,24,102,1,251,144,178,50,149,13,72,65,177,195,218,201,87,134,131,175,32,138,133,5,222,97,231,84,23,145,0,0,0,0,0,0,0,4,41,206,128,242,166,173,199,241,117,198,134,165,146,203,52,95,227,238,179,230,157,217,246,150,222,230,133,245,132,184,119,132,141,103,152,252,95,104,99,219,67,10,130,249,141,182,75,54,161,214,140,241,127,170,234,139,166,120,25,52,114,229,18,143,207,253,104,37,55,211,118,149,102,205,172,243,69,131,177,163,206,196,98,47,43,253,141,83,226,156,196,105,10,77,247,10,236,181,186,106,38,189,26,85,26,251,214,169,108,81,34,175,213,207,232,27,50,12,237,189,170,53,40,169,229,145,66,35,223,91,159,197,71,248,89,5,51,45,26,107,203,217,23,146],[1,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,145,0,0,0,0,0,0,0,4,152,114,8,226,152,129,189,143,159,235,189,61,126,77,186,177,15,177,198,231,5,34,111,125,133,166,28,66,30,241,227,59,80,219,209,42,163,202,187,2,195,122,112,97,36,57,11,1,211,21,128,2,225,173,117,181,10,180,163,2,95,194,192,197,47,20,11,73,107,64,162,186,132,11,124,214,88,140,12,251,69,62,23,141,83,2,96,21,114,228,19,194,60,10,241,245,51,4,112,163,62,149,80,145,205,86,193,203,69,217,220,173,33,215,247,80,176,64,133,51,142,249,107,142,120,179,55,137,175,200,161,84,102,99,113,62,168,235,217,165,32,55,228,213,145,0,0,0,0,0,0,0,4,221,149,209,31,50,228,196,193,40,117,20,66,130,133,167,86,232,131,255,67,132,106,254,5,143,9,175,168,200,26,164,176,67,148,98,98,222,11,25,3,228,254,142,237,212,73,95,96,110,238,141,127,144,83,49,59,74,232,96,228,191,253,97,216,58,228,9,219,171,28,211,114,147,98,128,186,194,69,37,205,51,171,30,102,54,225,233,116,73,90,187,77,26,248,83,39,96,230,195,183,192,95,211,68,44,117,64,43,181,212,233,145,28,25,84,130,206,91,146,213,29,122,36,213,187,244,203,93,16,77,236,46,253,213,226,70,101,220,4,246,60,200,163,47,145,0,0,0,0,0,0,0,4,118,236,102,255,65,189,12,26,115,11,178,130,105,223,84,158,135,128,9,1,180,170,35,104,224,216,71,114,102,103,251,234,127,217,183,115,2,17,190,231,245,104,142,247,27,216,29,178,181,1,208,166,116,118,186,16,218,36,114,187,196,84,204,246,0,229,191,181,50,130,12,141,47,132,164,18,165,13,106,235,181,171,193,122,62,126,175,113,253,14,26,199,239,142,167,76,99,212,149,132,198,50,10,11,123,211,114,232,137,78,117,130,155,38,27,106,122,219,221,34,141,219,253,91,249,73,134,81,31,134,243,143,240,164,23,114,81,161,77,241,94,52,47,67],[2,0,0,0,0,0,0,0,3,0,0,0,0,0,0,0,145,0,0,0,0,0,0,0,4,241,132,141,26,40,54,65,201,52,48,86,28,100,57,102,106,142,94,36,177,250,127,115,148,189,34,186,71,15,164,119,226,250,197,157,48,40,236,159,63,80,229,161,192,21,53,21,39,32,27,230,41,248,81,122,150,238,78,155,55,225,175,106,169,115,101,103,73,66,119,243,244,229,127,33,76,57,94,222,110,172,161,101,120,37,227,250,45,205,42,233,90,34,105,196,174,132,242,39,90,90,83,153,197,181,36,45,8,89,218,182,138,146,212,39,101,125,63,10,57,52,191,208,142,40,215,184,107,87,172,33,93,128,165,57,129,215,204,52,165,146,81,229,226,145,0,0,0,0,0,0,0,4,94,40,188,81,188,105,191,202,35,228,70,225,229,181,40,243,109,142,213,0,38,93,214,202,139,44,212,42,86,56,184,220,94,141,8,171,175,55,6,9,146,248,79,146,132,170,182,210,12,205,175,86,61,81,99,72,26,53,124,200,8,62,232,145,58,88,140,80,156,182,196,199,13,248,182,135,95,7,234,230,133,254,118,12,132,222,173,124,226,9,36,63,64,63,161,202,183,243,182,118,155,97,51,22,36,34,203,142,155,227,158,30,78,39,10,247,135,207,212,83,207,190,180,242,79,199,46,180,179,183,140,158,220,71,192,35,152,229,130,139,159,203,14,228,145,0,0,0,0,0,0,0,4,229,251,155,218,232,213,74,252,105,57,155,105,170,138,98,149,27,48,37,163,92,41,51,192,123,239,185,132,28,113,210,58,240,253,6,78,210,78,165,20,129,90,61,59,36,164,50,215,134,129,125,125,71,17,122,108,246,237,122,2,236,152,215,214,2,140,47,74,187,242,14,125,150,112,140,180,154,47,91,9,161,142,91,254,245,186,121,120,144,13,38,247,209,191,215,79,204,198,4,58,23,241,86,128,197,147,38,177,243,159,161,104,215,82,153,242,222,127,144,99,171,20,112,43,252,224,102,61,57,224,130,86,32,5,116,56,102,117,104,148,20,96,102,209]]] - - //fixing parts. - //there is a bug in web3-eth-abi handling byte arrays, - //but buffer work fine. - const parts = []; - partsRaw.forEach(x => { - parts.push( Buffer.from(x)); - }); - - return {parts, acks}; -}; - -exports.getTestPartNAcks = getTestPartNAcks; \ No newline at end of file diff --git a/test/testhelpers/data.ts b/test/testhelpers/data.ts new file mode 100644 index 00000000..09a0f2ba --- /dev/null +++ b/test/testhelpers/data.ts @@ -0,0 +1,68 @@ + +/// gets a set of 3 real Acks and Parts for testing purposes +export function getTestPartNAcks() { + const parts = [ + new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 162, 238, 181, 164, 119, 226, 238, 142, 43, 227, 179, 139, 95, 25, 108, 237, 11, 190, 84, 64, 234, 22, 245, 210, 187, 24, 142, 145, 31, 26, 197, 119, 92, 171, 182, 30, 182, 191, 151, 218, 208, 96, 103, 110, 14, 170, 189, 220, 3, 0, 0, 0, 0, 0, 0, 0, 153, 0, 0, 0, 0, 0, 0, 0, 4, 21, 73, 242, 168, 17, 236, 103, 137, 92, 198, 188, 151, 185, 9, 174, 175, 170, 174, 57, 210, 222, 4, 81, 210, 164, 8, 69, 148, 77, 228, 38, 240, 153, 232, 223, 247, 87, 154, 182, 186, 84, 25, 66, 211, 40, 191, 201, 51, 82, 23, 210, 22, 213, 222, 200, 8, 206, 218, 143, 128, 49, 28, 60, 223, 37, 52, 95, 47, 33, 245, 72, 158, 241, 216, 97, 244, 234, 136, 89, 239, 199, 11, 252, 232, 95, 18, 174, 135, 13, 237, 240, 213, 206, 206, 85, 52, 124, 247, 123, 199, 87, 112, 132, 42, 136, 94, 223, 15, 75, 137, 122, 27, 20, 92, 167, 40, 222, 99, 160, 147, 245, 251, 242, 221, 134, 74, 193, 248, 249, 246, 54, 58, 185, 109, 78, 212, 36, 101, 241, 65, 82, 183, 246, 62, 156, 217, 247, 255, 92, 205, 160, 220, 153, 0, 0, 0, 0, 0, 0, 0, 4, 249, 64, 230, 166, 97, 82, 165, 124, 79, 27, 92, 167, 19, 229, 52, 40, 203, 120, 236, 87, 142, 125, 122, 227, 174, 162, 64, 228, 170, 35, 46, 169, 74, 119, 13, 26, 126, 67, 141, 151, 3, 86, 253, 135, 156, 100, 60, 42, 68, 245, 201, 4, 66, 216, 34, 29, 88, 229, 82, 88, 171, 213, 215, 25, 96, 245, 193, 33, 229, 228, 139, 233, 239, 14, 164, 187, 39, 151, 82, 164, 72, 181, 215, 161, 64, 167, 181, 169, 96, 89, 32, 93, 180, 176, 201, 116, 8, 190, 99, 179, 132, 43, 11, 107, 59, 223, 207, 173, 43, 197, 181, 169, 127, 184, 189, 122, 220, 159, 133, 133, 17, 192, 5, 149, 159, 97, 197, 143, 104, 103, 252, 93, 120, 213, 56, 242, 193, 4, 27, 187, 151, 60, 172, 129, 55, 69, 23, 243, 110, 119, 16, 151, 153, 0, 0, 0, 0, 0, 0, 0, 4, 144, 226, 236, 244, 137, 245, 236, 219, 56, 172, 227, 38, 22, 176, 15, 182, 184, 184, 45, 175, 169, 208, 170, 150, 182, 129, 76, 191, 47, 255, 123, 213, 136, 70, 214, 129, 234, 24, 96, 55, 181, 159, 73, 123, 96, 55, 238, 104, 140, 106, 39, 86, 194, 82, 217, 229, 245, 194, 114, 78, 33, 192, 217, 137, 147, 141, 230, 183, 211, 227, 236, 196, 102, 226, 30, 247, 198, 211, 117, 159, 70, 135, 219, 249, 232, 158, 39, 102, 214, 42, 163, 97, 67, 172, 10, 15, 53, 212, 46, 69, 144, 227, 87, 81, 113, 248, 238, 229, 74, 78, 4, 158, 139, 125, 42, 181, 220, 208, 108, 188, 71, 4, 193, 66, 135, 63, 246, 180, 166, 251, 117, 160, 133, 3, 14, 154, 17, 254, 34, 215, 98, 212, 107, 3, 219, 145, 162, 81, 154, 129, 98, 30]), + + new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 178, 73, 138, 14, 3, 78, 162, 102, 191, 223, 232, 10, 81, 96, 118, 193, 17, 245, 152, 100, 177, 160, 138, 30, 241, 144, 254, 80, 221, 191, 133, 251, 43, 252, 251, 55, 111, 234, 36, 30, 11, 227, 3, 209, 11, 29, 97, 12, 3, 0, 0, 0, 0, 0, 0, 0, 153, 0, 0, 0, 0, 0, 0, 0, 4, 190, 190, 139, 180, 190, 148, 3, 35, 23, 114, 210, 184, 188, 37, 29, 84, 197, 247, 58, 199, 180, 139, 151, 50, 108, 72, 160, 72, 104, 120, 177, 113, 88, 114, 102, 35, 83, 214, 49, 107, 226, 189, 62, 146, 134, 227, 121, 204, 221, 170, 229, 103, 242, 35, 66, 174, 12, 222, 96, 244, 80, 109, 177, 162, 22, 173, 241, 253, 188, 107, 213, 119, 32, 142, 210, 120, 23, 6, 255, 53, 195, 183, 16, 224, 211, 157, 34, 76, 41, 196, 121, 60, 10, 124, 231, 193, 177, 178, 201, 176, 242, 10, 34, 30, 74, 16, 76, 255, 101, 225, 104, 179, 5, 15, 231, 147, 247, 214, 103, 172, 127, 161, 226, 217, 18, 140, 93, 42, 235, 252, 105, 19, 214, 191, 80, 37, 230, 77, 82, 122, 248, 38, 124, 30, 68, 164, 81, 129, 51, 162, 87, 154, 153, 0, 0, 0, 0, 0, 0, 0, 4, 45, 167, 32, 19, 176, 115, 181, 244, 240, 144, 71, 62, 123, 234, 47, 139, 101, 220, 132, 48, 31, 222, 255, 194, 15, 65, 214, 103, 75, 68, 161, 78, 40, 143, 28, 242, 143, 191, 87, 76, 169, 19, 24, 217, 145, 231, 90, 139, 69, 34, 90, 12, 175, 146, 173, 49, 116, 34, 148, 58, 62, 142, 168, 154, 1, 79, 76, 99, 59, 135, 153, 22, 213, 9, 80, 206, 179, 110, 110, 123, 8, 42, 101, 53, 36, 241, 202, 64, 203, 169, 148, 175, 0, 2, 217, 163, 109, 89, 248, 214, 243, 66, 44, 69, 11, 100, 90, 132, 74, 218, 16, 240, 20, 157, 154, 134, 8, 63, 131, 18, 59, 157, 105, 93, 133, 47, 166, 97, 196, 160, 48, 54, 218, 118, 46, 146, 224, 36, 123, 226, 204, 171, 215, 17, 73, 92, 147, 55, 1, 41, 54, 32, 153, 0, 0, 0, 0, 0, 0, 0, 4, 116, 101, 44, 65, 60, 102, 230, 141, 166, 221, 113, 19, 43, 220, 253, 67, 27, 109, 103, 171, 33, 42, 189, 108, 84, 229, 139, 200, 63, 218, 76, 180, 101, 159, 208, 102, 117, 168, 34, 185, 211, 61, 12, 143, 250, 49, 210, 194, 39, 135, 64, 150, 174, 159, 196, 254, 136, 138, 229, 53, 214, 85, 228, 119, 125, 222, 201, 207, 137, 10, 57, 88, 233, 155, 50, 94, 50, 238, 174, 188, 71, 119, 14, 67, 50, 222, 24, 92, 82, 87, 126, 120, 5, 30, 112, 40, 106, 216, 120, 181, 16, 197, 44, 52, 86, 129, 181, 241, 249, 91, 31, 253, 24, 42, 106, 14, 5, 175, 226, 29, 226, 200, 218, 97, 99, 81, 125, 219, 133, 214, 228, 198, 138, 241, 41, 193, 138, 218, 51, 168, 61, 46, 35, 86, 144, 153, 99, 180, 150, 11, 4, 112]), + + new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 170, 254, 25, 182, 81, 8, 235, 232, 45, 133, 72, 208, 54, 10, 151, 224, 33, 250, 175, 154, 155, 189, 139, 187, 155, 22, 199, 114, 11, 221, 65, 195, 66, 45, 57, 81, 129, 41, 252, 72, 173, 189, 241, 122, 193, 176, 97, 209, 3, 0, 0, 0, 0, 0, 0, 0, 153, 0, 0, 0, 0, 0, 0, 0, 4, 106, 140, 219, 6, 75, 230, 222, 99, 131, 82, 163, 144, 68, 231, 71, 69, 7, 214, 27, 149, 103, 189, 152, 156, 32, 231, 59, 113, 140, 92, 46, 178, 144, 219, 172, 255, 183, 225, 111, 161, 65, 244, 242, 135, 6, 223, 69, 149, 189, 167, 16, 27, 107, 145, 136, 2, 12, 12, 243, 105, 75, 232, 172, 184, 119, 164, 14, 223, 101, 219, 182, 114, 55, 189, 158, 72, 194, 84, 185, 46, 74, 77, 128, 16, 2, 195, 132, 20, 78, 189, 141, 196, 64, 145, 81, 196, 15, 182, 249, 21, 181, 205, 247, 242, 35, 208, 150, 216, 84, 254, 243, 5, 232, 211, 110, 196, 137, 93, 18, 176, 42, 201, 176, 20, 114, 94, 139, 48, 60, 113, 173, 246, 59, 152, 54, 204, 22, 124, 81, 29, 86, 57, 176, 80, 68, 85, 253, 54, 169, 193, 165, 91, 153, 0, 0, 0, 0, 0, 0, 0, 4, 104, 82, 218, 8, 57, 188, 206, 90, 232, 210, 234, 64, 176, 216, 102, 167, 61, 82, 75, 197, 47, 186, 148, 82, 186, 148, 182, 186, 30, 33, 232, 250, 130, 0, 204, 228, 25, 63, 7, 21, 157, 244, 225, 15, 53, 251, 119, 149, 11, 45, 150, 165, 213, 162, 59, 248, 44, 174, 177, 88, 128, 38, 11, 228, 110, 198, 243, 237, 199, 79, 167, 252, 11, 250, 131, 140, 109, 122, 89, 181, 115, 128, 198, 25, 153, 196, 196, 248, 72, 212, 208, 54, 32, 102, 7, 208, 238, 103, 32, 125, 62, 111, 222, 83, 6, 5, 148, 59, 10, 74, 29, 64, 4, 251, 189, 34, 108, 226, 206, 8, 77, 109, 181, 121, 208, 54, 82, 193, 89, 132, 22, 238, 147, 160, 28, 88, 39, 32, 50, 147, 222, 138, 153, 191, 243, 96, 34, 218, 212, 51, 159, 23, 153, 0, 0, 0, 0, 0, 0, 0, 4, 20, 112, 232, 10, 136, 250, 15, 177, 137, 89, 249, 144, 240, 199, 202, 172, 135, 49, 130, 254, 98, 208, 175, 191, 151, 185, 180, 168, 51, 4, 128, 163, 66, 75, 212, 151, 21, 75, 144, 199, 45, 191, 89, 166, 90, 109, 221, 74, 10, 97, 171, 7, 180, 219, 192, 127, 71, 90, 221, 87, 223, 233, 110, 232, 90, 245, 107, 197, 138, 136, 222, 206, 16, 139, 147, 205, 107, 117, 53, 190, 36, 204, 74, 112, 199, 210, 123, 131, 71, 199, 95, 6, 181, 165, 60, 186, 116, 116, 46, 203, 91, 155, 5, 187, 22, 95, 215, 92, 2, 77, 79, 204, 34, 75, 118, 213, 76, 78, 37, 180, 26, 63, 220, 229, 190, 164, 60, 155, 245, 136, 80, 165, 197, 44, 64, 108, 99, 152, 129, 80, 83, 235, 94, 234, 233, 252, 49, 252, 182, 182, 178, 2]) + ] + + const acks = [ + [ + new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 145, 0, 0, 0, 0, 0, 0, 0, 4, 49, 56, 206, 120, 208, 7, 197, 245, 119, 88, 166, 31, 191, 100, 103, 74, 94, 140, 184, 31, 111, 69, 189, 192, 100, 241, 203, 205, 189, 66, 172, 233, 179, 112, 132, 219, 243, 78, 177, 183, 108, 34, 50, 65, 27, 107, 63, 176, 91, 62, 117, 81, 36, 102, 5, 36, 26, 45, 216, 19, 213, 65, 150, 109, 205, 225, 150, 94, 35, 42, 219, 196, 29, 193, 159, 197, 151, 197, 236, 146, 233, 109, 92, 114, 132, 158, 253, 177, 201, 2, 138, 19, 105, 71, 220, 139, 123, 226, 74, 75, 79, 151, 109, 146, 250, 223, 71, 240, 101, 163, 100, 232, 34, 18, 27, 190, 42, 160, 240, 234, 71, 10, 190, 225, 42, 86, 126, 84, 180, 104, 163, 30, 81, 152, 217, 249, 46, 39, 75, 180, 37, 174, 25, 146, 145, 0, 0, 0, 0, 0, 0, 0, 4, 209, 118, 244, 76, 61, 65, 111, 73, 69, 38, 163, 50, 120, 117, 116, 225, 140, 206, 177, 188, 80, 71, 117, 111, 112, 177, 119, 120, 97, 192, 129, 63, 57, 10, 114, 60, 228, 137, 64, 189, 13, 184, 18, 147, 153, 76, 28, 166, 129, 11, 39, 164, 61, 116, 170, 155, 126, 161, 25, 67, 121, 213, 137, 1, 248, 133, 179, 141, 36, 108, 52, 127, 4, 2, 206, 60, 231, 133, 30, 94, 38, 184, 209, 145, 138, 230, 43, 82, 129, 228, 215, 42, 47, 192, 240, 126, 84, 97, 60, 129, 195, 203, 232, 81, 192, 119, 161, 187, 1, 255, 141, 201, 188, 35, 19, 205, 98, 234, 206, 113, 235, 15, 84, 88, 223, 168, 79, 142, 139, 113, 138, 109, 198, 168, 166, 134, 84, 148, 62, 238, 107, 210, 58, 184, 145, 0, 0, 0, 0, 0, 0, 0, 4, 169, 49, 88, 116, 160, 40, 158, 158, 37, 164, 106, 95, 107, 236, 212, 41, 98, 167, 202, 51, 165, 245, 162, 176, 162, 13, 27, 94, 205, 72, 164, 85, 128, 234, 178, 50, 240, 91, 53, 79, 54, 43, 208, 184, 144, 253, 54, 115, 5, 143, 67, 187, 222, 154, 181, 174, 39, 92, 120, 202, 117, 148, 241, 147, 163, 105, 150, 75, 56, 172, 215, 31, 143, 93, 13, 100, 27, 25, 52, 111, 206, 176, 55, 61, 33, 42, 77, 189, 94, 69, 182, 212, 97, 111, 43, 129, 38, 216, 218, 117, 64, 250, 128, 254, 104, 165, 160, 72, 205, 2, 142, 157, 116, 95, 218, 49, 143, 85, 160, 190, 195, 205, 97, 21, 77, 85, 58, 4, 94, 3, 253, 167, 237, 55, 75, 101, 200, 198, 97, 122, 46, 153, 85, 104]), + + new Uint8Array([1, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 145, 0, 0, 0, 0, 0, 0, 0, 4, 23, 51, 20, 34, 33, 38, 160, 91, 243, 39, 211, 84, 188, 187, 32, 88, 121, 194, 65, 132, 6, 33, 255, 93, 159, 16, 49, 126, 232, 121, 180, 244, 229, 106, 87, 125, 60, 156, 166, 70, 125, 207, 203, 103, 115, 212, 153, 133, 130, 108, 248, 22, 122, 230, 95, 106, 74, 90, 123, 120, 171, 33, 102, 115, 12, 56, 14, 171, 238, 173, 226, 146, 136, 62, 60, 201, 28, 178, 216, 162, 107, 163, 48, 76, 227, 28, 104, 85, 33, 252, 28, 249, 108, 249, 27, 72, 213, 44, 161, 33, 253, 20, 154, 127, 29, 27, 84, 76, 10, 232, 211, 60, 248, 37, 50, 100, 210, 125, 71, 109, 155, 165, 246, 47, 85, 219, 71, 51, 28, 163, 219, 240, 253, 113, 156, 131, 70, 148, 248, 187, 146, 135, 167, 165, 145, 0, 0, 0, 0, 0, 0, 0, 4, 192, 60, 165, 5, 196, 71, 96, 49, 93, 153, 135, 242, 152, 67, 254, 94, 244, 186, 64, 132, 128, 112, 67, 102, 177, 240, 181, 105, 170, 39, 57, 176, 247, 119, 207, 134, 253, 249, 122, 30, 151, 118, 91, 107, 16, 88, 156, 112, 214, 181, 199, 115, 246, 190, 173, 85, 153, 49, 13, 107, 64, 173, 3, 76, 236, 221, 54, 120, 163, 47, 192, 242, 19, 35, 90, 153, 37, 202, 166, 22, 33, 252, 250, 218, 68, 80, 197, 134, 147, 230, 72, 107, 239, 119, 69, 53, 177, 53, 92, 248, 15, 154, 177, 116, 202, 54, 140, 118, 62, 188, 103, 36, 5, 160, 74, 145, 223, 101, 251, 190, 96, 122, 191, 34, 227, 47, 66, 152, 165, 238, 80, 210, 237, 104, 71, 158, 119, 13, 105, 141, 144, 0, 178, 141, 145, 0, 0, 0, 0, 0, 0, 0, 4, 225, 41, 255, 228, 45, 231, 42, 88, 201, 191, 196, 69, 54, 108, 214, 0, 203, 113, 53, 203, 41, 155, 102, 29, 59, 80, 28, 21, 199, 78, 156, 141, 205, 214, 137, 150, 105, 116, 44, 164, 70, 53, 174, 153, 241, 100, 139, 87, 176, 6, 39, 38, 21, 0, 186, 0, 126, 67, 56, 61, 179, 90, 176, 124, 223, 224, 160, 121, 228, 119, 98, 103, 241, 178, 118, 96, 137, 223, 193, 235, 135, 196, 83, 1, 81, 221, 201, 242, 238, 155, 66, 12, 221, 16, 213, 18, 198, 232, 69, 253, 82, 230, 12, 212, 83, 137, 100, 18, 169, 241, 101, 21, 135, 126, 201, 168, 200, 16, 209, 248, 169, 108, 55, 250, 131, 104, 64, 209, 203, 142, 56, 15, 250, 225, 253, 236, 25, 208, 180, 120, 9, 110, 234, 184]), + + new Uint8Array([2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 145, 0, 0, 0, 0, 0, 0, 0, 4, 100, 13, 69, 238, 212, 63, 79, 226, 98, 251, 16, 122, 85, 165, 126, 121, 80, 111, 42, 109, 158, 70, 24, 38, 38, 111, 158, 79, 150, 173, 105, 34, 161, 225, 200, 179, 88, 218, 70, 23, 237, 26, 224, 110, 79, 152, 70, 59, 118, 103, 5, 164, 71, 141, 68, 50, 222, 235, 190, 144, 52, 217, 236, 70, 228, 228, 120, 58, 4, 140, 229, 232, 184, 37, 120, 151, 84, 2, 188, 45, 166, 166, 161, 187, 131, 248, 99, 81, 88, 35, 244, 114, 124, 35, 188, 35, 226, 110, 116, 96, 22, 200, 7, 218, 13, 242, 120, 227, 18, 75, 233, 181, 235, 133, 22, 176, 183, 146, 218, 62, 35, 32, 39, 72, 51, 200, 142, 43, 139, 0, 30, 41, 253, 158, 80, 250, 68, 109, 221, 189, 177, 28, 230, 134, 145, 0, 0, 0, 0, 0, 0, 0, 4, 230, 16, 43, 212, 214, 93, 133, 200, 66, 103, 14, 32, 84, 113, 112, 209, 67, 34, 129, 26, 136, 225, 228, 116, 249, 229, 195, 82, 36, 247, 52, 191, 165, 171, 143, 36, 78, 7, 95, 249, 100, 75, 104, 11, 108, 10, 125, 197, 38, 196, 120, 79, 205, 57, 54, 20, 100, 210, 169, 117, 30, 216, 101, 211, 1, 65, 202, 100, 146, 162, 231, 241, 5, 28, 237, 106, 82, 140, 136, 157, 60, 156, 166, 30, 139, 215, 218, 54, 192, 91, 26, 101, 227, 29, 219, 61, 209, 239, 219, 79, 194, 67, 158, 79, 171, 209, 46, 25, 90, 148, 156, 228, 253, 187, 118, 109, 190, 207, 97, 190, 225, 163, 65, 76, 250, 34, 125, 135, 80, 183, 141, 21, 182, 39, 53, 50, 53, 17, 231, 237, 74, 203, 174, 220, 145, 0, 0, 0, 0, 0, 0, 0, 4, 49, 229, 95, 158, 235, 69, 183, 126, 193, 92, 120, 197, 77, 79, 151, 132, 150, 130, 123, 226, 27, 226, 253, 204, 82, 95, 181, 114, 206, 239, 142, 232, 86, 117, 230, 232, 39, 123, 255, 21, 227, 52, 86, 154, 154, 217, 229, 4, 14, 111, 147, 103, 147, 193, 202, 157, 166, 220, 177, 1, 38, 93, 150, 126, 205, 238, 236, 213, 7, 187, 40, 13, 219, 11, 219, 121, 36, 90, 202, 159, 30, 159, 62, 6, 87, 109, 210, 169, 62, 53, 162, 10, 41, 238, 83, 97, 148, 23, 65, 146, 115, 98, 52, 29, 241, 192, 189, 6, 150, 174, 21, 123, 176, 123, 226, 75, 128, 104, 115, 68, 6, 217, 1, 159, 67, 121, 20, 198, 240, 72, 151, 231, 217, 154, 29, 120, 64, 123, 232, 14, 202, 99, 231, 251]) + ], + [ + new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 145, 0, 0, 0, 0, 0, 0, 0, 4, 184, 101, 147, 79, 192, 143, 119, 143, 72, 141, 194, 218, 23, 81, 123, 6, 94, 214, 88, 150, 139, 211, 68, 135, 97, 69, 29, 94, 41, 91, 26, 204, 61, 24, 91, 217, 137, 202, 97, 9, 18, 148, 103, 186, 213, 187, 223, 230, 25, 110, 175, 110, 90, 114, 194, 73, 165, 219, 155, 212, 227, 186, 187, 166, 92, 183, 23, 67, 2, 63, 180, 17, 40, 8, 93, 62, 100, 159, 223, 39, 225, 254, 172, 23, 104, 91, 22, 115, 192, 67, 106, 71, 6, 46, 27, 2, 222, 129, 174, 89, 183, 59, 187, 198, 112, 18, 17, 54, 82, 144, 204, 17, 210, 245, 97, 214, 176, 33, 220, 17, 74, 18, 178, 66, 43, 250, 173, 88, 181, 106, 91, 105, 221, 54, 26, 223, 99, 64, 50, 20, 108, 139, 245, 104, 145, 0, 0, 0, 0, 0, 0, 0, 4, 103, 215, 2, 70, 67, 85, 254, 117, 92, 62, 181, 133, 48, 134, 52, 71, 18, 106, 60, 87, 218, 85, 75, 223, 233, 176, 92, 120, 124, 200, 214, 185, 85, 234, 88, 94, 29, 171, 232, 194, 5, 189, 88, 126, 173, 116, 216, 3, 98, 168, 191, 124, 33, 154, 219, 4, 137, 156, 101, 110, 139, 4, 173, 100, 212, 241, 251, 197, 120, 8, 220, 188, 12, 228, 174, 113, 167, 127, 4, 97, 115, 155, 57, 38, 93, 245, 5, 3, 114, 61, 38, 194, 193, 33, 48, 196, 239, 88, 116, 63, 24, 255, 62, 246, 73, 77, 234, 138, 136, 93, 133, 105, 9, 29, 172, 52, 46, 101, 13, 129, 147, 75, 39, 25, 160, 179, 25, 88, 185, 85, 81, 240, 130, 180, 145, 12, 165, 206, 127, 142, 31, 233, 182, 117, 145, 0, 0, 0, 0, 0, 0, 0, 4, 125, 157, 244, 235, 22, 158, 28, 67, 94, 19, 16, 164, 238, 104, 224, 161, 47, 190, 216, 231, 249, 164, 129, 25, 238, 142, 145, 219, 48, 178, 181, 190, 209, 90, 107, 218, 157, 54, 101, 107, 81, 249, 140, 245, 169, 31, 47, 89, 39, 165, 99, 119, 87, 179, 112, 49, 81, 69, 2, 25, 227, 202, 37, 246, 115, 211, 85, 250, 25, 127, 52, 13, 228, 153, 108, 11, 47, 65, 133, 2, 45, 120, 125, 202, 166, 126, 113, 98, 185, 21, 91, 152, 3, 189, 240, 11, 253, 38, 225, 249, 239, 93, 239, 187, 102, 106, 145, 78, 99, 42, 15, 190, 254, 157, 170, 114, 170, 142, 108, 108, 67, 172, 246, 3, 209, 238, 143, 155, 254, 156, 246, 121, 30, 86, 133, 136, 214, 44, 31, 156, 211, 224, 222, 237]), + + new Uint8Array([1, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 145, 0, 0, 0, 0, 0, 0, 0, 4, 245, 37, 118, 90, 114, 11, 69, 85, 13, 113, 7, 10, 46, 220, 128, 237, 70, 201, 68, 71, 248, 182, 116, 96, 130, 201, 35, 161, 178, 141, 45, 55, 39, 87, 44, 21, 118, 135, 5, 60, 194, 1, 216, 148, 24, 127, 129, 234, 172, 95, 202, 131, 157, 77, 245, 198, 63, 183, 33, 45, 123, 242, 220, 247, 20, 196, 159, 155, 204, 250, 69, 161, 10, 93, 189, 70, 10, 97, 122, 141, 22, 61, 77, 21, 49, 86, 64, 137, 21, 43, 221, 154, 68, 7, 38, 203, 241, 208, 207, 125, 144, 211, 255, 135, 247, 27, 211, 203, 6, 189, 88, 198, 161, 156, 15, 58, 244, 254, 58, 171, 120, 239, 1, 83, 22, 236, 178, 245, 156, 59, 10, 11, 21, 33, 121, 227, 47, 25, 62, 160, 193, 73, 252, 123, 145, 0, 0, 0, 0, 0, 0, 0, 4, 50, 105, 164, 252, 224, 42, 30, 14, 83, 98, 248, 84, 249, 220, 134, 92, 208, 38, 53, 131, 214, 224, 87, 147, 147, 185, 212, 9, 134, 64, 43, 50, 28, 108, 234, 96, 14, 107, 243, 170, 216, 151, 162, 163, 208, 7, 198, 253, 12, 236, 16, 203, 174, 4, 48, 135, 216, 146, 175, 253, 10, 35, 203, 153, 123, 20, 105, 163, 223, 250, 166, 82, 141, 225, 134, 94, 27, 124, 157, 123, 110, 174, 31, 240, 203, 25, 146, 16, 101, 147, 74, 70, 107, 68, 78, 61, 178, 42, 126, 11, 177, 157, 18, 109, 54, 194, 124, 160, 236, 96, 187, 113, 162, 0, 68, 209, 93, 80, 239, 239, 73, 177, 74, 163, 97, 248, 138, 157, 21, 225, 77, 71, 152, 208, 192, 109, 19, 49, 222, 147, 105, 230, 187, 26, 145, 0, 0, 0, 0, 0, 0, 0, 4, 196, 48, 14, 64, 241, 20, 121, 45, 118, 108, 242, 220, 188, 251, 9, 107, 149, 237, 200, 167, 223, 80, 201, 104, 246, 181, 10, 255, 48, 238, 65, 55, 250, 9, 224, 197, 155, 166, 88, 92, 243, 71, 134, 100, 103, 55, 215, 124, 201, 181, 48, 208, 69, 30, 86, 179, 107, 38, 74, 80, 138, 169, 30, 221, 251, 16, 192, 12, 161, 130, 59, 65, 116, 91, 186, 37, 161, 54, 141, 67, 221, 161, 216, 44, 175, 218, 171, 197, 177, 244, 193, 164, 192, 140, 196, 90, 171, 162, 210, 100, 194, 164, 195, 189, 249, 124, 97, 79, 250, 133, 185, 89, 174, 62, 150, 155, 35, 87, 33, 82, 61, 38, 232, 43, 228, 126, 92, 91, 225, 253, 240, 28, 91, 77, 191, 108, 152, 75, 154, 244, 98, 221, 191, 41]), + + new Uint8Array([2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 145, 0, 0, 0, 0, 0, 0, 0, 4, 208, 125, 51, 24, 222, 224, 29, 26, 2, 119, 35, 43, 81, 99, 219, 140, 237, 96, 92, 48, 25, 35, 74, 4, 122, 119, 52, 55, 237, 99, 4, 144, 36, 224, 73, 174, 186, 0, 12, 39, 68, 103, 42, 134, 94, 0, 103, 107, 106, 211, 95, 98, 195, 248, 225, 183, 114, 52, 180, 10, 14, 36, 107, 238, 92, 93, 0, 121, 27, 201, 235, 125, 8, 100, 243, 73, 198, 214, 4, 217, 47, 60, 70, 194, 237, 149, 25, 135, 181, 31, 69, 97, 89, 42, 189, 55, 78, 56, 5, 104, 213, 119, 91, 115, 37, 201, 144, 98, 167, 187, 33, 253, 113, 207, 76, 20, 178, 24, 214, 144, 89, 186, 166, 135, 14, 51, 107, 97, 144, 163, 139, 211, 32, 17, 212, 27, 207, 155, 228, 3, 232, 99, 29, 60, 145, 0, 0, 0, 0, 0, 0, 0, 4, 234, 91, 111, 181, 233, 101, 114, 213, 130, 88, 131, 151, 254, 87, 194, 245, 250, 230, 67, 44, 21, 75, 113, 99, 35, 227, 123, 228, 175, 10, 249, 92, 34, 132, 237, 153, 77, 82, 121, 49, 55, 152, 228, 11, 46, 181, 146, 34, 5, 3, 138, 34, 124, 85, 0, 224, 9, 106, 36, 210, 163, 56, 94, 235, 72, 252, 235, 77, 30, 179, 248, 61, 123, 143, 39, 120, 163, 112, 18, 35, 141, 62, 143, 237, 22, 9, 66, 21, 3, 62, 100, 5, 46, 255, 142, 248, 160, 235, 218, 215, 209, 249, 65, 40, 221, 198, 201, 113, 8, 223, 82, 78, 41, 189, 237, 58, 52, 36, 237, 29, 112, 210, 54, 79, 232, 40, 100, 68, 151, 113, 155, 194, 127, 109, 170, 203, 56, 80, 214, 156, 160, 169, 170, 185, 145, 0, 0, 0, 0, 0, 0, 0, 4, 144, 88, 183, 137, 94, 77, 106, 60, 58, 106, 25, 131, 143, 146, 102, 70, 96, 101, 51, 196, 134, 213, 70, 185, 103, 71, 239, 116, 121, 157, 246, 50, 143, 242, 178, 108, 249, 215, 239, 222, 147, 243, 250, 216, 14, 192, 52, 246, 247, 244, 232, 119, 186, 159, 2, 36, 114, 163, 241, 82, 32, 197, 173, 98, 98, 42, 126, 14, 241, 129, 221, 106, 67, 41, 115, 178, 175, 34, 150, 92, 28, 40, 189, 70, 225, 15, 81, 134, 167, 214, 149, 173, 118, 25, 166, 226, 7, 163, 125, 124, 193, 175, 36, 163, 136, 128, 131, 86, 62, 64, 56, 176, 251, 4, 91, 42, 46, 167, 97, 141, 136, 49, 137, 96, 99, 124, 173, 113, 76, 33, 36, 202, 116, 5, 0, 254, 78, 198, 243, 113, 77, 124, 227, 174]) + ], + [ + new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 145, 0, 0, 0, 0, 0, 0, 0, 4, 23, 250, 79, 243, 54, 117, 62, 80, 179, 97, 221, 176, 136, 63, 222, 209, 236, 75, 87, 159, 246, 168, 252, 213, 57, 22, 96, 252, 27, 160, 103, 102, 80, 93, 78, 34, 182, 54, 109, 189, 204, 137, 210, 232, 139, 103, 3, 147, 219, 189, 217, 31, 68, 104, 247, 120, 169, 69, 79, 85, 180, 196, 118, 81, 189, 161, 132, 143, 123, 51, 43, 132, 220, 79, 82, 247, 160, 134, 243, 153, 40, 54, 207, 158, 51, 52, 168, 105, 127, 210, 129, 206, 119, 10, 251, 112, 225, 3, 181, 153, 204, 171, 86, 17, 102, 145, 81, 48, 60, 27, 219, 84, 8, 200, 15, 236, 158, 110, 58, 86, 225, 242, 33, 43, 29, 211, 190, 141, 197, 77, 250, 211, 84, 108, 189, 249, 186, 15, 248, 239, 126, 130, 47, 1, 145, 0, 0, 0, 0, 0, 0, 0, 4, 99, 232, 72, 81, 216, 83, 82, 177, 113, 154, 101, 171, 191, 102, 16, 53, 2, 147, 223, 165, 79, 243, 190, 113, 10, 157, 206, 135, 222, 5, 217, 65, 54, 23, 177, 200, 142, 189, 10, 163, 50, 96, 137, 158, 37, 217, 106, 216, 161, 158, 201, 42, 218, 173, 255, 223, 107, 187, 10, 160, 246, 209, 49, 119, 13, 79, 24, 62, 83, 44, 18, 75, 41, 113, 40, 151, 246, 166, 179, 165, 214, 223, 80, 188, 97, 80, 58, 155, 38, 155, 47, 74, 248, 20, 67, 155, 5, 160, 238, 98, 158, 83, 194, 190, 67, 77, 157, 214, 254, 231, 184, 219, 107, 52, 77, 127, 24, 102, 1, 251, 144, 178, 50, 149, 13, 72, 65, 177, 195, 218, 201, 87, 134, 131, 175, 32, 138, 133, 5, 222, 97, 231, 84, 23, 145, 0, 0, 0, 0, 0, 0, 0, 4, 41, 206, 128, 242, 166, 173, 199, 241, 117, 198, 134, 165, 146, 203, 52, 95, 227, 238, 179, 230, 157, 217, 246, 150, 222, 230, 133, 245, 132, 184, 119, 132, 141, 103, 152, 252, 95, 104, 99, 219, 67, 10, 130, 249, 141, 182, 75, 54, 161, 214, 140, 241, 127, 170, 234, 139, 166, 120, 25, 52, 114, 229, 18, 143, 207, 253, 104, 37, 55, 211, 118, 149, 102, 205, 172, 243, 69, 131, 177, 163, 206, 196, 98, 47, 43, 253, 141, 83, 226, 156, 196, 105, 10, 77, 247, 10, 236, 181, 186, 106, 38, 189, 26, 85, 26, 251, 214, 169, 108, 81, 34, 175, 213, 207, 232, 27, 50, 12, 237, 189, 170, 53, 40, 169, 229, 145, 66, 35, 223, 91, 159, 197, 71, 248, 89, 5, 51, 45, 26, 107, 203, 217, 23, 146]), + + new Uint8Array([1, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 145, 0, 0, 0, 0, 0, 0, 0, 4, 152, 114, 8, 226, 152, 129, 189, 143, 159, 235, 189, 61, 126, 77, 186, 177, 15, 177, 198, 231, 5, 34, 111, 125, 133, 166, 28, 66, 30, 241, 227, 59, 80, 219, 209, 42, 163, 202, 187, 2, 195, 122, 112, 97, 36, 57, 11, 1, 211, 21, 128, 2, 225, 173, 117, 181, 10, 180, 163, 2, 95, 194, 192, 197, 47, 20, 11, 73, 107, 64, 162, 186, 132, 11, 124, 214, 88, 140, 12, 251, 69, 62, 23, 141, 83, 2, 96, 21, 114, 228, 19, 194, 60, 10, 241, 245, 51, 4, 112, 163, 62, 149, 80, 145, 205, 86, 193, 203, 69, 217, 220, 173, 33, 215, 247, 80, 176, 64, 133, 51, 142, 249, 107, 142, 120, 179, 55, 137, 175, 200, 161, 84, 102, 99, 113, 62, 168, 235, 217, 165, 32, 55, 228, 213, 145, 0, 0, 0, 0, 0, 0, 0, 4, 221, 149, 209, 31, 50, 228, 196, 193, 40, 117, 20, 66, 130, 133, 167, 86, 232, 131, 255, 67, 132, 106, 254, 5, 143, 9, 175, 168, 200, 26, 164, 176, 67, 148, 98, 98, 222, 11, 25, 3, 228, 254, 142, 237, 212, 73, 95, 96, 110, 238, 141, 127, 144, 83, 49, 59, 74, 232, 96, 228, 191, 253, 97, 216, 58, 228, 9, 219, 171, 28, 211, 114, 147, 98, 128, 186, 194, 69, 37, 205, 51, 171, 30, 102, 54, 225, 233, 116, 73, 90, 187, 77, 26, 248, 83, 39, 96, 230, 195, 183, 192, 95, 211, 68, 44, 117, 64, 43, 181, 212, 233, 145, 28, 25, 84, 130, 206, 91, 146, 213, 29, 122, 36, 213, 187, 244, 203, 93, 16, 77, 236, 46, 253, 213, 226, 70, 101, 220, 4, 246, 60, 200, 163, 47, 145, 0, 0, 0, 0, 0, 0, 0, 4, 118, 236, 102, 255, 65, 189, 12, 26, 115, 11, 178, 130, 105, 223, 84, 158, 135, 128, 9, 1, 180, 170, 35, 104, 224, 216, 71, 114, 102, 103, 251, 234, 127, 217, 183, 115, 2, 17, 190, 231, 245, 104, 142, 247, 27, 216, 29, 178, 181, 1, 208, 166, 116, 118, 186, 16, 218, 36, 114, 187, 196, 84, 204, 246, 0, 229, 191, 181, 50, 130, 12, 141, 47, 132, 164, 18, 165, 13, 106, 235, 181, 171, 193, 122, 62, 126, 175, 113, 253, 14, 26, 199, 239, 142, 167, 76, 99, 212, 149, 132, 198, 50, 10, 11, 123, 211, 114, 232, 137, 78, 117, 130, 155, 38, 27, 106, 122, 219, 221, 34, 141, 219, 253, 91, 249, 73, 134, 81, 31, 134, 243, 143, 240, 164, 23, 114, 81, 161, 77, 241, 94, 52, 47, 67]), + + new Uint8Array([2, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 145, 0, 0, 0, 0, 0, 0, 0, 4, 241, 132, 141, 26, 40, 54, 65, 201, 52, 48, 86, 28, 100, 57, 102, 106, 142, 94, 36, 177, 250, 127, 115, 148, 189, 34, 186, 71, 15, 164, 119, 226, 250, 197, 157, 48, 40, 236, 159, 63, 80, 229, 161, 192, 21, 53, 21, 39, 32, 27, 230, 41, 248, 81, 122, 150, 238, 78, 155, 55, 225, 175, 106, 169, 115, 101, 103, 73, 66, 119, 243, 244, 229, 127, 33, 76, 57, 94, 222, 110, 172, 161, 101, 120, 37, 227, 250, 45, 205, 42, 233, 90, 34, 105, 196, 174, 132, 242, 39, 90, 90, 83, 153, 197, 181, 36, 45, 8, 89, 218, 182, 138, 146, 212, 39, 101, 125, 63, 10, 57, 52, 191, 208, 142, 40, 215, 184, 107, 87, 172, 33, 93, 128, 165, 57, 129, 215, 204, 52, 165, 146, 81, 229, 226, 145, 0, 0, 0, 0, 0, 0, 0, 4, 94, 40, 188, 81, 188, 105, 191, 202, 35, 228, 70, 225, 229, 181, 40, 243, 109, 142, 213, 0, 38, 93, 214, 202, 139, 44, 212, 42, 86, 56, 184, 220, 94, 141, 8, 171, 175, 55, 6, 9, 146, 248, 79, 146, 132, 170, 182, 210, 12, 205, 175, 86, 61, 81, 99, 72, 26, 53, 124, 200, 8, 62, 232, 145, 58, 88, 140, 80, 156, 182, 196, 199, 13, 248, 182, 135, 95, 7, 234, 230, 133, 254, 118, 12, 132, 222, 173, 124, 226, 9, 36, 63, 64, 63, 161, 202, 183, 243, 182, 118, 155, 97, 51, 22, 36, 34, 203, 142, 155, 227, 158, 30, 78, 39, 10, 247, 135, 207, 212, 83, 207, 190, 180, 242, 79, 199, 46, 180, 179, 183, 140, 158, 220, 71, 192, 35, 152, 229, 130, 139, 159, 203, 14, 228, 145, 0, 0, 0, 0, 0, 0, 0, 4, 229, 251, 155, 218, 232, 213, 74, 252, 105, 57, 155, 105, 170, 138, 98, 149, 27, 48, 37, 163, 92, 41, 51, 192, 123, 239, 185, 132, 28, 113, 210, 58, 240, 253, 6, 78, 210, 78, 165, 20, 129, 90, 61, 59, 36, 164, 50, 215, 134, 129, 125, 125, 71, 17, 122, 108, 246, 237, 122, 2, 236, 152, 215, 214, 2, 140, 47, 74, 187, 242, 14, 125, 150, 112, 140, 180, 154, 47, 91, 9, 161, 142, 91, 254, 245, 186, 121, 120, 144, 13, 38, 247, 209, 191, 215, 79, 204, 198, 4, 58, 23, 241, 86, 128, 197, 147, 38, 177, 243, 159, 161, 104, 215, 82, 153, 242, 222, 127, 144, 99, 171, 20, 112, 43, 252, 224, 102, 61, 57, 224, 130, 86, 32, 5, 116, 56, 102, 117, 104, 148, 20, 96, 102, 209]) + ] + ] + + return { parts, acks }; +}; + +export function getNValidatorsPartNAcks(count: number) { + const parts = Array(count).fill(new Uint8Array([ + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 181, 129, 31, 84, 186, 242, 5, 151, 59, 35, 196, + 140, 106, 29, 40, 112, 142, 156, 132, 158, 47, 223, 253, 185, 227, 249, 190, 96, 5, 99, 239, 213, + 127, 29, 136, 115, 71, 164, 202, 44, 6, 171, 131, 251, 147, 159, 54, 49, 1, 0, 0, 0, 0, 0, 0, 0, + 153, 0, 0, 0, 0, 0, 0, 0, 4, 177, 133, 61, 18, 58, 222, 74, 65, 5, 126, 253, 181, 113, 165, 43, + 141, 56, 226, 132, 208, 218, 197, 119, 179, 128, 30, 162, 251, 23, 33, 73, 38, 120, 246, 223, 233, + 11, 104, 60, 154, 241, 182, 147, 219, 81, 45, 134, 239, 69, 169, 198, 188, 152, 95, 254, 170, 108, + 60, 166, 107, 254, 204, 195, 170, 234, 154, 134, 26, 91, 9, 139, 174, 178, 248, 60, 65, 196, 218, + 46, 163, 218, 72, 1, 98, 12, 109, 186, 152, 148, 159, 121, 254, 34, 112, 51, 70, 121, 51, 167, 35, + 240, 5, 134, 197, 125, 252, 3, 213, 84, 70, 176, 160, 36, 73, 140, 104, 92, 117, 184, 80, 26, 240, + 106, 230, 241, 26, 79, 46, 241, 195, 20, 106, 12, 186, 49, 254, 168, 233, 25, 179, 96, 62, 104, 118, + 153, 95, 53, 127, 160, 237, 246, 41 + ])); + + const ack = new Uint8Array([ + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 145, 0, 0, 0, 0, 0, 0, 0, 4, 239, 1, 112, 13, 13, 251, + 103, 186, 212, 78, 44, 47, 250, 221, 84, 118, 88, 7, 64, 206, 186, 11, 2, 8, 204, 140, 106, 179, 52, + 251, 237, 19, 53, 74, 187, 217, 134, 94, 66, 68, 89, 42, 85, 207, 155, 220, 101, 223, 51, 199, 37, 38, + 203, 132, 13, 77, 78, 114, 53, 219, 114, 93, 21, 25, 164, 12, 43, 252, 160, 16, 23, 111, 79, 230, 121, + 95, 223, 174, 211, 172, 231, 0, 52, 25, 49, 152, 79, 128, 39, 117, 216, 85, 201, 237, 242, 151, 219, + 149, 214, 77, 233, 145, 47, 10, 184, 175, 162, 174, 237, 177, 131, 45, 126, 231, 32, 147, 227, 170, 125, + 133, 36, 123, 164, 232, 129, 135, 196, 136, 186, 45, 73, 226, 179, 169, 147, 42, 41, 140, 202, 191, 12, + 73, 146, 2 + ]); + + const acks = Array(count).fill([ack]); + + return { parts, acks }; +} \ No newline at end of file diff --git a/test/utils/utils.ts b/test/utils/utils.ts new file mode 100644 index 00000000..a45caa0f --- /dev/null +++ b/test/utils/utils.ts @@ -0,0 +1,5 @@ +export function random(low: number, high: number): bigint { + return BigInt(Math.floor((Math.random() * (high - low) + low))); +} + +export const range = (start: number, end: number) => Array.from({ length: (end - start) }, (v, k) => k + start); diff --git a/tsconfig.json b/tsconfig.json index 7e99e659..063493b3 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -14,8 +14,8 @@ "resolveJsonModule": true, "sourceMap": true, "strict": true, - "target": "es6" + "target": "es2020" }, "files": ["./hardhat.config.ts"], "include": ["./test", "./src", "./scripts"] -} \ No newline at end of file +}