diff --git a/README.md b/README.md index 6af963e..e93cee0 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Proposal 45 +# Proposal 47 Create airdrop with Sablier streams and snapshot diff --git a/contracts/Airdrop.sol b/contracts/Airdrop.sol index 271a28a..26bb13f 100644 --- a/contracts/Airdrop.sol +++ b/contracts/Airdrop.sol @@ -10,6 +10,7 @@ import "./ReentrancyGuard.sol"; import "./CarefulMath.sol"; import "./interfaces/ISablierAirdrop.sol"; +import "./interfaces/IRecipientStorage.sol"; import "./libraries/Types.sol"; contract SablierAirdrop is ISablierAirdrop, ReentrancyGuard, CarefulMath { @@ -146,31 +147,40 @@ contract SablierAirdrop is ISablierAirdrop, ReentrancyGuard, CarefulMath { return 0; } - /*** Public Effects & Interactions Functions ***/ - - struct CreateStreamLocalVars { + /** + * @notice To avoid "stack to deep" error + */ + struct CreateAirdropLocalVars { MathError mathErr; - uint256 duration; + uint256 airdropDuration; uint256 ratePerSecond; + uint256 firstStream; + Types.Recipient[] airdropRecipients; } + /*** Public Effects & Interactions Functions ***/ function createAirdrop( - Types.Recipient[] memory recipients, uint256 startTime, - uint256 stopTime + uint256 stopTime, + address recipientStorage ) public onlyGovernance returns (bool) { - uint256 airdropDuration = stopTime - startTime; - CreateStreamLocalVars memory vars; + CreateAirdropLocalVars memory vars; + vars.airdropDuration = stopTime - startTime; + vars.airdropRecipients = IRecipientStorage(recipientStorage).getAirdropRecipients(); + vars.firstStream = nextStreamId; - for (uint256 i = 0; i < recipients.length; i++) { - uint256 normalizedDeposit = recipients[i].deposit - (recipients[i].deposit % airdropDuration); - address recipientAddr = recipients[i].addr; - uint256 recipientInitialLockedBalance = recipients[i].initialLockedBalance; + require(vars.airdropRecipients.length > 0, "no airdrop recipients"); + + for (uint256 i = 0; i < vars.airdropRecipients.length; i++) { + uint256 normalizedDeposit = vars.airdropRecipients[i].deposit - + (vars.airdropRecipients[i].deposit % vars.airdropDuration); + address recipientAddr = vars.airdropRecipients[i].addr; + uint256 recipientInitialLockedBalance = vars.airdropRecipients[i].initialLockedBalance; /* Without this, the rate per second would be zero. */ - require(normalizedDeposit >= airdropDuration, "deposit smaller than time delta"); + require(normalizedDeposit >= vars.airdropDuration, "deposit smaller than time delta"); - (vars.mathErr, vars.ratePerSecond) = divUInt(normalizedDeposit, airdropDuration); + (vars.mathErr, vars.ratePerSecond) = divUInt(normalizedDeposit, vars.airdropDuration); /* `divUInt` can only return MathError.DIVISION_BY_ZERO but we know `duration` is not zero. */ assert(vars.mathErr == MathError.NO_ERROR); @@ -201,6 +211,7 @@ contract SablierAirdrop is ISablierAirdrop, ReentrancyGuard, CarefulMath { ); } + emit CreateAirdrop(startTime, stopTime, vars.airdropRecipients.length, vars.firstStream, nextStreamId - 1); return true; } @@ -249,7 +260,7 @@ contract SablierAirdrop is ISablierAirdrop, ReentrancyGuard, CarefulMath { * @param streamId The id of the stream to cancel. * @return bool true=success, otherwise false. */ - function cancelStream(uint256 streamId) external nonReentrant streamExists(streamId) onlyGovernance returns (bool) { + function cancelStream(uint256 streamId) external streamExists(streamId) onlyGovernance returns (bool) { Types.Stream memory stream = streams[streamId]; uint256 remainingBalance = stream.remainingBalance; @@ -262,11 +273,36 @@ contract SablierAirdrop is ISablierAirdrop, ReentrancyGuard, CarefulMath { } /** - * @notice Cancels airdrop and withdraw all unclaimed tokens back to governance. + * @notice Cancels all airdrop streams and withdraw all unclaimed tokens back to governance. * @dev Throws if there is a token transfer failure. * @return bool true=success, otherwise false. */ - function cancelAirdrop() external onlyGovernance returns (bool) { + function cancelAirdrop(uint256 firstStreamId, uint256 lastStreamId) external onlyGovernance returns (bool) { + require(lastStreamId < nextStreamId, "last id exceeds stream count"); + + uint256 airdropRemainingBalance; + for (uint256 streamId = firstStreamId; streamId <= lastStreamId; streamId++) { + Types.Stream memory stream = streams[streamId]; + uint256 remainingBalance = stream.remainingBalance; + + if (remainingBalance > 0) { + airdropRemainingBalance += stream.remainingBalance; + + delete streams[streamId]; + emit CancelStream(streamId, stream.recipient, stream.remainingBalance); + } + } + + torn.safeTransfer(tornadoGovernance, airdropRemainingBalance); + return true; + } + + /** + * @notice Withdraw all unclaimed tokens back to governance without canceling airdrop streams + * @dev Throws if there is a token transfer failure. + * @return bool true=success, otherwise false. + */ + function withdrawFunds() external onlyGovernance returns (bool) { torn.safeTransfer(tornadoGovernance, torn.balanceOf(address(this))); return true; } diff --git a/contracts/AirdropRecipients.sol b/contracts/AirdropRecipients.sol new file mode 100644 index 0000000..fc04493 --- /dev/null +++ b/contracts/AirdropRecipients.sol @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.9; + +import "./libraries/Types.sol"; + +/** + * @notice i create separate contract bcs i will use the same airdrop recipients in two proposals + */ +contract AirdropRecipients { + Types.Recipient[] public airdropRecipients; + + constructor(Types.Recipient[] memory _recipients) { + for (uint256 i = 0; i < _recipients.length; i++) { + airdropRecipients.push(_recipients[i]); + } + } + + function getAirdropRecipients() external view returns (Types.Recipient[] memory) { + return airdropRecipients; + } +} diff --git a/contracts/Proposal.sol b/contracts/Proposal.sol index 101a5bc..1a2ee9b 100644 --- a/contracts/Proposal.sol +++ b/contracts/Proposal.sol @@ -8,29 +8,19 @@ import { ISablierAirdrop } from "./interfaces/ISablierAirdrop.sol"; // copied fr contract Proposal { IERC20 public constant torn = IERC20(0x77777FeDdddFfC19Ff86DB637967013e6C6A116C); ISablierAirdrop public immutable airdrop; + address public immutable airdropRecipientStorage; uint256 public constant airdropDuration = 180 days; - Types.Recipient[] public recipients; - constructor(address _airdropContract) { - Types.Recipient[1] memory _recipients = [ - Types.Recipient({ - addr: 0xeb3E49Af2aB5D5D0f83A9289cF5a34d9e1f6C5b4, - deposit: 1000 ether, - initialLockedBalance: 1000 ether - }) - ]; + constructor(address _airdropContract, address _airdropRecipientsStorage) { airdrop = ISablierAirdrop(_airdropContract); - for (uint256 i = 0; i < _recipients.length; i++) { - recipients.push(_recipients[i]); - } + airdropRecipientStorage = _airdropRecipientsStorage; } - function executeProposal() external { + function executeProposal() public { torn.transfer(address(airdrop), 1000000 ether); - require(recipients[0].addr != address(0), "zero"); uint256 startTime = block.timestamp; uint256 endTime = startTime + airdropDuration; - airdrop.createAirdrop(recipients, startTime, endTime); + airdrop.createAirdrop(startTime, endTime, airdropRecipientStorage); } } diff --git a/contracts/interfaces/IRecipientStorage.sol b/contracts/interfaces/IRecipientStorage.sol new file mode 100644 index 0000000..ac6bb7b --- /dev/null +++ b/contracts/interfaces/IRecipientStorage.sol @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity >=0.5.17; + +pragma experimental ABIEncoderV2; + +import "../libraries/Types.sol"; + +interface IRecipientStorage { + function getAirdropRecipients() external view returns (Types.Recipient[] memory); +} diff --git a/contracts/interfaces/ISablierAirdrop.sol b/contracts/interfaces/ISablierAirdrop.sol index 897ec08..93c64f8 100644 --- a/contracts/interfaces/ISablierAirdrop.sol +++ b/contracts/interfaces/ISablierAirdrop.sol @@ -18,6 +18,17 @@ interface ISablierAirdrop { uint256 stopTime ); + /** + * @notice Emits when full airdrop is successfully created. + */ + event CreateAirdrop( + uint256 startTime, + uint256 stopTime, + uint256 recipientsAmount, + uint256 firstStreamId, + uint256 lastStreamId + ); + /** * @notice Emits when the recipient of a stream withdraws a portion or all their pro rata share of the stream. */ @@ -44,11 +55,7 @@ interface ISablierAirdrop { uint256 ratePerSecond ); - function createAirdrop( - Types.Recipient[] calldata recipients, - uint256 startTime, - uint256 stopTime - ) external returns (bool); + function createAirdrop(uint256 startTime, uint256 stopTime, address recipientStorage) external returns (bool); function withdrawFromStream(uint256 streamId, uint256 funds) external returns (bool); diff --git a/contracts/libraries/Types.sol b/contracts/libraries/Types.sol index 0a23d75..567abba 100644 --- a/contracts/libraries/Types.sol +++ b/contracts/libraries/Types.sol @@ -1,10 +1,6 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity >=0.5.17; -/** - * @title Sablier Types - * @author Sablier - */ library Types { struct Stream { uint256 deposit; diff --git a/data/airdropRecipients.json b/data/airdropRecipients.json index 0e9e5ac..40ef96d 100644 --- a/data/airdropRecipients.json +++ b/data/airdropRecipients.json @@ -1,967 +1,507 @@ [ - { - "addr": "0xA29DbaA84a9949A0A38a2Ba07E0b75e6603934DB", - "initialLockedBalance": "222061659733700101062", - "deposit": "137712154083725857922" - }, - { - "addr": "0xe9B4aA5906C6e842e52aE7B7ab4dec3EE52362cB", - "initialLockedBalance": "187871680391712414210", - "deposit": "116509143582455301337" - }, { "addr": "0x642df98E9d71Ba533dF7288512cF63D34a907659", "initialLockedBalance": "3274920890240498949168", - "deposit": "2030951271775840853887" + "deposit": "2004814304723645272516" }, { "addr": "0x97b90FBc8904F861F76CB06BFa0A465b72C5E662", "initialLockedBalance": "1957577871492703175932", - "deposit": "1213997345571417446927" + "deposit": "1198374022125105268723" }, { "addr": "0xBFb910652F850F85E3F85AA0C12aE8f4037095b0", "initialLockedBalance": "18064223509187007832993", - "deposit": "11202578303176107566187" - }, - { - "addr": "0xe2506955723C01dDd6e619dD0829e28F76328c41", - "initialLockedBalance": "369300000000000000000", - "deposit": "229022419106966084976" - }, - { - "addr": "0x3Df488Bd07C2082E84B1CD63F343Cf3d538342bA", - "initialLockedBalance": "268606679563771005193", - "deposit": "166577177205482007264" + "deposit": "11058408709311980658129" }, { "addr": "0x92F82EF0D08d8ADa7f542fC300adfd0b712b5963", - "initialLockedBalance": "3614275869036584865053", - "deposit": "2241403202942569198557" + "initialLockedBalance": "3697937593601682896111", + "deposit": "2263773212880129366243" }, { "addr": "0x65C6AA5521F9b149E918A9A44A44FD651dF0AFF3", "initialLockedBalance": "1337537896786103209588", - "deposit": "829477835822358177551" - }, - { - "addr": "0x25713B024a8004727Ba79c43647a77c7447948dB", - "initialLockedBalance": "327316949018727268744", - "deposit": "202986513617601971220" - }, - { - "addr": "0xB157ba30e3467DdBC844f14F02b4ba741f1d549F", - "initialLockedBalance": "300000008217141924923", - "deposit": "186045837026806247722" + "deposit": "818803017983691524659" }, { "addr": "0x83c418D2eD6670785330B996b47a18492b61e218", "initialLockedBalance": "24604927081108500781847", - "deposit": "15258813761348418011124" - }, - { - "addr": "0x39978cc40e2D1d7E127050bDFFFBB0dFcfaEbAd0", - "initialLockedBalance": "407032960152083087629", - "deposit": "252422618982668288170" - }, - { - "addr": "0x1d7979F557BA38892f25D3d54Fa6C1D75a4CfA27", - "initialLockedBalance": "176136388919542490495", - "deposit": "109231470032816240159" - }, - { - "addr": "0x9433ea2C250D84d3fD6398699D48728fa610569A", - "initialLockedBalance": "320126637964798831618", - "deposit": "198527422278034547590" + "deposit": "15062443164929711616095" }, { "addr": "0xF99d1946Bf038a1205d430Ec91401E760e5F8F6F", "initialLockedBalance": "37075508978146311050113", - "deposit": "22992479707005438225042" + "deposit": "22696582068838664514735" }, { "addr": "0x9897Bc7231492CDf163BB81bFF10A5919a73d132", "initialLockedBalance": "9523810000000000000000", - "deposit": "5906217182006809287179" + "deposit": "5830208167888886361781" }, { "addr": "0x9C42EBDf0fA6fA0274aEEBf981613Dfa9c99BFF8", "initialLockedBalance": "43892178461318681920771", - "deposit": "27219856190321898062447" + "deposit": "26869555080542013306367" }, { "addr": "0xeE1D1ac27A80De54F0ba92b2E25EBb3418495db2", - "initialLockedBalance": "2331546926022547020105", - "deposit": "1445915291792835672082" - }, - { - "addr": "0xefe8Aa053Ef0C9F1879911ef1C83Da08AD385164", - "initialLockedBalance": "306015687989988508846", - "deposit": "189776477520037140979" - }, - { - "addr": "0x238926025E84475e3182774df480021470f8F978", - "initialLockedBalance": "119748510011508001412", - "deposit": "74262370558598184724" - }, - { - "addr": "0x0c3a4a0ed70fDB29860760b5ca78B116Fe77DE00", - "initialLockedBalance": "140306615000000000000", - "deposit": "87011536376955684545" - }, - { - "addr": "0x54F2f104Fb6ABf1a6991150B27662Aade958A338", - "initialLockedBalance": "319349649026838373837", - "deposit": "198045570433487955572" - }, - { - "addr": "0x327346e623A4334f7c4034D5a73Ac636d33a31c0", - "initialLockedBalance": "304751021776330822150", - "deposit": "188992191260587558962" - }, - { - "addr": "0xeafa6FbaebB26F9d07B42f3Fd8906818CE75026F", - "initialLockedBalance": "922236496491056455335", - "deposit": "571927520755794174703" + "initialLockedBalance": "2616085853090372402156", + "deposit": "1601494056326832896097" }, { "addr": "0xe443cbad516eE9b00A2CbE7F884A4bb314776dE3", - "initialLockedBalance": "64680368781627387285673", - "deposit": "40111710065255870068208" - }, - { - "addr": "0x2D56db2f95Ae61c2396d30ABEa61fc91E506943F", - "initialLockedBalance": "135065031612858769227", - "deposit": "83760953903969034612" - }, - { - "addr": "0xc7557AfDB4C2EF7E2A5e68ed60B1f8AC41c87459", - "initialLockedBalance": "100170264404649634361", - "deposit": "62120867253011847070" - }, - { - "addr": "0x6eA8BfAa4697187D3BB1E27688931d73BcbbEC0b", - "initialLockedBalance": "439287784325687715732", - "deposit": "272425537639881340272" - }, - { - "addr": "0xE0a9Cf94C4c41a7709B55D9bA37D788A8DF19F9E", - "initialLockedBalance": "118418383918603784875", - "deposit": "73437489173506874713" - }, - { - "addr": "0x06F166E11d765aE936E7ec36777E1b4B6f0Cb83B", - "initialLockedBalance": "180305703889462319555", - "deposit": "111817082273352191382" - }, - { - "addr": "0x1023aE712D5F219e9166a9D286e183226DFAafa6", - "initialLockedBalance": "143712248142294445923", - "deposit": "89123549214321328899" - }, - { - "addr": "0x75F3fC9189fd3228a4178e544CdE26b75Da81Bf3", - "initialLockedBalance": "547090923569720095523", - "deposit": "339279953391285095179" - }, - { - "addr": "0x90e14E059B28Af64B52d4Da0442b22052f507eF1", - "initialLockedBalance": "906706256793263291165", - "deposit": "562296399540252262006" - }, - { - "addr": "0x344651A2445484bd2928eB46D2610DaaC1B42A66", - "initialLockedBalance": "244547007283286030643", - "deposit": "151656504720788034033" + "initialLockedBalance": "67999143733426979646229", + "deposit": "41627160055070014952951" }, { "addr": "0x2490419318b3F69e8dc209604056f40Eb350d0d7", "initialLockedBalance": "1641166788776420175594", - "deposit": "1017774135184367682001" - }, - { - "addr": "0x4aAE2d5072385b02465263d5feb91bb1995D4f37", - "initialLockedBalance": "133266200000000000000", - "deposit": "82645403490909189476" + "deposit": "1004676071529383683706" }, { "addr": "0x0df59978Cc975e27C5E4e19d355e025F0770F088", "initialLockedBalance": "1278073898007810414591", - "deposit": "792601072080201958361" - }, - { - "addr": "0x85e6C3c83929eE45712EFF4F89c5E74cCddB5D41", - "initialLockedBalance": "220168850000000000000", - "deposit": "136538322878415244836" - }, - { - "addr": "0xC346A5dc3b3821AEeF3f3fFB70989631521E41cD", - "initialLockedBalance": "224707550488945833056", - "deposit": "139353010572919291597" + "deposit": "782400833209684334969" }, { "addr": "0x5d17B355538A9ea9b45A0018e11b36947fC16376", "initialLockedBalance": "3461949885239649131822", - "deposit": "2146937821675245232841" - }, - { - "addr": "0xAaF7168Bae99a4860D7729745B22C4b48d1f9Adb", - "initialLockedBalance": "100475944611586099877", - "deposit": "62310435681026218386" + "deposit": "2119308186297941176769" }, { "addr": "0xB835b4e277094D4AF9Fbb66e9f5Db9e6E8dC65dB", "initialLockedBalance": "2499187111378392690208", - "deposit": "1549877817624777089547" + "deposit": "1529931940036701386170" }, { "addr": "0x42DbF634c256acd17beDDC1330488F1BEa7B8BDf", "initialLockedBalance": "6877216358537763535178", - "deposit": "4264924795977034435640" - }, - { - "addr": "0xE7304bA0f157f2Ade94015934284b6704BC72911", - "initialLockedBalance": "112608649098976008132", - "deposit": "69834566014121208052" + "deposit": "4210038103016117810921" }, { "addr": "0x3eE9378Fb0809a243FcF7C30865941675d766D71", "initialLockedBalance": "2774004155905058916423", - "deposit": "1720306369883980751803" - }, - { - "addr": "0x81348BB6CFA32662cE76aE5FcC8c54F056CE7042", - "initialLockedBalance": "100400761930000000000", - "deposit": "62263810932551272954" + "deposit": "1698167192280756360412" }, { "addr": "0x06981EfbE070996654482F4F20786e0CEf0f8740", - "initialLockedBalance": "32754177841356351554810", - "deposit": "20312594219028475614390" - }, - { - "addr": "0x92e74E50edCE4573d181C03cA889f72640cD3a94", - "initialLockedBalance": "407199993263279657437", - "deposit": "252526205029776875443" - }, - { - "addr": "0x3dD44f129563787449367046c9cBF5610f21467f", - "initialLockedBalance": "196204479061497808556", - "deposit": "121676751785232339178" - }, - { - "addr": "0x0A54cf15a8719DB69B5cC40d797a213ca9407B8E", - "initialLockedBalance": "370960788258305263912", - "deposit": "230052361550891122613" - }, - { - "addr": "0x95880f2E70203f759168665Feb6948E81Fe5dF77", - "initialLockedBalance": "294020437588528361099", - "deposit": "182337589719505840836" - }, - { - "addr": "0x0050faCd2C04930257438b213FE9E132a26E5a29", - "initialLockedBalance": "119786423000000000000", - "deposit": "74285882403548122668" - }, - { - "addr": "0x1d14080067dE02E048DdE58a936b4EBED7ee56e4", - "initialLockedBalance": "135408011012662929013", - "deposit": "83973653529874813015" - }, - { - "addr": "0xbb6d1648A8BeF51603Badd347Dc91eb7D04a43e5", - "initialLockedBalance": "961751770023408248012", - "deposit": "596433027216808733123" + "initialLockedBalance": "43121397719834144990842", + "deposit": "26397704825795793106456" }, { "addr": "0xD7b2879C8922cd704E41E8CC1f18f6994D6B7C36", "initialLockedBalance": "1119299000000000000000", - "deposit": "694136378781500221899" - }, - { - "addr": "0x7a628E9bCC082844797C37c79084ed6BC99e6Abc", - "initialLockedBalance": "138985632834248119775", - "deposit": "86192325623644948413" - }, - { - "addr": "0xDaa5C5a5B6725666B1e37B14dc8e1FCB446c5952", - "initialLockedBalance": "119080000000000000000", - "deposit": "73847792221114328185" - }, - { - "addr": "0x5dab475E601D55efa2290D27333913e025C7Bd89", - "initialLockedBalance": "146964212351551947890", - "deposit": "91140263836724321518" - }, - { - "addr": "0x4051e1fcD4Be1366a0CDcfA47ca717868A96575E", - "initialLockedBalance": "561299291075539499694", - "deposit": "348091311901286638548" - }, - { - "addr": "0xB3AAd889bf41Ec39571aFa78aa5D9A26a05DDaAb", - "initialLockedBalance": "208128000000000000000", - "deposit": "129071156360397068328" - }, - { - "addr": "0x4303Ddc9943D862f2B205aF468a4A786c5137E76", - "initialLockedBalance": "121978258758390804343", - "deposit": "75645155427300664363" + "deposit": "685203313811369884096" }, { "addr": "0xa1eBC8bdE2F1F87fe24F384497b6bD9cE3B14345", "initialLockedBalance": "2984693312345136089833", - "deposit": "1850965834513042482137" + "deposit": "1827145158111926585380" }, { "addr": "0xaf095d9cedBc20c8Bb0A75ED9509c1f31DC4E7E6", "initialLockedBalance": "4411294324551597847209", - "deposit": "2735676408344535371939" - }, - { - "addr": "0x4839460F05b2a8fC1b615e0523EbC46eFba75420", - "initialLockedBalance": "147677697371346056769", - "deposit": "91582733550317141439" - }, - { - "addr": "0x6b69c30354Cef94ee9d77DBC7BD268B4A6683825", - "initialLockedBalance": "215671961915475600719", - "deposit": "133749565262463257561" - }, - { - "addr": "0x1CE7DC66CC98c61A573105514d073D64a9a8608f", - "initialLockedBalance": "183302847714096393245", - "deposit": "113675769327587772448" + "deposit": "2700470106182569134054" }, { "addr": "0x0d4E989c7620C8749c9417d2BF218896C767B606", "initialLockedBalance": "11111000000000000000000", - "deposit": "6890517461948280991520" - }, - { - "addr": "0x4963C9C61f48272969587c27aA4e6384798d48cA", - "initialLockedBalance": "646591448141274005553", - "deposit": "400985479629545037314" - }, - { - "addr": "0x6fb4becf05497b79F0fCF61CfA5075efAA137DDF", - "initialLockedBalance": "118347626348277285232", - "deposit": "73393608670050860014" - }, - { - "addr": "0x6f9BB7e454f5B3eb2310343f0E99269dC2BB8A1d", - "initialLockedBalance": "554530214763375646077", - "deposit": "343893450454951879621" - }, - { - "addr": "0xb4e39F6D3d386E98AF0C064E087aCBC9A8F08944", - "initialLockedBalance": "147140882538472853905", - "deposit": "91249826343067960228" - }, - { - "addr": "0x2462375371935c8122895e701380A06CE815B0FD", - "initialLockedBalance": "214282527968312078762", - "deposit": "132887903947086246196" - }, - { - "addr": "0x24f04EC62597C11752c47448228B63052ED3158a", - "initialLockedBalance": "321761894521216575819", - "deposit": "199541531166231998831" - }, - { - "addr": "0x8904FFC6Aa039dB5941De11309a42372F3F7D2FD", - "initialLockedBalance": "296350209248534143997", - "deposit": "183782404075155384585" - }, - { - "addr": "0xa729adDeFe1fa7BCe87053ed55D55EDdDD13De60", - "initialLockedBalance": "105257962571588444433", - "deposit": "65276017379950388262" - }, - { - "addr": "0x9265f86d58b348060E43216f968bda8A6Bb63572", - "initialLockedBalance": "462054994392400414840", - "deposit": "286544686098573495848" - }, - { - "addr": "0xcE1fFD4cfE424757D6e597293566195Fba6f4cD8", - "initialLockedBalance": "378325759765781498396", - "deposit": "234619769055077653820" + "deposit": "6801841170016350217587" }, { "addr": "0x2E63Dbd91657dc5fa97213Ba6a1AEb5f194805F6", "initialLockedBalance": "1200089842937217922038", - "deposit": "744239044070351003936" - }, - { - "addr": "0x4273397532A8dF43a6607C4441e3EB6edF63acf3", - "initialLockedBalance": "150000000000000000037", - "deposit": "93022915965461448022" + "deposit": "734661191738711575684" }, { "addr": "0xC68c10C524eC53A284FB76a91b2e97F15Fe79634", "initialLockedBalance": "1295708210000000000000", - "deposit": "803537039563923164080" - }, - { - "addr": "0x12168AEa666Be756E1aD0595fEd9C306442a4103", - "initialLockedBalance": "129858882018647549604", - "deposit": "80532345795929491274" - }, - { - "addr": "0xE70eF2B9A263855535727Ee014C6Ffaf01881Ae3", - "initialLockedBalance": "126263397985613051754", - "deposit": "78302596402195314565" + "deposit": "793196062200179174796" }, { "addr": "0x5Fc0A53A7e33Aa6E41A93b718DD2216707251fC2", "initialLockedBalance": "1216512730000000000000", - "deposit": "754423743024693945441" - }, - { - "addr": "0x18F516dD6D5F46b2875Fd822B994081274be2a8b", - "initialLockedBalance": "808879218854315691416", - "deposit": "501628690677954052253" + "deposit": "744714820516873760042" }, { "addr": "0x7803Ab56769dDa5432CDbd63749a6BEeb3180008", "initialLockedBalance": "1000020482341666374383", - "deposit": "620165475284060366758" - }, - { - "addr": "0x4F50d47D20380172746527bbeAa274940C38EFAC", - "initialLockedBalance": "489392817721401322749", - "deposit": "303498313046655382433" - }, - { - "addr": "0xFeAe121618049802Ccb40f094536a7B186642699", - "initialLockedBalance": "748171152585153967146", - "deposit": "463980415031408080496" + "deposit": "612184365732261263987" }, { "addr": "0x069Dd24FC8ABEC3708841a4726617c17BC74d5eC", "initialLockedBalance": "4465692444586264801956", - "deposit": "2769411553335628098085" + "deposit": "2733771102710630419369" }, { "addr": "0x11A2A99396c1BC4D878c9ac86401d38d5f2f4caE", "initialLockedBalance": "1841131594759449968212", - "deposit": "1141782864137762235164" + "deposit": "1127088892147663211458" }, { "addr": "0x26D3b88d464A575784Be70Edc5F9290dC5e296DB", "initialLockedBalance": "4584368997732369384071", - "deposit": "2843009146871499471200" - }, - { - "addr": "0x7Abbdbd51813d85B448F887b946719Dd2B09D6F7", - "initialLockedBalance": "477257927573167840914", - "deposit": "295972827269927187802" + "deposit": "2806421545074486738262" }, { "addr": "0xEb89EfE3Ed80288E310c5529e1E242b4ab56E196", "initialLockedBalance": "1300090776209185468018", - "deposit": "806254900151857368940" - }, - { - "addr": "0xAD142B79f2500Bf194C174f06C7dC901A2CdA74f", - "initialLockedBalance": "174034164798218427885", - "deposit": "107927769914292944774" - }, - { - "addr": "0x4fFDAeB9f4ec23254B6DFA41eEeF2C8d23f8c554", - "initialLockedBalance": "131502368878796458509", - "deposit": "81551558729809304902" - }, - { - "addr": "0xb03384cA294C06E8d04B08412E8467ff2363E5E3", - "initialLockedBalance": "906139663513082751610", - "deposit": "561945025146326732110" - }, - { - "addr": "0x6A3738c6299f45c31697aceA647D49EdCC9C28A4", - "initialLockedBalance": "426032828677716268597", - "deposit": "264205440137433563456" - }, - { - "addr": "0xc74d1af789F5A0223448Db69a1B56c84845e17d5", - "initialLockedBalance": "386136667062531373859", - "deposit": "239463724875608142556" - }, - { - "addr": "0xDf90418385aF4E9833603069DEaF7C71d76f83a2", - "initialLockedBalance": "683465828138249494426", - "deposit": "423853228641125993744" - }, - { - "addr": "0x16eb5Fbb2a5c7dAbC2c7688482378e89471d5724", - "initialLockedBalance": "251802411781229744678", - "deposit": "156155963940172361485" + "deposit": "795878945763491226316" }, { "addr": "0x356eE97D7D560af2E97E9f9EEe56b2e09D60e6F5", "initialLockedBalance": "10836062927446519092234", - "deposit": "6720014473975398114095" - }, - { - "addr": "0x21c756E2c7B898BDa8a3b2A77e4C56D855Ab9414", - "initialLockedBalance": "261098218101404112455", - "deposit": "161920784007857599013" - }, - { - "addr": "0xFB96D60ce3ee83ed4BC71c6E0da10C537601b77C", - "initialLockedBalance": "446702746160587197664", - "deposit": "277023946784247729147" - }, - { - "addr": "0xeb0fCD59212E521918b514c64313eF5a3dd101f8", - "initialLockedBalance": "100240415124564555330", - "deposit": "62164371416502262511" - }, - { - "addr": "0x34DF0B83cf4F30683f8AB2Ac971a52A5f663FEb4", - "initialLockedBalance": "116124431887044456353", - "deposit": "72014888459769921482" + "deposit": "6633532439995826525191" }, { "addr": "0xF2Ba32f180B243D3138DEd0E1F1BdbdcCBCE0702", "initialLockedBalance": "1482848214495146566693", - "deposit": "919592432310110475444" - }, - { - "addr": "0xbC063735a5b8bdd12611157E7E0F29D1570D892D", - "initialLockedBalance": "509451890000000000000", - "deposit": "315938002346103396038" - }, - { - "addr": "0xe7c724F87EcFf8E2f563962f96b6c291cBD729cF", - "initialLockedBalance": "250243001109044335565", - "deposit": "155188891087410047740" + "deposit": "907757900660455726169" }, { "addr": "0x1fe7d323946A7C3B644528baA42eFf13056cd2B4", "initialLockedBalance": "2012288953464165015019", - "deposit": "1247926574775489230293" + "deposit": "1231866605133801915315" }, { "addr": "0x48c0477Bf79a59e505d26eB33c5b331502a511B2", - "initialLockedBalance": "11028610297596262814514", - "deposit": "6839423259527466183047" + "initialLockedBalance": "11808140176616152755130", + "deposit": "7228610745624325871482" }, { "addr": "0xE5A5BfC1772D4A2b44Add05aae63026A89486C1B", "initialLockedBalance": "2897272017864013753943", - "deposit": "1796751276312313804058" - }, - { - "addr": "0x00377B2FC0044Dec6507855eDd6531aF1755cCe4", - "initialLockedBalance": "942500316330675833924", - "deposit": "584494184822995267578" - }, - { - "addr": "0xD9D10dc5609d77F2A15FAa68414835A6ed19269B", - "initialLockedBalance": "604677796610747756803", - "deposit": "374992612402013185045" - }, - { - "addr": "0xdF20a1124d6B44e19ad75675a622d9c9669E59B6", - "initialLockedBalance": "720900000000000000000", - "deposit": "447068134130007719088" - }, - { - "addr": "0xF4d2D64D1f9190A9daB0960c80e5C73c04710184", - "initialLockedBalance": "630536604758334996358", - "deposit": "391029023983879835698" - }, - { - "addr": "0xf68de31d7fC80A70959966F9Aa78e86A7b418A10", - "initialLockedBalance": "100424753924039137153", - "deposit": "62278689634186916337" + "deposit": "1773628304548987061553" }, { "addr": "0x47B9cCa44fe405D12ff56aaCd1Df6dbA4A79Ae28", "initialLockedBalance": "1198321376929923406445", - "deposit": "743142324971788784895" - }, - { - "addr": "0x71917F124be5C0Cd97aDBE7AB472f4C82577B542", - "initialLockedBalance": "171985544540000000000", - "deposit": "106657312380123646444" - }, - { - "addr": "0x2a2a1FB6382a528F1B23E76d3Ed6F4C17A9e5966", - "initialLockedBalance": "679861011890874134021", - "deposit": "421617691848789138824" + "deposit": "733578586672003784191" }, { "addr": "0x343F48B346b0cE11342ffdEDaDAC4135E1FD525a", - "initialLockedBalance": "1112013784183226328856", - "deposit": "689618431990073636589" - }, - { - "addr": "0x958622B4631212DC751c5B1Ba45013c833Dcb86c", - "initialLockedBalance": "1000000000000000000000", - "deposit": "620152773103076320000" - }, - { - "addr": "0x0F46576F3b8b0ed6522e4b200Df53ac73251b911", - "initialLockedBalance": "440579268126896398907", - "deposit": "273226454900618607292" + "initialLockedBalance": "1244831656243158248642", + "deposit": "762050869334385255591" }, { "addr": "0xaAaC34d30d6938787c653AAfB922bc20bFa9C512", "initialLockedBalance": "2313674300000000000000", - "deposit": "1434831533202318932522" + "deposit": "1416366223359622003260" }, { "addr": "0x758aB8aC42a8c44dF8C31129Db146c65c2669391", "initialLockedBalance": "9999580000000000000000", - "deposit": "6201267266866059907945" - }, - { - "addr": "0x149da2CB603A8818Fb2d703D72D46390Cd09A6D9", - "initialLockedBalance": "351315917791207543375", - "deposit": "217869540653469745005" + "deposit": "6121461158030068878478" }, { "addr": "0xC2e6B265cb965DED721566f0f9Eb5ab1A6162A21", "initialLockedBalance": "2004486788385385993147", - "deposit": "1243088040465676437960" + "deposit": "1227090339482816134431" }, { "addr": "0x4e3072f7b5C075EA5FdEb423DA95312C4B99dc22", "initialLockedBalance": "3776301446297895060890", - "deposit": "2341883813994797462369" + "deposit": "2311745355757475480138" }, { "addr": "0x4d6A11EbEC10E133A5007578Ad792F765ED724F2", "initialLockedBalance": "19993341693923915158883", - "deposit": "12398926295084273323110" + "deposit": "12239360512999380835412" }, { "addr": "0x4F0535b9F0ad2f08dd01Fb4DA3ED15718978B2a9", "initialLockedBalance": "1713558815628887133179", - "deposit": "1062668251387477431363" + "deposit": "1048992430869320583495" }, { "addr": "0xddbc1841BE23b2ab55501Deb4d6bc39E3f8AA2d7", - "initialLockedBalance": "48363478557462694029018", - "deposit": "29992745344321658938248" + "initialLockedBalance": "49454261304684065909473", + "deposit": "30274505496800160316711" }, { "addr": "0x7b5edF38D955dd9deC103aF05c2D68B28e02Ad90", - "initialLockedBalance": "29597872806644626228418", - "deposit": "18355202898992797589838" + "initialLockedBalance": "30721199782932567542900", + "deposit": "18806652999356322522553" }, { "addr": "0xE4143f6377AEcd7193b9731d1C28815b57C4f5Ab", "initialLockedBalance": "98406849008651890866330", - "deposit": "61027280305051186971055" + "deposit": "60241900548882287002636" }, { "addr": "0x9Fd4d0dE8A3A8a8F2aC003A5ece295CE9512d9c6", "initialLockedBalance": "16038729098845967400725", - "deposit": "9946462327698330956413" + "deposit": "9818458095515231506193" }, { "addr": "0xa39fE8D3094e2D69Bd579Dc2bc2fc44Feb54Fc57", "initialLockedBalance": "62364443294474230012244", - "deposit": "38675482452097746632776" - }, - { - "addr": "0x6f4CbC2E042ed0D1Df4bf14d00eEb52Ff1E0e5F8", - "initialLockedBalance": "632357477375385036674", - "deposit": "392158243186810874128" + "deposit": "38177755192647369581395" }, { "addr": "0x92374BA66EE27f207F9efff0837FF6D707006304", - "initialLockedBalance": "26511566449802577442283", - "deposit": "16441221453151548410460" + "initialLockedBalance": "27582360269943737743173", + "deposit": "16885143879968194272088" }, { "addr": "0x9Ff3C1Bea9ffB56a78824FE29f457F066257DD58", "initialLockedBalance": "1081206035039738702927", - "deposit": "670512920925675861069" + "deposit": "661883873855047722935" }, { "addr": "0x94596B6A626392F5D972D6CC4D929a42c2f0008c", - "initialLockedBalance": "6237585974021878690758", - "deposit": "3868256239258521440628" - }, - { - "addr": "0x065f2A0eF62878e8951af3c387E4ddC944f1B8F4", - "initialLockedBalance": "289834051536966486101", - "deposit": "179741390800349705806" + "initialLockedBalance": "6435143032935074622460", + "deposit": "3939413267605226576623" }, { "addr": "0x7C199A0f301913212cfAB3756c3ed8F5B8927713", "initialLockedBalance": "7414560240165695407853", - "deposit": "4598160094278567570627" + "deposit": "4538984888770168690491" }, { "addr": "0x544F1D81aF6DdA4ca3Be8E1B8f28a3C270a007bb", "initialLockedBalance": "1423536639305809866205", - "deposit": "882810194479331701702" + "deposit": "871449025313380694981" }, { "addr": "0x8Fec4550BF2D184950391f3e053eD7A9557A5FE5", "initialLockedBalance": "7924889676611148883137", - "deposit": "4914642309486345686864" + "deposit": "4851394192260937109610" }, { "addr": "0x50042C58F7F55d62EC5275F67Ac4F847e4c93FBb", "initialLockedBalance": "13849331891297736274686", - "deposit": "8588701578013163885182" + "deposit": "8478170806898510207075" }, { "addr": "0x1c24ca7497947F8317Ccb2BfA9E404Fc57Aa3f0F", "initialLockedBalance": "39291332117152764542755", - "deposit": "24366628571366253718339" + "deposit": "24053046568196864267448" }, { "addr": "0x64Cd976be8b37db8402C65eae0893E94F21D3556", "initialLockedBalance": "3166824297101437639597", - "deposit": "1963914869777657009114" + "deposit": "1938640615807096433220" }, { "addr": "0x7268335b68638B16F4A86360f3E9eb322301ab90", "initialLockedBalance": "1053386541481860916683", - "deposit": "653260584849434784914" + "deposit": "644853563656957743719" }, { "addr": "0xBEF6d320Ed305BC9a0977D312c0c1BF9f56749D4", - "initialLockedBalance": "16792018296955216982422", - "deposit": "10413616712854374719888" + "initialLockedBalance": "17647018296955216982422", + "deposit": "10803007432297886158423" }, { "addr": "0x6e1Ea6FCEE2221844950FB269780BB450f47b6Ee", "initialLockedBalance": "55567601300164580084708", - "deposit": "34460402040983173549160" + "deposit": "34016920011026326250380" }, { "addr": "0x25a3BD3A11DDf704b695a185143Ad582936724EA", "initialLockedBalance": "52522786968174962240266", - "deposit": "32572151989415821179294" + "deposit": "32152970458476347486656" }, { "addr": "0xAd0dC9b5bf4308Cc26C1d44E1BEB2d30c43Bca1b", "initialLockedBalance": "146313191178089164638730", - "deposit": "90736531250652557606055" + "deposit": "89568813560579599899399" }, { "addr": "0xfA9330bb565c2F502D371a96A9F43D9182D732c9", - "initialLockedBalance": "2932970328956661635966", - "deposit": "1818889682931515698545" + "initialLockedBalance": "3346805409290437403641", + "deposit": "2048819982084881524260" }, { "addr": "0x09AdFab2635dcb681FADA41CeB0bfa6f52EFfd97", "initialLockedBalance": "73474731701589249491935", - "deposit": "45565558617745086536199" + "deposit": "44979160745547227024940" }, { "addr": "0xb5a07432eEe9a07176E6Da4B25b2b04a00C2407B", "initialLockedBalance": "17680387515310000000000", - "deposit": "10964541347156505735882" + "deposit": "10823435127664354378147" }, { "addr": "0xeb3E49Af2aB5D5D0f83A9289cF5a34d9e1f6C5b4", - "initialLockedBalance": "1011706736327691989355", - "deposit": "627412738100681031188" + "initialLockedBalance": "4736654395057849473603", + "deposit": "2899646374983653173540" }, { "addr": "0xD97938E0EAa80d8801174e6cF3E7155C872aDdcD", "initialLockedBalance": "11018292609207029948990", - "deposit": "6833024716460870008800" + "deposit": "6745088317216384559631" }, { "addr": "0xa5c4024fFb7C28516DAC1D83B3f92e5FeE7D3c22", "initialLockedBalance": "7177114122787556481405", - "deposit": "4450907226123956153834" + "deposit": "4393627065276049339976" }, { "addr": "0x9DD56f43baB75551114fce768b7F85aBcbc4d61c", "initialLockedBalance": "4862000000000000000000", - "deposit": "3015182782827157067840" + "deposit": "2976379422969984228054" }, { "addr": "0xef5031F705dfBD187B7F6A86f4173cB067afD1A9", - "initialLockedBalance": "42729083148460923251275", - "deposit": "26498559406669968884335" + "initialLockedBalance": "44126667450172916291870", + "deposit": "27013102633264921813266" }, { "addr": "0xFB7c1D49e006eaDdff2385c7eF8B0C5Cf49d038A", "initialLockedBalance": "1758194322344402845627", - "deposit": "1090349084655965486336" + "deposit": "1076317030565309787974" }, { "addr": "0x0AD50B53b0c142432c5f6c5c1fA1e4bb03021374", "initialLockedBalance": "10000000000000000000000", - "deposit": "6201527731030763200000" - }, - { - "addr": "0xa99a29c335590685cCeaCeD2A0dBAf2C099CBeD9", - "initialLockedBalance": "170002896000000000000", - "deposit": "105427767389953880909" + "deposit": "6121718270197417170000" }, { "addr": "0xa983D03A49C15dE8AF54b313B0C9D4d1e489D600", "initialLockedBalance": "1249862822519364975935", - "deposit": "775105895383822296275" - }, - { - "addr": "0x9b78e16456c8C0A1FE386894c6f1E7F7C0104ADC", - "initialLockedBalance": "1000000000000000000000", - "deposit": "620152773103076320000" + "deposit": "765130807585730838328" }, { "addr": "0xD98f8EB41e46C5D22e6eD7A2fE720af3D8DBFcd6", - "initialLockedBalance": "74604454901819108700316", - "deposit": "46266159593206515671774" + "initialLockedBalance": "66904454901819108700316", + "deposit": "40957022393006518211295" }, { "addr": "0xBf1F678061DFca5Dee9D85796751D3bb2dc64DE6", - "initialLockedBalance": "2475233242348013353909", - "deposit": "1535022759319039446230" + "initialLockedBalance": "2547945659038579414017", + "deposit": "1559780549240667045495" }, { "addr": "0xC0F12799B8D3FA8810DfE1616095170C72117F8F", "initialLockedBalance": "6096614520309199098544", - "deposit": "3780832401310231227583" + "deposit": "3732175649532768655580" }, { "addr": "0x8eD607D5E14EEc65DbcFe015905E7c19d3Dbe600", - "initialLockedBalance": "39407794500000000000000", - "deposit": "24438853041051158936376" + "initialLockedBalance": "39896294500000000000000", + "deposit": "24423387495382672855367" }, { "addr": "0xE5bbc8C362EB53C6f7264C94d969B5a7962A11DF", "initialLockedBalance": "11790930224760000000000", - "deposit": "7312178076349792956425" + "deposit": "7218075297953623044183" }, { "addr": "0xBa9B359C89Bb8B8985b7BeDba7fF143abBD2dadD", "initialLockedBalance": "5287777839235049283919", - "deposit": "3279230090554608692859" + "deposit": "3237028620719022216232" }, { "addr": "0x13CC8E623098Bb7076a7ae179A2A309282428589", - "initialLockedBalance": "89840000000000000000000", - "deposit": "55714525135580376588800" + "initialLockedBalance": "90992000000000000000000", + "deposit": "55702738884180338313264" }, { "addr": "0x5aAF2c73342eEdb0B295f0DB7641FAB6e2e0ede7", - "initialLockedBalance": "11177220714563111217644", - "deposit": "6931584421721461684214" - }, - { - "addr": "0x88cafaD2072054b5a641150C8710062D11C296Ad", - "initialLockedBalance": "4960490823893811264302", - "deposit": "3076262140390110852616" + "initialLockedBalance": "12421230169425669515176", + "deposit": "7603927166650048058600" }, { "addr": "0x43F3D8909819B681aDB64c50EbcaEb77689A101B", - "initialLockedBalance": "9063225233738240554677", - "deposit": "5620584261960546940548" + "initialLockedBalance": "9163639294452615765232", + "deposit": "5609721809034954731572" }, { "addr": "0x2d1270896be64F2A3835CBb0528313511840AE02", - "initialLockedBalance": "2663650000000000000000", - "deposit": "1651869934076009239768" + "initialLockedBalance": "2787650000000000000000", + "deposit": "1706520793591582997395" }, { "addr": "0x28d5fdd7cD29f9676cc82f30ee4ff47C4aF3c5aB", "initialLockedBalance": "9230000000000000000000", - "deposit": "5724010095741394433600" + "deposit": "5650345963392216047910" }, { "addr": "0x9d8f0f4192643209F38f5E0D02E2504Eab6F15Ac", "initialLockedBalance": "10596676565182876169022", - "deposit": "6571558357574542332903" + "deposit": "6486986853245282483395" }, { "addr": "0x9d7f41108Cd351AEE210082a41896Af822F81156", "initialLockedBalance": "2184748060000000000000", - "deposit": "1354877567940566170151" + "deposit": "1337441211468036297916" }, { "addr": "0xD498265eb913f95BDd0618C67Fc41F82aC1F8E0E", "initialLockedBalance": "2406194461606211909460", - "deposit": "1492208167990356019983" + "deposit": "1473004459726258509271" }, { "addr": "0x3376E7f9510b566f8CC6AB9e4F4588d941A64685", "initialLockedBalance": "3000000000000000000000", - "deposit": "1860458319309228960000" + "deposit": "1836515481059225151000" }, { "addr": "0x516b55a1938C5306f2291fBd01C02C16B7E9B837", "initialLockedBalance": "5007812741016906817987", - "deposit": "3105608958522552511650" + "deposit": "3065641875041060506578" }, { "addr": "0x7bd70c6462220072cEd0E7873a98CF21aAA952dA", "initialLockedBalance": "6297877657280000000000", - "deposit": "3905646293826097690162" + "deposit": "3855383271803908368970" }, { "addr": "0x26532eC1bb6b115a8Ae697be63D47122De02fCa7", "initialLockedBalance": "22733003153052279993119", - "deposit": "14097934946326349159270" - }, - { - "addr": "0x5D9A3E0Cb733d566FA887b4b74776A8cF9250640", - "initialLockedBalance": "287024310000000000000", - "deposit": "177998921794497039625" - }, - { - "addr": "0x9D1B637E76c0192b11aac1c59666866a8044f83d", - "initialLockedBalance": "446950120000000000000", - "deposit": "277177356356752733593" + "deposit": "13916504073849563384710" }, { "addr": "0xa0Ea24593C1571fCcea113Fe7eC1e8dc81191025", "initialLockedBalance": "3700000000000000000000", - "deposit": "2294565260481382384000" + "deposit": "2265035759973044352900" }, { "addr": "0x1cE7260e0c5776A2834892e4452bdB099D6f0713", "initialLockedBalance": "43659039111640240367762", - "deposit": "27075274176099364728818" - }, - { - "addr": "0xefC17Ff5dB1FbbF77304aB3423faab05BAA21d8C", - "initialLockedBalance": "732170000000000000000", - "deposit": "454057255882879389214" + "deposit": "26726833738899167307285" }, { "addr": "0x0c9fCE6d71774709Ea41CAD8c55e171D5477DC18", "initialLockedBalance": "10282263191686831069699", - "deposit": "6376574032100276686526" - }, - { - "addr": "0x4Bb93141ceAFb41856695cC4fC2c07f3a45A5265", - "initialLockedBalance": "755139560000000000000", - "deposit": "468301892213836886931" + "deposit": "6294511843952768117827" }, { "addr": "0x6Da70176136DaE6eFA25A3399bdA5aEC78215723", "initialLockedBalance": "17075770306076350632861", - "deposit": "10589586308184415159004" + "deposit": "10453305506040213793350" }, { "addr": "0xE68E072002B084EB674d4263aE6e992204705fB7", "initialLockedBalance": "1614550204755241657412", - "deposit": "1001267786793102793690" + "deposit": "988382148660114366468" }, { "addr": "0x1cC43840c765f71d4B419944eA8CebA75eb6DFB0", "initialLockedBalance": "2500000000000000000000", - "deposit": "1550381932757690800000" + "deposit": "1530429567549354292500" }, { "addr": "0x6db80dCeB07984e36D6CB97EDeBCC34013fDa1a1", - "initialLockedBalance": "4994201825300195752523", - "deposit": "3097168111396361898859" + "initialLockedBalance": "17906842555414252576213", + "deposit": "10962064523302803559512" + }, + { + "addr": "0xf2608E4Ea9e2cf9415Cbbc93610E63a068C2357c", + "initialLockedBalance": "1664328504317590735119", + "deposit": "1018855021249133610883" + }, + { + "addr": "0xd858d1d1bcD52A37391064474375Eb601e17bc42", + "initialLockedBalance": "23083830817942002710430", + "deposit": "14131270886434174634566" + }, + { + "addr": "0xFA0eF1B3013b3c1B3228a0a689eddB80c140c46F", + "initialLockedBalance": "1500000000000000000000", + "deposit": "918257740529612575500" } ] \ No newline at end of file diff --git a/data/stakers.json b/data/stakers.json index 72281ab..09fa5a8 100644 --- a/data/stakers.json +++ b/data/stakers.json @@ -1,12 +1,4 @@ [ - { - "address": "0xA29DbaA84a9949A0A38a2Ba07E0b75e6603934DB", - "balance": "222061659733700101062" - }, - { - "address": "0xe9B4aA5906C6e842e52aE7B7ab4dec3EE52362cB", - "balance": "187871680391712414210" - }, { "address": "0x642df98E9d71Ba533dF7288512cF63D34a907659", "balance": "3274920890240498949168" @@ -19,46 +11,18 @@ "address": "0xBFb910652F850F85E3F85AA0C12aE8f4037095b0", "balance": "18064223509187007832993" }, - { - "address": "0xe2506955723C01dDd6e619dD0829e28F76328c41", - "balance": "369300000000000000000" - }, - { - "address": "0x3Df488Bd07C2082E84B1CD63F343Cf3d538342bA", - "balance": "268606679563771005193" - }, { "address": "0x92F82EF0D08d8ADa7f542fC300adfd0b712b5963", - "balance": "3614275869036584865053" + "balance": "3697937593601682896111" }, { "address": "0x65C6AA5521F9b149E918A9A44A44FD651dF0AFF3", "balance": "1337537896786103209588" }, - { - "address": "0x25713B024a8004727Ba79c43647a77c7447948dB", - "balance": "327316949018727268744" - }, - { - "address": "0xB157ba30e3467DdBC844f14F02b4ba741f1d549F", - "balance": "300000008217141924923" - }, { "address": "0x83c418D2eD6670785330B996b47a18492b61e218", "balance": "24604927081108500781847" }, - { - "address": "0x39978cc40e2D1d7E127050bDFFFBB0dFcfaEbAd0", - "balance": "407032960152083087629" - }, - { - "address": "0x1d7979F557BA38892f25D3d54Fa6C1D75a4CfA27", - "balance": "176136388919542490495" - }, - { - "address": "0x9433ea2C250D84d3fD6398699D48728fa610569A", - "balance": "320126637964798831618" - }, { "address": "0xF99d1946Bf038a1205d430Ec91401E760e5F8F6F", "balance": "37075508978146311050113" @@ -73,100 +37,24 @@ }, { "address": "0xeE1D1ac27A80De54F0ba92b2E25EBb3418495db2", - "balance": "2331546926022547020105" - }, - { - "address": "0xefe8Aa053Ef0C9F1879911ef1C83Da08AD385164", - "balance": "306015687989988508846" - }, - { - "address": "0x238926025E84475e3182774df480021470f8F978", - "balance": "119748510011508001412" - }, - { - "address": "0x0c3a4a0ed70fDB29860760b5ca78B116Fe77DE00", - "balance": "140306615000000000000" - }, - { - "address": "0x54F2f104Fb6ABf1a6991150B27662Aade958A338", - "balance": "319349649026838373837" - }, - { - "address": "0x327346e623A4334f7c4034D5a73Ac636d33a31c0", - "balance": "304751021776330822150" - }, - { - "address": "0xeafa6FbaebB26F9d07B42f3Fd8906818CE75026F", - "balance": "922236496491056455335" + "balance": "2616085853090372402156" }, { "address": "0xe443cbad516eE9b00A2CbE7F884A4bb314776dE3", - "balance": "64680368781627387285673" - }, - { - "address": "0x2D56db2f95Ae61c2396d30ABEa61fc91E506943F", - "balance": "135065031612858769227" - }, - { - "address": "0xc7557AfDB4C2EF7E2A5e68ed60B1f8AC41c87459", - "balance": "100170264404649634361" - }, - { - "address": "0x6eA8BfAa4697187D3BB1E27688931d73BcbbEC0b", - "balance": "439287784325687715732" - }, - { - "address": "0xE0a9Cf94C4c41a7709B55D9bA37D788A8DF19F9E", - "balance": "118418383918603784875" - }, - { - "address": "0x06F166E11d765aE936E7ec36777E1b4B6f0Cb83B", - "balance": "180305703889462319555" - }, - { - "address": "0x1023aE712D5F219e9166a9D286e183226DFAafa6", - "balance": "143712248142294445923" - }, - { - "address": "0x75F3fC9189fd3228a4178e544CdE26b75Da81Bf3", - "balance": "547090923569720095523" - }, - { - "address": "0x90e14E059B28Af64B52d4Da0442b22052f507eF1", - "balance": "906706256793263291165" - }, - { - "address": "0x344651A2445484bd2928eB46D2610DaaC1B42A66", - "balance": "244547007283286030643" + "balance": "67999143733426979646229" }, { "address": "0x2490419318b3F69e8dc209604056f40Eb350d0d7", "balance": "1641166788776420175594" }, - { - "address": "0x4aAE2d5072385b02465263d5feb91bb1995D4f37", - "balance": "133266200000000000000" - }, { "address": "0x0df59978Cc975e27C5E4e19d355e025F0770F088", "balance": "1278073898007810414591" }, - { - "address": "0x85e6C3c83929eE45712EFF4F89c5E74cCddB5D41", - "balance": "220168850000000000000" - }, - { - "address": "0xC346A5dc3b3821AEeF3f3fFB70989631521E41cD", - "balance": "224707550488945833056" - }, { "address": "0x5d17B355538A9ea9b45A0018e11b36947fC16376", "balance": "3461949885239649131822" }, - { - "address": "0xAaF7168Bae99a4860D7729745B22C4b48d1f9Adb", - "balance": "100475944611586099877" - }, { "address": "0xB835b4e277094D4AF9Fbb66e9f5Db9e6E8dC65dB", "balance": "2499187111378392690208" @@ -175,78 +63,18 @@ "address": "0x42DbF634c256acd17beDDC1330488F1BEa7B8BDf", "balance": "6877216358537763535178" }, - { - "address": "0xE7304bA0f157f2Ade94015934284b6704BC72911", - "balance": "112608649098976008132" - }, { "address": "0x3eE9378Fb0809a243FcF7C30865941675d766D71", "balance": "2774004155905058916423" }, - { - "address": "0x81348BB6CFA32662cE76aE5FcC8c54F056CE7042", - "balance": "100400761930000000000" - }, { "address": "0x06981EfbE070996654482F4F20786e0CEf0f8740", - "balance": "32754177841356351554810" - }, - { - "address": "0x92e74E50edCE4573d181C03cA889f72640cD3a94", - "balance": "407199993263279657437" - }, - { - "address": "0x3dD44f129563787449367046c9cBF5610f21467f", - "balance": "196204479061497808556" - }, - { - "address": "0x0A54cf15a8719DB69B5cC40d797a213ca9407B8E", - "balance": "370960788258305263912" - }, - { - "address": "0x95880f2E70203f759168665Feb6948E81Fe5dF77", - "balance": "294020437588528361099" - }, - { - "address": "0x0050faCd2C04930257438b213FE9E132a26E5a29", - "balance": "119786423000000000000" - }, - { - "address": "0x1d14080067dE02E048DdE58a936b4EBED7ee56e4", - "balance": "135408011012662929013" - }, - { - "address": "0xbb6d1648A8BeF51603Badd347Dc91eb7D04a43e5", - "balance": "961751770023408248012" + "balance": "43121397719834144990842" }, { "address": "0xD7b2879C8922cd704E41E8CC1f18f6994D6B7C36", "balance": "1119299000000000000000" }, - { - "address": "0x7a628E9bCC082844797C37c79084ed6BC99e6Abc", - "balance": "138985632834248119775" - }, - { - "address": "0xDaa5C5a5B6725666B1e37B14dc8e1FCB446c5952", - "balance": "119080000000000000000" - }, - { - "address": "0x5dab475E601D55efa2290D27333913e025C7Bd89", - "balance": "146964212351551947890" - }, - { - "address": "0x4051e1fcD4Be1366a0CDcfA47ca717868A96575E", - "balance": "561299291075539499694" - }, - { - "address": "0xB3AAd889bf41Ec39571aFa78aa5D9A26a05DDaAb", - "balance": "208128000000000000000" - }, - { - "address": "0x4303Ddc9943D862f2B205aF468a4A786c5137E76", - "balance": "121978258758390804343" - }, { "address": "0xa1eBC8bdE2F1F87fe24F384497b6bD9cE3B14345", "balance": "2984693312345136089833" @@ -255,102 +83,26 @@ "address": "0xaf095d9cedBc20c8Bb0A75ED9509c1f31DC4E7E6", "balance": "4411294324551597847209" }, - { - "address": "0x4839460F05b2a8fC1b615e0523EbC46eFba75420", - "balance": "147677697371346056769" - }, - { - "address": "0x6b69c30354Cef94ee9d77DBC7BD268B4A6683825", - "balance": "215671961915475600719" - }, - { - "address": "0x1CE7DC66CC98c61A573105514d073D64a9a8608f", - "balance": "183302847714096393245" - }, { "address": "0x0d4E989c7620C8749c9417d2BF218896C767B606", "balance": "11111000000000000000000" }, - { - "address": "0x4963C9C61f48272969587c27aA4e6384798d48cA", - "balance": "646591448141274005553" - }, - { - "address": "0x6fb4becf05497b79F0fCF61CfA5075efAA137DDF", - "balance": "118347626348277285232" - }, - { - "address": "0x6f9BB7e454f5B3eb2310343f0E99269dC2BB8A1d", - "balance": "554530214763375646077" - }, - { - "address": "0xb4e39F6D3d386E98AF0C064E087aCBC9A8F08944", - "balance": "147140882538472853905" - }, - { - "address": "0x2462375371935c8122895e701380A06CE815B0FD", - "balance": "214282527968312078762" - }, - { - "address": "0x24f04EC62597C11752c47448228B63052ED3158a", - "balance": "321761894521216575819" - }, - { - "address": "0x8904FFC6Aa039dB5941De11309a42372F3F7D2FD", - "balance": "296350209248534143997" - }, - { - "address": "0xa729adDeFe1fa7BCe87053ed55D55EDdDD13De60", - "balance": "105257962571588444433" - }, - { - "address": "0x9265f86d58b348060E43216f968bda8A6Bb63572", - "balance": "462054994392400414840" - }, - { - "address": "0xcE1fFD4cfE424757D6e597293566195Fba6f4cD8", - "balance": "378325759765781498396" - }, { "address": "0x2E63Dbd91657dc5fa97213Ba6a1AEb5f194805F6", "balance": "1200089842937217922038" }, - { - "address": "0x4273397532A8dF43a6607C4441e3EB6edF63acf3", - "balance": "150000000000000000037" - }, { "address": "0xC68c10C524eC53A284FB76a91b2e97F15Fe79634", "balance": "1295708210000000000000" }, - { - "address": "0x12168AEa666Be756E1aD0595fEd9C306442a4103", - "balance": "129858882018647549604" - }, - { - "address": "0xE70eF2B9A263855535727Ee014C6Ffaf01881Ae3", - "balance": "126263397985613051754" - }, { "address": "0x5Fc0A53A7e33Aa6E41A93b718DD2216707251fC2", "balance": "1216512730000000000000" }, - { - "address": "0x18F516dD6D5F46b2875Fd822B994081274be2a8b", - "balance": "808879218854315691416" - }, { "address": "0x7803Ab56769dDa5432CDbd63749a6BEeb3180008", "balance": "1000020482341666374383" }, - { - "address": "0x4F50d47D20380172746527bbeAa274940C38EFAC", - "balance": "489392817721401322749" - }, - { - "address": "0xFeAe121618049802Ccb40f094536a7B186642699", - "balance": "748171152585153967146" - }, { "address": "0x069Dd24FC8ABEC3708841a4726617c17BC74d5eC", "balance": "4465692444586264801956" @@ -363,129 +115,37 @@ "address": "0x26D3b88d464A575784Be70Edc5F9290dC5e296DB", "balance": "4584368997732369384071" }, - { - "address": "0x7Abbdbd51813d85B448F887b946719Dd2B09D6F7", - "balance": "477257927573167840914" - }, { "address": "0xEb89EfE3Ed80288E310c5529e1E242b4ab56E196", "balance": "1300090776209185468018" }, - { - "address": "0xAD142B79f2500Bf194C174f06C7dC901A2CdA74f", - "balance": "174034164798218427885" - }, - { - "address": "0x4fFDAeB9f4ec23254B6DFA41eEeF2C8d23f8c554", - "balance": "131502368878796458509" - }, - { - "address": "0xb03384cA294C06E8d04B08412E8467ff2363E5E3", - "balance": "906139663513082751610" - }, - { - "address": "0x6A3738c6299f45c31697aceA647D49EdCC9C28A4", - "balance": "426032828677716268597" - }, - { - "address": "0xc74d1af789F5A0223448Db69a1B56c84845e17d5", - "balance": "386136667062531373859" - }, - { - "address": "0xDf90418385aF4E9833603069DEaF7C71d76f83a2", - "balance": "683465828138249494426" - }, - { - "address": "0x16eb5Fbb2a5c7dAbC2c7688482378e89471d5724", - "balance": "251802411781229744678" - }, { "address": "0x356eE97D7D560af2E97E9f9EEe56b2e09D60e6F5", "balance": "10836062927446519092234" }, - { - "address": "0x21c756E2c7B898BDa8a3b2A77e4C56D855Ab9414", - "balance": "261098218101404112455" - }, - { - "address": "0xFB96D60ce3ee83ed4BC71c6E0da10C537601b77C", - "balance": "446702746160587197664" - }, - { - "address": "0xeb0fCD59212E521918b514c64313eF5a3dd101f8", - "balance": "100240415124564555330" - }, - { - "address": "0x34DF0B83cf4F30683f8AB2Ac971a52A5f663FEb4", - "balance": "116124431887044456353" - }, { "address": "0xF2Ba32f180B243D3138DEd0E1F1BdbdcCBCE0702", "balance": "1482848214495146566693" }, - { - "address": "0xbC063735a5b8bdd12611157E7E0F29D1570D892D", - "balance": "509451890000000000000" - }, - { - "address": "0xe7c724F87EcFf8E2f563962f96b6c291cBD729cF", - "balance": "250243001109044335565" - }, { "address": "0x1fe7d323946A7C3B644528baA42eFf13056cd2B4", "balance": "2012288953464165015019" }, { "address": "0x48c0477Bf79a59e505d26eB33c5b331502a511B2", - "balance": "11028610297596262814514" + "balance": "11808140176616152755130" }, { "address": "0xE5A5BfC1772D4A2b44Add05aae63026A89486C1B", "balance": "2897272017864013753943" }, - { - "address": "0x00377B2FC0044Dec6507855eDd6531aF1755cCe4", - "balance": "942500316330675833924" - }, - { - "address": "0xD9D10dc5609d77F2A15FAa68414835A6ed19269B", - "balance": "604677796610747756803" - }, - { - "address": "0xdF20a1124d6B44e19ad75675a622d9c9669E59B6", - "balance": "720900000000000000000" - }, - { - "address": "0xF4d2D64D1f9190A9daB0960c80e5C73c04710184", - "balance": "630536604758334996358" - }, - { - "address": "0xf68de31d7fC80A70959966F9Aa78e86A7b418A10", - "balance": "100424753924039137153" - }, { "address": "0x47B9cCa44fe405D12ff56aaCd1Df6dbA4A79Ae28", "balance": "1198321376929923406445" }, - { - "address": "0x71917F124be5C0Cd97aDBE7AB472f4C82577B542", - "balance": "171985544540000000000" - }, - { - "address": "0x2a2a1FB6382a528F1B23E76d3Ed6F4C17A9e5966", - "balance": "679861011890874134021" - }, { "address": "0x343F48B346b0cE11342ffdEDaDAC4135E1FD525a", - "balance": "1112013784183226328856" - }, - { - "address": "0x958622B4631212DC751c5B1Ba45013c833Dcb86c", - "balance": "1000000000000000000000" - }, - { - "address": "0x0F46576F3b8b0ed6522e4b200Df53ac73251b911", - "balance": "440579268126896398907" + "balance": "1244831656243158248642" }, { "address": "0xaAaC34d30d6938787c653AAfB922bc20bFa9C512", @@ -495,10 +155,6 @@ "address": "0x758aB8aC42a8c44dF8C31129Db146c65c2669391", "balance": "9999580000000000000000" }, - { - "address": "0x149da2CB603A8818Fb2d703D72D46390Cd09A6D9", - "balance": "351315917791207543375" - }, { "address": "0xC2e6B265cb965DED721566f0f9Eb5ab1A6162A21", "balance": "2004486788385385993147" @@ -517,11 +173,11 @@ }, { "address": "0xddbc1841BE23b2ab55501Deb4d6bc39E3f8AA2d7", - "balance": "48363478557462694029018" + "balance": "49454261304684065909473" }, { "address": "0x7b5edF38D955dd9deC103aF05c2D68B28e02Ad90", - "balance": "29597872806644626228418" + "balance": "30721199782932567542900" }, { "address": "0xE4143f6377AEcd7193b9731d1C28815b57C4f5Ab", @@ -535,13 +191,9 @@ "address": "0xa39fE8D3094e2D69Bd579Dc2bc2fc44Feb54Fc57", "balance": "62364443294474230012244" }, - { - "address": "0x6f4CbC2E042ed0D1Df4bf14d00eEb52Ff1E0e5F8", - "balance": "632357477375385036674" - }, { "address": "0x92374BA66EE27f207F9efff0837FF6D707006304", - "balance": "26511566449802577442283" + "balance": "27582360269943737743173" }, { "address": "0x9Ff3C1Bea9ffB56a78824FE29f457F066257DD58", @@ -549,11 +201,7 @@ }, { "address": "0x94596B6A626392F5D972D6CC4D929a42c2f0008c", - "balance": "6237585974021878690758" - }, - { - "address": "0x065f2A0eF62878e8951af3c387E4ddC944f1B8F4", - "balance": "289834051536966486101" + "balance": "6435143032935074622460" }, { "address": "0x7C199A0f301913212cfAB3756c3ed8F5B8927713", @@ -585,7 +233,7 @@ }, { "address": "0xBEF6d320Ed305BC9a0977D312c0c1BF9f56749D4", - "balance": "16792018296955216982422" + "balance": "17647018296955216982422" }, { "address": "0x6e1Ea6FCEE2221844950FB269780BB450f47b6Ee", @@ -601,7 +249,7 @@ }, { "address": "0xfA9330bb565c2F502D371a96A9F43D9182D732c9", - "balance": "2932970328956661635966" + "balance": "3346805409290437403641" }, { "address": "0x09AdFab2635dcb681FADA41CeB0bfa6f52EFfd97", @@ -613,7 +261,7 @@ }, { "address": "0xeb3E49Af2aB5D5D0f83A9289cF5a34d9e1f6C5b4", - "balance": "1011706736327691989355" + "balance": "4736654395057849473603" }, { "address": "0xD97938E0EAa80d8801174e6cF3E7155C872aDdcD", @@ -629,7 +277,7 @@ }, { "address": "0xef5031F705dfBD187B7F6A86f4173cB067afD1A9", - "balance": "42729083148460923251275" + "balance": "44126667450172916291870" }, { "address": "0xFB7c1D49e006eaDdff2385c7eF8B0C5Cf49d038A", @@ -639,25 +287,17 @@ "address": "0x0AD50B53b0c142432c5f6c5c1fA1e4bb03021374", "balance": "10000000000000000000000" }, - { - "address": "0xa99a29c335590685cCeaCeD2A0dBAf2C099CBeD9", - "balance": "170002896000000000000" - }, { "address": "0xa983D03A49C15dE8AF54b313B0C9D4d1e489D600", "balance": "1249862822519364975935" }, - { - "address": "0x9b78e16456c8C0A1FE386894c6f1E7F7C0104ADC", - "balance": "1000000000000000000000" - }, { "address": "0xD98f8EB41e46C5D22e6eD7A2fE720af3D8DBFcd6", - "balance": "74604454901819108700316" + "balance": "66904454901819108700316" }, { "address": "0xBf1F678061DFca5Dee9D85796751D3bb2dc64DE6", - "balance": "2475233242348013353909" + "balance": "2547945659038579414017" }, { "address": "0xC0F12799B8D3FA8810DfE1616095170C72117F8F", @@ -665,7 +305,7 @@ }, { "address": "0x8eD607D5E14EEc65DbcFe015905E7c19d3Dbe600", - "balance": "39407794500000000000000" + "balance": "39896294500000000000000" }, { "address": "0xE5bbc8C362EB53C6f7264C94d969B5a7962A11DF", @@ -677,23 +317,19 @@ }, { "address": "0x13CC8E623098Bb7076a7ae179A2A309282428589", - "balance": "89840000000000000000000" + "balance": "90992000000000000000000" }, { "address": "0x5aAF2c73342eEdb0B295f0DB7641FAB6e2e0ede7", - "balance": "11177220714563111217644" - }, - { - "address": "0x88cafaD2072054b5a641150C8710062D11C296Ad", - "balance": "4960490823893811264302" + "balance": "12421230169425669515176" }, { "address": "0x43F3D8909819B681aDB64c50EbcaEb77689A101B", - "balance": "9063225233738240554677" + "balance": "9163639294452615765232" }, { "address": "0x2d1270896be64F2A3835CBb0528313511840AE02", - "balance": "2663650000000000000000" + "balance": "2787650000000000000000" }, { "address": "0x28d5fdd7cD29f9676cc82f30ee4ff47C4aF3c5aB", @@ -727,14 +363,6 @@ "address": "0x26532eC1bb6b115a8Ae697be63D47122De02fCa7", "balance": "22733003153052279993119" }, - { - "address": "0x5D9A3E0Cb733d566FA887b4b74776A8cF9250640", - "balance": "287024310000000000000" - }, - { - "address": "0x9D1B637E76c0192b11aac1c59666866a8044f83d", - "balance": "446950120000000000000" - }, { "address": "0xa0Ea24593C1571fCcea113Fe7eC1e8dc81191025", "balance": "3700000000000000000000" @@ -743,18 +371,10 @@ "address": "0x1cE7260e0c5776A2834892e4452bdB099D6f0713", "balance": "43659039111640240367762" }, - { - "address": "0xefC17Ff5dB1FbbF77304aB3423faab05BAA21d8C", - "balance": "732170000000000000000" - }, { "address": "0x0c9fCE6d71774709Ea41CAD8c55e171D5477DC18", "balance": "10282263191686831069699" }, - { - "address": "0x4Bb93141ceAFb41856695cC4fC2c07f3a45A5265", - "balance": "755139560000000000000" - }, { "address": "0x6Da70176136DaE6eFA25A3399bdA5aEC78215723", "balance": "17075770306076350632861" @@ -769,6 +389,18 @@ }, { "address": "0x6db80dCeB07984e36D6CB97EDeBCC34013fDa1a1", - "balance": "4994201825300195752523" + "balance": "17906842555414252576213" + }, + { + "address": "0xf2608E4Ea9e2cf9415Cbbc93610E63a068C2357c", + "balance": "1664328504317590735119" + }, + { + "address": "0xd858d1d1bcD52A37391064474375Eb601e17bc42", + "balance": "23083830817942002710430" + }, + { + "address": "0xFA0eF1B3013b3c1B3228a0a689eddB80c140c46F", + "balance": "1500000000000000000000" } ] \ No newline at end of file diff --git a/hardhat.config.js b/hardhat.config.js index ad2af08..1175890 100644 --- a/hardhat.config.js +++ b/hardhat.config.js @@ -37,11 +37,12 @@ module.exports = { }, hardhat: { forking: { - url: "https://rpc.mevblocker.io/fast", + url: "https://rpc.mevblocker.io", enabled: true, - blockNumber: 19104883, + blockNumber: 19195278, accounts: [process.env.REAL_PK], }, + timeout: 100000000, chainId: 1, accounts: [ { diff --git a/package-lock.json b/package-lock.json index 24aa66c..3737211 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,17 +1,18 @@ { - "name": "proposal-45", + "name": "proposal-47", "version": "1.0.0", "lockfileVersion": 2, "requires": true, "packages": { "": { - "name": "proposal-45", + "name": "proposal-47", "version": "1.0.0", "license": "ISC", "dependencies": { "@openzeppelin/contracts": "^3.2.0-rc.0", "@openzeppelin/upgrades-core": "^1.30.1", "base58-solidity": "^1.0.2", + "bignumber.js": "^9.0.1", "content-hash": "^2.5.2", "torn-token": "^1.0.8" }, @@ -2504,9 +2505,9 @@ } }, "node_modules/bignumber.js": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.2.tgz", - "integrity": "sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.1.tgz", + "integrity": "sha512-IdZR9mh6ahOBv/hYGiXyVuyCetmGJhtYkqLBpTStdhEGjegpPlUawydyaF3pbIOFynJTpllEs+NP+CS9jKFLjA==", "engines": { "node": "*" } @@ -11906,9 +11907,9 @@ "integrity": "sha512-jOTSb+drvEDxEq6OuUybOAv/xxoh3cuYRUIPyu8sSHQNKM303UQ2R1DAo45o1AkcIXw6fzbaFI1+xGGdaXs2lg==" }, "bignumber.js": { - "version": "9.1.2", - "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.2.tgz", - "integrity": "sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==" + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.1.tgz", + "integrity": "sha512-IdZR9mh6ahOBv/hYGiXyVuyCetmGJhtYkqLBpTStdhEGjegpPlUawydyaF3pbIOFynJTpllEs+NP+CS9jKFLjA==" }, "binary-extensions": { "version": "2.2.0", diff --git a/package.json b/package.json index 80b11f3..d1fdd69 100644 --- a/package.json +++ b/package.json @@ -39,6 +39,7 @@ "@openzeppelin/contracts": "^3.2.0-rc.0", "@openzeppelin/upgrades-core": "^1.30.1", "base58-solidity": "^1.0.2", + "bignumber.js": "^9.0.1", "content-hash": "^2.5.2", "torn-token": "^1.0.8" } diff --git a/scripts/deploy.js b/scripts/deploy.js index 4d07dbe..5c159cb 100644 --- a/scripts/deploy.js +++ b/scripts/deploy.js @@ -8,25 +8,43 @@ const hre = require("hardhat"); const { ethers } = require("hardhat"); async function main() { + const airdropRecipients = [...require("../data/airdropRecipients.json")]; + const recipientsFactory = await ethers.getContractFactory("AirdropRecipients"); + const airdropRecipientsContract = await recipientsFactory.deploy(airdropRecipients); + const recipientStorageAddr = await airdropRecipientsContract.getAddress(); + + let tx = airdropRecipientsContract.deploymentTransaction(); + await tx.wait(16); + console.log("Aidrop recipients contract confirmed with 16 blocks, waiting for verification on Etherscan"); + await hre.run("verify:verify", { + address: recipientStorageAddr, + contract: "contracts/AirdropRecipients.sol:AirdropRecipients", + constructorArguments: [airdropRecipients], + }); + const airdropFactory = await ethers.getContractFactory("SablierAirdrop"); const airdrop = await airdropFactory.deploy(); const airdropAddr = await airdrop.getAddress(); - let tx = airdrop.deploymentTransaction(); + + tx = airdrop.deploymentTransaction(); await tx.wait(16); console.log("Aidrop deployment confirmed with 16 blocks, waiting for verification on Etherscan"); await hre.run("verify:verify", { - address: governanceImplAddr, + address: airdropAddr, contract: "contracts/Airdrop.sol:SablierAirdrop", - constructorArguments: [stakingAddr, gasCompensationAddr, userVaultAddr], }); const proposalFactory = await ethers.getContractFactory("Proposal"); - const proposal = await proposalFactory.deploy(airdropAddr); + const proposal = await proposalFactory.deploy(airdropAddr, recipientStorageAddr); const deployedProposalAddr = await proposal.getAddress(); + tx = proposal.deploymentTransaction(); + await tx.wait(16); + console.log("Proposal deployment confirmed with 16 blocks, waiting for verification on Etherscan"); await hre.run("verify:verify", { - address: "0xc4217881856cA15c320B32A87F9ab3Ed17a5A9d0", + address: deployedProposalAddr, contract: "contracts/Proposal.sol:Proposal", + constructorArguments: [airdropAddr, recipientStorageAddr], }); } @@ -35,4 +53,4 @@ async function main() { main().catch((error) => { console.error(error); process.exitCode = 1; -}); \ No newline at end of file +}); diff --git a/scripts/findStakers.js b/scripts/findStakers.js index 6236d66..5a4311a 100644 --- a/scripts/findStakers.js +++ b/scripts/findStakers.js @@ -24,7 +24,7 @@ async function main() { allStakers.push(...resultsPart); } - const result = allStakers.filter((staker) => staker.balance > 100n * 10n ** 18n); + const result = allStakers.filter((staker) => staker.balance > 1000n * 10n ** 18n); fs.writeFileSync("data/stakers.json", JSON.stringify(result, null, 4), { encoding: "utf-8" }); } diff --git a/test/Governance.js b/test/Governance.js new file mode 100644 index 0000000..468ac67 --- /dev/null +++ b/test/Governance.js @@ -0,0 +1,358 @@ +const { ethers, network } = require("hardhat"); +const { time } = require("@nomicfoundation/hardhat-toolbox/network-helpers"); +const { expect } = require("chai"); +const { + deployAndExecuteProposal, + getProxyImplAddr, + governanceAddr, + resetStateBeforeProposal, + getManyEth, + resolveAddr, + getTorn, + getGovernance, + getPermitSignature, + tornAddr, + stakingAddr, + executeNewProposal, + signerLockInGov, +} = require("./utils"); + +// comment some checks if your proposal changes something +describe("All Governance checks", function () { + beforeEach(resetStateBeforeProposal); + + it("Governance implementation should be a valid contract", async function () { + await deployAndExecuteProposal(); + const governanceImplAddr = await getProxyImplAddr(governanceAddr); + const code = await ethers.provider.getCode(governanceImplAddr); + expect(code).to.not.be.equal("0x"); + }); + + async function createValidProposal() { + // this proposal changes governance impl addr to old governance impl 0xBa178126C28F50Ee60322a82f5EbCd6b3711e101 + const proposalBytecode = + "0x608060405234801561001057600080fd5b50610161806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063373058b814610030575b600080fd5b61003861003a565b005b735efda50f22d34f262c29268506c5fa42cb56a1ce73ffffffffffffffffffffffffffffffffffffffff16633659cfe673ba178126c28f50ee60322a82f5ebcd6b3711e1016040518263ffffffff1660e01b815260040161009b9190610110565b600060405180830381600087803b1580156100b557600080fd5b505af11580156100c9573d6000803e3d6000fd5b50505050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006100fa826100cf565b9050919050565b61010a816100ef565b82525050565b60006020820190506101256000830184610101565b9291505056fea264697066735822122071ee22910809ebd1174acbe4a8ce386abb553bbc1cf37fd7c9abb166b18ca6f664736f6c63430008140033"; + const signer = (await ethers.getSigners())[0]; + const proposalAbi = ["function executeProposal()"]; + const proposalFactory = new ethers.ContractFactory(proposalAbi, proposalBytecode, signer); + const proposalContract = await proposalFactory.deploy(); + const proposalAddr = await proposalContract.getAddress(); + + return proposalAddr; + } + + it("Governance contract should be updatable", async function () { + const someOldGovernanceImpl = "0xBa178126C28F50Ee60322a82f5EbCd6b3711e101"; + await deployAndExecuteProposal(); + expect(await getProxyImplAddr(governanceAddr)).to.be.not.equal(someOldGovernanceImpl); + const proposalAddr = await createValidProposal(); + + await executeNewProposal(proposalAddr); + + const governance = await getGovernance(); + const lastProposalId = await governance.proposalCount(); + expect(await governance.state(lastProposalId)).to.be.equal(5); // executed + expect(await getProxyImplAddr(governanceAddr)).to.be.equal(someOldGovernanceImpl); + }); + + it("Proposal count should change by one", async function () { + const governance = await getGovernance(); + const lastProposal = await governance.proposalCount(); + await deployAndExecuteProposal(); + expect(await governance.proposalCount()).to.be.equal(lastProposal + 1n); + }); + + it("Stakers should be able to lock and unlock", async function () { + const signer = (await ethers.getSigners())[0]; + const governanceSigner = await ethers.getImpersonatedSigner(governanceAddr); + const governance = await getGovernance(signer); + const torn = await getTorn(governanceSigner); + const thousandTorns = 1000n * 10n ** 18n; + const balanceBefore = await torn.balanceOf(signer.address); + const lockedBalanceBefore = await governance.lockedBalance(signer.address); + + await deployAndExecuteProposal(); + + await torn.transfer(signer.address, thousandTorns); + const deadline = ethers.MaxUint256; + const { v, r, s } = await getPermitSignature(signer, torn, governanceAddr, thousandTorns, deadline); + await governance.lock(signer.address, thousandTorns, deadline, v, r, s); + const lockedBalanceAfter = await governance.lockedBalance(signer.address); + expect(lockedBalanceAfter - lockedBalanceBefore).to.be.equal(thousandTorns); + await governance.unlock(thousandTorns); + const balanceAfter = await torn.balanceOf(signer.address); + expect(balanceAfter - balanceBefore).to.be.equal(thousandTorns); + }); + + it("Staker locked balance should not change", async function () { + const me = await resolveAddr("butterfly-attractor.eth"); + const governance = await getGovernance(); + const lockedBalanceBefore = await governance.lockedBalance(me); + await deployAndExecuteProposal(); + expect(await governance.lockedBalance(me)).to.be.equal(lockedBalanceBefore); + }); + + it("Proposals info should not change", async function () { + const governance = await getGovernance(); + const lastProposal = await governance.proposalCount(); + const proposalsBefore = await Promise.all( + Array.from({ length: Number(lastProposal) - 1 }, (_, i) => i + 1).map((i) => governance.proposals(i)), + ); + await deployAndExecuteProposal(); + const proposalsAfter = await Promise.all( + Array.from({ length: Number(lastProposal) - 1 }, (_, i) => i + 1).map((i) => governance.proposals(i)), + ); + expect(proposalsAfter).to.deep.equal(proposalsBefore); + }); + + it("Proposals state should not change", async function () { + const governance = await getGovernance(); + const lastProposal = await governance.proposalCount(); + const proposalStatesBefore = await Promise.all( + Array.from({ length: Number(lastProposal) - 1 }, (_, i) => i + 1).map((i) => governance.state(i)), + ); + await deployAndExecuteProposal(); + const proposalStatesAfter = await Promise.all( + Array.from({ length: Number(lastProposal) - 1 }, (_, i) => i + 1).map((i) => governance.state(i)), + ); + expect(proposalStatesAfter).to.deep.equal(proposalStatesBefore); + }); + + it("Quorum votes should not change", async function () { + const governance = await getGovernance(); + const quorum = await governance.QUORUM_VOTES(); + await deployAndExecuteProposal(); + expect(await governance.QUORUM_VOTES()).to.be.equal(quorum); + }); + + it("Closing period should not change", async function () { + const governance = await getGovernance(); + const closingPeriod = await governance.CLOSING_PERIOD(); + await deployAndExecuteProposal(); + expect(await governance.CLOSING_PERIOD()).to.be.equal(closingPeriod); + }); + + it("Execution delay should not change", async function () { + const governance = await getGovernance(); + const executionDelay = await governance.EXECUTION_DELAY(); + await deployAndExecuteProposal(); + expect(await governance.EXECUTION_DELAY()).to.be.equal(executionDelay); + }); + + it("Execution expiration should not change", async function () { + const governance = await getGovernance(); + const expirationPeriod = await governance.EXECUTION_EXPIRATION(); + await deployAndExecuteProposal(); + expect(await governance.EXECUTION_EXPIRATION()).to.be.equal(expirationPeriod); + }); + + it("Proposal initiation threshold should not change", async function () { + const governance = await getGovernance(); + const proposalThreshold = await governance.PROPOSAL_THRESHOLD(); + await deployAndExecuteProposal(); + expect(await governance.PROPOSAL_THRESHOLD()).to.be.equal(proposalThreshold); + }); + + it("Voting extend time should not change", async function () { + const governance = await getGovernance(); + const votingExtendTime = await governance.VOTE_EXTEND_TIME(); + await deployAndExecuteProposal(); + expect(await governance.VOTE_EXTEND_TIME()).to.be.equal(votingExtendTime); + }); + + it("Voting initiation delay should not change", async function () { + const governance = await getGovernance(); + const proposalVotingDelay = await governance.VOTING_DELAY(); + await deployAndExecuteProposal(); + expect(await governance.VOTING_DELAY()).to.be.equal(proposalVotingDelay); + }); + + it("Voting period should not change", async function () { + const governance = await getGovernance(); + const votingPeriod = await governance.VOTING_PERIOD(); + await deployAndExecuteProposal(); + expect(await governance.VOTING_PERIOD()).to.be.equal(votingPeriod); + }); + + it("User vault address should not change", async function () { + const governance = await getGovernance(); + const vaultAddr = await governance.userVault(); + const vaultCode = await ethers.provider.getCode(vaultAddr); + expect(vaultCode).to.be.not.equal("0x"); + await deployAndExecuteProposal(); + + expect(await governance.userVault()).to.be.equal(vaultAddr); + expect(await ethers.provider.getCode(vaultAddr)).to.be.equal(vaultCode); + }); + + it("Torn address should not be reinitialized", async function () { + const governanceContract = await getGovernance(); + await deployAndExecuteProposal(); + expect(await governanceContract.torn()).to.be.equal(tornAddr); + }); + + it("Staking address should not change", async function () { + const governanceContract = await getGovernance(); + await deployAndExecuteProposal(); + expect(await governanceContract.Staking()).to.be.equal(stakingAddr); + }); + + it("Gas compensator address should not change", async function () { + const governance = await getGovernance(); + const gasCompensatorAddr = await governance.gasCompensationVault(); + await deployAndExecuteProposal(); + expect(await governance.gasCompensationVault()).to.be.equal(gasCompensatorAddr); + }); + + async function delegate(tornAmount, signer) { + const governance = await getGovernance(); + if (!tornAmount) tornAmount = await governance.QUORUM_VOTES(); + if (!signer) signer = (await ethers.getSigners())[0]; + const governanceContract = await getGovernance(signer); + const zer0 = "0x000000000000000000000000000000000000dEaD"; + await signerLockInGov(tornAmount, signer); + await governanceContract.delegate(zer0); + + return { signer, delegated: await ethers.getImpersonatedSigner(zer0), governance: governanceContract }; + } + + it("Delegators state should not change", async function () { + await deployAndExecuteProposal(); + const { signer, governance, delegated } = await delegate(); + expect(await governance.delegatedTo(signer.address)).to.be.equal(delegated.address); + }); + + it("Delegation should work", async function () { + await deployAndExecuteProposal(); + const { signer, governance, delegated } = await delegate(); + expect(await governance.delegatedTo(signer.address)).to.be.equal(delegated.address); + }); + + it("Delegator should be able to cast vote", async function () { + await deployAndExecuteProposal(); + const proposalAddr = await createValidProposal(); + const gov = await getGovernance(); + await gov.propose(proposalAddr, ""); + const { governance, delegated, signer } = await delegate(); + const proposalId = await governance.proposalCount(); + await time.increase(60 * 60); + const governanceDelegated = governance.connect(delegated); + await governanceDelegated.castDelegatedVote([signer.address], proposalId, true); + await time.increase(60 * 60 * 24 * 7 + 60); + + expect(await governance.state(proposalId)).to.be.equal(4); // awaiting execution + }); + + it("Delegator should be able to propose", async function () { + await deployAndExecuteProposal(); + const { governance, delegated, signer } = await delegate(); + const proposalAddr = await createValidProposal(); + const governanceDelegated = governance.connect(delegated); + await governanceDelegated.proposeByDelegate(signer.address, proposalAddr, ""); + const proposalId = await governance.proposalCount(); + await time.increase(60 * 60); + await expect(governanceDelegated.castVote(proposalId, true)).to.be.revertedWith("Governance: balance is 0"); + await governanceDelegated.castDelegatedVote([signer.address], proposalId, true); + await time.increase(60 * 60 * 24 * 7 + 60); + await governanceDelegated.execute(proposalId); + + expect(await governance.state(proposalId)).to.be.equal(5); // executed + }); + + it("Staking rewards should be distributed without problem", async function () { + const governanceContract = await getGovernance(); + await deployAndExecuteProposal(); + const stakingVault = await governanceContract.userVault(); + const torn = await getTorn(); + const manyTorns = 100n * 1000n * 10n ** 18n; + const signer = await signerLockInGov(manyTorns); + const signerLockedBalance = await governanceContract.lockedBalance(signer.address); + const sumStaking = await torn.balanceOf(stakingVault); + const toDistibute = 10000n * 18n ** 18n; + const stakingAddr = await governanceContract.Staking(); + const governanceSigner = await ethers.getImpersonatedSigner(governanceAddr); + const stakingContract = await ethers.getContractAt( + require("./abi/staking.abi.json"), + stakingAddr, + governanceSigner, + ); + const ratioConstant = await stakingContract.ratioConstant(); + const expectedReward = (toDistibute * ((signerLockedBalance * ratioConstant) / sumStaking)) / ratioConstant; + const rewardsBeforeDistribute = await stakingContract.checkReward(signer.address); + await stakingContract.addBurnRewards(toDistibute); + const rewardsAfterDistibute = await stakingContract.checkReward(signer.address); + + expect((rewardsAfterDistibute - rewardsBeforeDistribute) / 1000n).to.be.equal(expectedReward / 1000n); + }); + + it("Check if account voted in proposal should work correct", async function () { + await deployAndExecuteProposal(); + const proposalAddr = await createValidProposal(); + const signer = await signerLockInGov("quorum"); + const governance = await getGovernance(signer); + let proposalId = await governance.proposalCount(); + await governance.propose(proposalAddr, ""); + expect(await governance.hasAccountVoted(proposalId + 1n, signer.address)).to.be.equal(false); + proposalId = await governance.proposalCount(); + expect(await governance.hasAccountVoted(proposalId, signer.address)).to.be.equal(false); + await time.increase(60 * 60); + expect(await governance.hasAccountVoted(proposalId, signer.address)).to.be.equal(false); + await governance.castVote(proposalId, true); + expect(await governance.hasAccountVoted(proposalId, signer.address)).to.be.equal(true); + }); + + it("Staker should be able to change vote", async function () { + const governanceContract = await getGovernance(); + await deployAndExecuteProposal(); + const halfQuorum = (await governanceContract.QUORUM_VOTES()) / 2n; + const proposalAddr = await createValidProposal(); + const signer = await signerLockInGov(halfQuorum); + const lockedBalance = await governanceContract.lockedBalance(signer.address); + const governance = await getGovernance(signer); + await governance.propose(proposalAddr, ""); + const proposalId = await governance.proposalCount(); + await time.increase(60 * 60); + await governance.castVote(proposalId, true); + let proposalInfo = await governance.proposals(proposalId); + expect(proposalInfo.forVotes).to.be.equal(lockedBalance); + expect(proposalInfo.againstVotes).to.be.equal(0n); + + await governance.castVote(proposalId, false); + proposalInfo = await governance.proposals(proposalId); + expect(proposalInfo.forVotes).to.be.equal(0n); + expect(proposalInfo.againstVotes).to.be.equal(lockedBalance); + }); + + it("Delegator should not be able to vote twice in one proposal", async function () { + const governanceContract = await getGovernance(); + await deployAndExecuteProposal(); + const proposalAddr = await createValidProposal(); + const halfQuorum = (await governanceContract.QUORUM_VOTES()) / 2n; + const { signer, governance, delegated } = await delegate(halfQuorum); + await governance.propose(proposalAddr, ""); + const proposalId = await governance.proposalCount(); + await time.increase(60 * 60); + await governance.castVote(proposalId, true); + const governanceDelegated = governance.connect(delegated); + await expect(governanceDelegated.castDelegatedVote([signer.address], proposalId, true)).to.be.revertedWith( + "Governance: voted already", + ); + }); + + it("If staker change vote in last hour voting should prolong", async function () { + await deployAndExecuteProposal(); + const proposalAddr = await createValidProposal(); + const signer = await signerLockInGov("quorum"); + const governance = await getGovernance(signer); + await governance.propose(proposalAddr, ""); + const proposalId = await governance.proposalCount(); + await time.increase(60 * 10); + await governance.castVote(proposalId, true); + await time.increase(60 * 60 * 24 * 4 + 60 * 60 * 23 + 60 * 30); + let proposalInfo = await governance.proposals(proposalId); + expect(proposalInfo.extended).to.be.equal(false); + await governance.castVote(proposalId, false); + proposalInfo = await governance.proposals(proposalId); + expect(proposalInfo.extended).to.be.equal(true); + }); +}); diff --git a/test/Proposal.js b/test/Proposal.js index 9341323..0a39cb1 100644 --- a/test/Proposal.js +++ b/test/Proposal.js @@ -2,7 +2,7 @@ const { ethers, network } = require("hardhat"); const contentHash = require("content-hash"); const { expect, assert } = require("chai"); const { time } = require("@nomicfoundation/hardhat-toolbox/network-helpers"); -const { deployAndExecuteProposal } = require("./utils"); +const { deployAndExecuteProposal, getGovernance, getTorn } = require("./utils"); const tornAddr = "0x77777FeDdddFfC19Ff86DB637967013e6C6A116C"; const sablierAddr = "0xCD18eAa163733Da39c232722cBC4E8940b1D8888"; @@ -56,14 +56,191 @@ describe("Proposal results check", function () { }); }); - async function getStreamArgs() { - const sablier = await getSablierContract(); - const filter = sablier.filters.CreateStream; - const events = await sablier.queryFilter(filter, config.networks.hardhat.forking.blockNumber - 1); - return events[0].args; + async function getEvents(contract, eventName, fromBlock = 0) { + const filter = contract.filters[eventName]; + const events = await contract.queryFilter(filter, fromBlock); //config.networks.hardhat.forking.blockNumber - 1 + return events; } - it("Proposal executed", async function () { - await deployAndExecuteProposal(); + function normalizeAirdropAmount(amount) { + const halfYear = 180 * 24 * 60 * 60; + return amount - (amount % BigInt(halfYear)); + } + + it("Airdrop recipients storage contracts should deployed successfully", async function () { + const { airdropRecipientsContract } = await deployAndExecuteProposal(); + expect(await ethers.provider.getCode(await airdropRecipientsContract.getAddress())).to.not.be.equal("0x"); + }); + + it("Airdrop recipients deposits sum should be almost equal 1m", async function () { + const { airdropRecipientsContract } = await deployAndExecuteProposal(); + const recipients = await airdropRecipientsContract.getAirdropRecipients(); + const airdropSum = await recipients.reduce((acc, r) => acc + r[1], 0n); + const decimals = 10n ** 18n; + const millionTorn = 1000n * 1000n * decimals; + + expect(airdropSum).to.greaterThan(millionTorn - 1n * decimals); + expect(airdropSum).to.lessThan(millionTorn + 1n * decimals); + }); + + it("Airdrop recipient deposit should calculated correctly", async function () { + const someRecipient = await resolveAddr("butterfly-effect.eth"); + const governance = await getGovernance(); + const recipientLockedBalance = await governance.lockedBalance(someRecipient); + + const decimals = 10n ** 18n; + const millionTorn = 1000n * 1000n * decimals; + const { airdropRecipientsContract } = await deployAndExecuteProposal(); + const recipients = await airdropRecipientsContract.getAirdropRecipients(); + const airdropLockedSum = await recipients.reduce((acc, r) => acc + r[2], 0n); + const selectedRecipient = recipients.find((r) => r[0] === someRecipient); + const expectedRecipientAirdrop = + (recipientLockedBalance * ((millionTorn * decimals) / airdropLockedSum)) / decimals; + + expect(selectedRecipient[1]).to.be.equal(expectedRecipientAirdrop); + }); + + it("Airdrop should start", async function () { + const { airdropContract } = await deployAndExecuteProposal(); + const filter = airdropContract.filters.CreateAirdrop; + const events = await airdropContract.queryFilter(filter); + const args = events[0].args; + expect(args[1] - args[0]).to.be.equal(180 * 24 * 60 * 60); + expect(args[2]).to.be.equal([...require("../data/airdropRecipients.json")].length); + expect(args[3]).to.be.equal(1); + }); + + it("Airdrop recipient should be able to withdraw funds", async function () { + const someRecipient = await resolveAddr("butterfly-effect.eth"); + const { airdropContract, airdropRecipientsContract } = await deployAndExecuteProposal(); + const recipients = await airdropRecipientsContract.getAirdropRecipients(); + const selectedRecipientInfo = recipients.find((r) => r[0] === someRecipient); + const recipientAirdropAmount = selectedRecipientInfo[1]; + const halfYear = 180 * 24 * 60 * 60; + const normalizedAmount = recipientAirdropAmount - (recipientAirdropAmount % BigInt(halfYear)); + const events = await getEvents(airdropContract, "CreateStream"); + const recipientStreamId = events.find((e) => e.args[1] === someRecipient).args[0]; + + await time.increase(halfYear); + const torn = await getTorn(); + const recipientBalance = await torn.balanceOf(someRecipient); + const connectedAirdrop = airdropContract.connect(await ethers.getImpersonatedSigner(someRecipient)); + await connectedAirdrop.withdrawFromStream(recipientStreamId, normalizedAmount); + + expect(await torn.balanceOf(someRecipient)).to.be.equal(recipientBalance + normalizedAmount); + }); + + it("Airdrop recipient should not be able to withdraw all funds early", async function () { + const someRecipient = await resolveAddr("butterfly-effect.eth"); + const { airdropContract, airdropRecipientsContract } = await deployAndExecuteProposal(); + const recipients = await airdropRecipientsContract.getAirdropRecipients(); + const selectedRecipientInfo = recipients.find((r) => r[0] === someRecipient); + const recipientAirdropAmount = selectedRecipientInfo[1]; + const halfYear = 180 * 24 * 60 * 60; + const normalizedAmount = normalizeAirdropAmount(recipientAirdropAmount); + const events = await getEvents(airdropContract, "CreateStream"); + const recipientStreamId = events.find((e) => e.args[1] === someRecipient).args[0]; + + await time.increase(halfYear / 2); + const connectedAirdrop = airdropContract.connect(await ethers.getImpersonatedSigner(someRecipient)); + await expect(connectedAirdrop.withdrawFromStream(recipientStreamId, normalizedAmount)).to.be.revertedWith( + "amount exceeds the available balance", + ); + }); + + it("Airdrop recipient should not be able to withdraw funds if his stake balance is lower than initial", async function () { + const someRecipient = await resolveAddr("butterfly-effect.eth"); + const { airdropContract, airdropRecipientsContract } = await deployAndExecuteProposal(); + const recipients = await airdropRecipientsContract.getAirdropRecipients(); + const selectedRecipientInfo = recipients.find((r) => r[0] === someRecipient); + const recipientAirdropAmount = selectedRecipientInfo[1]; + const halfYear = 180 * 24 * 60 * 60; + const normalizedAmount = normalizeAirdropAmount(recipientAirdropAmount); + const events = await getEvents(airdropContract, "CreateStream"); + const recipientStreamId = events.find((e) => e.args[1] === someRecipient).args[0]; + + await time.increase(halfYear); + const governance = await getGovernance(await ethers.getImpersonatedSigner(someRecipient)); + governance.unlock(1000n * 10n ** 18n); + const connectedAirdrop = airdropContract.connect(await ethers.getImpersonatedSigner(someRecipient)); + await expect(connectedAirdrop.withdrawFromStream(recipientStreamId, normalizedAmount)).to.be.revertedWith( + "not enough locked tokens in governance", + ); + }); + + it("Airdrop recipient should be able to withdraw part of funds", async function () { + const someRecipient = await resolveAddr("butterfly-effect.eth"); + const { airdropContract, airdropRecipientsContract } = await deployAndExecuteProposal(); + const recipients = await airdropRecipientsContract.getAirdropRecipients(); + const selectedRecipientInfo = recipients.find((r) => r[0] === someRecipient); + const recipientAirdropAmount = selectedRecipientInfo[1]; + const quarter = 90 * 24 * 60 * 60; + const events = await getEvents(airdropContract, "CreateStream"); + const recipientStreamId = events.find((e) => e.args[1] === someRecipient).args[0]; + + await time.increase(quarter); + const torn = await getTorn(); + const recipientBalance = await torn.balanceOf(someRecipient); + const connectedAirdrop = airdropContract.connect(await ethers.getImpersonatedSigner(someRecipient)); + await connectedAirdrop.withdrawFromStream(recipientStreamId, recipientAirdropAmount / 4n); + expect(await torn.balanceOf(someRecipient)).to.be.equal(recipientBalance + recipientAirdropAmount / 4n); + }); + + it("Airdrop recipient should not be able to withdraw funds if stream is canceled", async function () { + const someRecipient = await resolveAddr("butterfly-effect.eth"); + const { airdropContract, airdropRecipientsContract } = await deployAndExecuteProposal(); + const recipients = await airdropRecipientsContract.getAirdropRecipients(); + const selectedRecipientInfo = recipients.find((r) => r[0] === someRecipient); + const recipientAirdropAmount = selectedRecipientInfo[1]; + const halfYear = 180 * 24 * 60 * 60; + const normalizedAmount = recipientAirdropAmount - (recipientAirdropAmount % BigInt(halfYear)); + const events = await getEvents(airdropContract, "CreateStream"); + const recipientStreamId = events.find((e) => e.args[1] === someRecipient).args[0]; + + await time.increase(halfYear); + await airdropContract.cancelStream(recipientStreamId); + const connectedAirdrop = airdropContract.connect(await ethers.getImpersonatedSigner(someRecipient)); + await expect(connectedAirdrop.withdrawFromStream(recipientStreamId, normalizedAmount)).to.be.revertedWith( + "stream does not exist", + ); + }); + + it("Airdrop recipient should not be able to withdraw funds if airdrop is canceled", async function () { + const someRecipient = await resolveAddr("butterfly-effect.eth"); + const { airdropContract, airdropRecipientsContract } = await deployAndExecuteProposal(); + const recipients = await airdropRecipientsContract.getAirdropRecipients(); + const selectedRecipientInfo = recipients.find((r) => r[0] === someRecipient); + const recipientAirdropAmount = selectedRecipientInfo[1]; + const halfYear = 180 * 24 * 60 * 60; + const normalizedAmount = normalizeAirdropAmount(recipientAirdropAmount); + const events = await getEvents(airdropContract, "CreateStream"); + const recipientStreamId = events.find((e) => e.args[1] === someRecipient).args[0]; + + await time.increase(halfYear); + await airdropContract.cancelAirdrop(1, recipients.length); + const connectedAirdrop = airdropContract.connect(await ethers.getImpersonatedSigner(someRecipient)); + await expect(connectedAirdrop.withdrawFromStream(recipientStreamId, normalizedAmount)).to.be.revertedWith( + "stream does not exist", + ); + }); + + it("Airdrop cancelation should return tokens to governance", async function () { + const torn = await getTorn(); + const tornDecimals = 10n ** 18n; + const govBalanceBeforeProposal = await torn.balanceOf(governanceAddr); + const { airdropContract, airdropAddr, airdropRecipientsContract } = await deployAndExecuteProposal(); + const recipients = await airdropRecipientsContract.getAirdropRecipients(); + const airdropSum = await recipients.reduce((acc, r) => acc + normalizeAirdropAmount(r[1]), 0n); + const governanceBalance = await torn.balanceOf(governanceAddr); + const airdropContractBalance = await torn.balanceOf(airdropAddr); + await airdropContract.cancelAirdrop(1, recipients.length); + + expect(await torn.balanceOf(governanceAddr)).to.be.equal(governanceBalance + airdropSum); + expect(await torn.balanceOf(airdropAddr)).to.be.equal(airdropContractBalance - airdropSum); + expect((await torn.balanceOf(airdropAddr)) < 1n * tornDecimals); + + await airdropContract.withdrawFunds(); + expect(await torn.balanceOf(airdropAddr)).to.be.equal(0); + expect(await torn.balanceOf(governanceAddr)).to.be.equal(govBalanceBeforeProposal); }); }); diff --git a/test/abi/airdrop.abi.json b/test/abi/airdrop.abi.json index b3f8213..c976b59 100644 --- a/test/abi/airdrop.abi.json +++ b/test/abi/airdrop.abi.json @@ -1,374 +1,395 @@ [ - { - "inputs": [], - "payable": false, - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "streamId", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "remainingBalance", - "type": "uint256" - } - ], - "name": "CancelStream", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "streamId", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "deposit", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "startTime", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "stopTime", - "type": "uint256" - } - ], - "name": "CreateStream", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "uint256", - "name": "streamId", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "WithdrawFromStream", - "type": "event" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "uint256", - "name": "streamId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "who", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "internalType": "uint256", - "name": "balance", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [], - "name": "cancelAirdrop", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "uint256", - "name": "streamId", - "type": "uint256" - } - ], - "name": "cancelStream", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "components": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "deposit", - "type": "uint256" - } - ], - "internalType": "struct Types.Recipient[]", - "name": "recipients", - "type": "tuple[]" - }, - { - "internalType": "uint256", - "name": "startTime", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "stopTime", - "type": "uint256" - } - ], - "name": "createAirdrop", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "deposit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "startTime", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "stopTime", - "type": "uint256" - } - ], - "name": "createStream", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "uint256", - "name": "streamId", - "type": "uint256" - } - ], - "name": "deltaOf", - "outputs": [ - { - "internalType": "uint256", - "name": "delta", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [ - { - "internalType": "uint256", - "name": "streamId", - "type": "uint256" - } - ], - "name": "getStream", - "outputs": [ - { - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "internalType": "uint256", - "name": "deposit", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "startTime", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "stopTime", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "remainingBalance", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "ratePerSecond", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "nextStreamId", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "torn", - "outputs": [ - { - "internalType": "contract IERC20", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": true, - "inputs": [], - "name": "tornadoGovernance", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "payable": false, - "stateMutability": "view", - "type": "function" - }, - { - "constant": false, - "inputs": [ - { - "internalType": "uint256", - "name": "streamId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "withdrawFromStream", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "payable": false, - "stateMutability": "nonpayable", - "type": "function" - } - ] \ No newline at end of file + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "streamId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "remainingBalance", + "type": "uint256" + } + ], + "name": "CancelStream", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "startTime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "stopTime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "recipientsAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "firstStreamId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "lastStreamId", + "type": "uint256" + } + ], + "name": "CreateAirdrop", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "streamId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "deposit", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "initialLockedBalance", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "startTime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "stopTime", + "type": "uint256" + } + ], + "name": "CreateStream", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "streamId", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "WithdrawFromStream", + "type": "event" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "uint256", + "name": "streamId", + "type": "uint256" + }, + { + "internalType": "address", + "name": "who", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "firstStreamId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "lastStreamId", + "type": "uint256" + } + ], + "name": "cancelAirdrop", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "streamId", + "type": "uint256" + } + ], + "name": "cancelStream", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "startTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "stopTime", + "type": "uint256" + }, + { + "internalType": "address", + "name": "recipientStorage", + "type": "address" + } + ], + "name": "createAirdrop", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "uint256", + "name": "streamId", + "type": "uint256" + } + ], + "name": "deltaOf", + "outputs": [ + { + "internalType": "uint256", + "name": "delta", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "uint256", + "name": "streamId", + "type": "uint256" + } + ], + "name": "getStream", + "outputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "deposit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "startTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "stopTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "remainingBalance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "ratePerSecond", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "nextStreamId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "torn", + "outputs": [ + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "tornadoGovernance", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "streamId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "withdrawFromStream", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "withdrawFunds", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + } +] \ No newline at end of file diff --git a/test/abi/staking.abi.json b/test/abi/staking.abi.json new file mode 100644 index 0000000..a3ed86c --- /dev/null +++ b/test/abi/staking.abi.json @@ -0,0 +1 @@ +[{"inputs":[{"internalType":"address","name":"governanceAddress","type":"address"},{"internalType":"address","name":"tornAddress","type":"address"},{"internalType":"address","name":"_relayerRegistry","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"rewardsClaimed","type":"uint256"}],"name":"RewardsClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"rewards","type":"uint256"}],"name":"RewardsUpdated","type":"event"},{"inputs":[],"name":"Governance","outputs":[{"internalType":"contract ITornadoGovernance","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"accumulatedRewardPerTorn","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"accumulatedRewardRateOnLastUpdate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"accumulatedRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"addBurnRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"domains","type":"bytes32[]"}],"name":"bulkResolve","outputs":[{"internalType":"address[]","name":"result","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"checkReward","outputs":[{"internalType":"uint256","name":"rewards","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"ratioConstant","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"relayerRegistry","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"resolve","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"setReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"torn","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amountLockedBeforehand","type":"uint256"}],"name":"updateRewardsOnLockedBalanceChange","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawTorn","outputs":[],"stateMutability":"nonpayable","type":"function"}] \ No newline at end of file diff --git a/test/utils.js b/test/utils.js index 10adb0b..b749b89 100644 --- a/test/utils.js +++ b/test/utils.js @@ -8,7 +8,7 @@ const governanceAddr = "0x5efda50f22d34F262c29268506C5Fa42cB56A1Ce"; const tornAddr = "0x77777FeDdddFfC19Ff86DB637967013e6C6A116C"; async function getManyEth(addr) { - await network.provider.send("hardhat_setBalance", [addr, "0x111166630153555558483537"]); + await network.provider.send("hardhat_setBalance", [addr, "0x111166630153483537"]); } async function getPermitSignature(signer, tokenContract, spender, value, deadline) { @@ -117,6 +117,7 @@ async function getAirdrop(airdropAddr, signer) { async function signerLockInGov(tornAmount, signer) { if (!signer) signer = (await ethers.getSigners())[0]; + if (tornAmount == "quorum") tornAmount = await (await getGovernance()).QUORUM_VOTES(); const governanceSigner = await ethers.getImpersonatedSigner(governanceAddr); const torn = await getTorn(governanceSigner); @@ -140,6 +141,7 @@ async function executeNewProposal(proposalAddr) { await time.increase(60 * 60); await governanceContract.castVote(proposalId, true); await time.increase(60 * 60 * 24 * 7 + 60); + await getManyEth(stakerSigner.address); await governanceContract.execute(proposalId); await time.increase(60 * 60 * 24 * 4); await governanceContract.unlock(quorum); @@ -148,18 +150,22 @@ async function executeNewProposal(proposalAddr) { } async function deployAndExecuteProposal() { + const recipientsFactory = await ethers.getContractFactory("AirdropRecipients"); + const airdropRecipientsContract = await recipientsFactory.deploy(require("../data/airdropRecipients.json")); + const recipientStorageAddr = await airdropRecipientsContract.getAddress(); + const airdropFactory = await ethers.getContractFactory("SablierAirdrop"); const airdrop = await airdropFactory.deploy(); const airdropAddr = await airdrop.getAddress(); const proposalFactory = await ethers.getContractFactory("Proposal"); - const proposal = await proposalFactory.deploy(airdropAddr); + const proposal = await proposalFactory.deploy(airdropAddr, recipientStorageAddr); const deployedProposalAddr = await proposal.getAddress(); await executeNewProposal(deployedProposalAddr); - const airdropContract = await getAirdrop(airdropAddr); - return { airdropAddr, airdropContract }; + const airdropContract = await getAirdrop(airdropAddr, await ethers.getImpersonatedSigner(governanceAddr)); + return { airdropAddr, airdropContract, airdropRecipientsContract }; } module.exports = {