@gooddollar/goodprotocol 2.0.5-beta.6 → 2.0.5-beta.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/artifacts/abis/Faucet.min.json +1 -1
- package/artifacts/abis/FuseFaucetV2.min.json +1 -1
- package/artifacts/abis/IdentityFix.min.json +1 -0
- package/artifacts/abis/IdentityV2.min.json +1 -1
- package/artifacts/abis/UBISchemeV2.min.json +1 -0
- package/artifacts/contracts/DAOStackInterfaces.sol/Avatar.dbg.json +1 -1
- package/artifacts/contracts/DAOStackInterfaces.sol/Controller.dbg.json +1 -1
- package/artifacts/contracts/DAOStackInterfaces.sol/GlobalConstraintInterface.dbg.json +1 -1
- package/artifacts/contracts/DAOStackInterfaces.sol/IntVoteInterface.dbg.json +1 -1
- package/artifacts/contracts/DAOStackInterfaces.sol/ReputationInterface.dbg.json +1 -1
- package/artifacts/contracts/DAOStackInterfaces.sol/SchemeRegistrar.dbg.json +1 -1
- package/artifacts/contracts/Interfaces.sol/AggregatorV3Interface.dbg.json +1 -1
- package/artifacts/contracts/Interfaces.sol/ERC20.dbg.json +1 -1
- package/artifacts/contracts/Interfaces.sol/IAaveIncentivesController.dbg.json +1 -1
- package/artifacts/contracts/Interfaces.sol/IAdminWallet.dbg.json +1 -1
- package/artifacts/contracts/Interfaces.sol/IDonationStaking.dbg.json +1 -1
- package/artifacts/contracts/Interfaces.sol/IERC2917.dbg.json +1 -1
- package/artifacts/contracts/Interfaces.sol/IFirstClaimPool.dbg.json +1 -1
- package/artifacts/contracts/Interfaces.sol/IGoodDollar.dbg.json +1 -1
- package/artifacts/contracts/Interfaces.sol/IGoodStaking.dbg.json +1 -1
- package/artifacts/contracts/Interfaces.sol/IHasRouter.dbg.json +1 -1
- package/artifacts/contracts/Interfaces.sol/IIdentity.dbg.json +1 -1
- package/artifacts/contracts/Interfaces.sol/IIdentityV2.dbg.json +1 -1
- package/artifacts/contracts/Interfaces.sol/ILendingPool.dbg.json +1 -1
- package/artifacts/contracts/Interfaces.sol/IMultichainRouter.dbg.json +1 -1
- package/artifacts/contracts/Interfaces.sol/INameService.dbg.json +1 -1
- package/artifacts/contracts/Interfaces.sol/IUBIScheme.dbg.json +1 -1
- package/artifacts/contracts/Interfaces.sol/ProxyAdmin.dbg.json +1 -1
- package/artifacts/contracts/Interfaces.sol/Reserve.dbg.json +1 -1
- package/artifacts/contracts/Interfaces.sol/Staking.dbg.json +1 -1
- package/artifacts/contracts/Interfaces.sol/Uniswap.dbg.json +1 -1
- package/artifacts/contracts/Interfaces.sol/UniswapFactory.dbg.json +1 -1
- package/artifacts/contracts/Interfaces.sol/UniswapPair.dbg.json +1 -1
- package/artifacts/contracts/Interfaces.sol/cERC20.dbg.json +1 -1
- package/artifacts/contracts/fuseFaucet/Faucet.sol/Faucet.dbg.json +1 -1
- package/artifacts/contracts/fuseFaucet/Faucet.sol/Faucet.json +28 -9
- package/artifacts/contracts/fuseFaucet/FuseFaucet.sol/FuseFaucet.dbg.json +1 -1
- package/artifacts/contracts/fuseFaucet/FuseFaucetV2.sol/FuseFaucetV2.dbg.json +1 -1
- package/artifacts/contracts/fuseFaucet/FuseFaucetV2.sol/FuseFaucetV2.json +28 -2
- package/artifacts/contracts/governance/ClaimersDistribution.sol/ClaimersDistribution.dbg.json +1 -1
- package/artifacts/contracts/governance/CompoundVotingMachine.sol/CompoundVotingMachine.dbg.json +1 -1
- package/artifacts/contracts/governance/GReputation.sol/GReputation.dbg.json +1 -1
- package/artifacts/contracts/governance/GoodDollarStaking.sol/GoodDollarStaking.dbg.json +1 -1
- package/artifacts/contracts/governance/GoodDollarStaking.sol/IGovernanceStaking.dbg.json +1 -1
- package/artifacts/contracts/governance/GoodDollarStaking.sol/IStakingUpgrade.dbg.json +1 -1
- package/artifacts/contracts/governance/GoodDollarStaking.sol/RewardsMinter.dbg.json +1 -1
- package/artifacts/contracts/governance/GovernanceStaking.sol/GovernanceStaking.dbg.json +1 -1
- package/artifacts/contracts/governance/MultiBaseGovernanceShareField.sol/MultiBaseGovernanceShareField.dbg.json +1 -1
- package/artifacts/contracts/governance/Reputation.sol/Reputation.dbg.json +1 -1
- package/artifacts/contracts/governance/StakersDistribution.sol/StakersDistribution.dbg.json +1 -1
- package/artifacts/contracts/identity/IdentityV2.sol/IdentityV2.dbg.json +1 -1
- package/artifacts/contracts/identity/IdentityV2.sol/IdentityV2.json +20 -2
- package/artifacts/contracts/invite/InvitesFuseV2.sol/InvitesFuseV2.dbg.json +1 -1
- package/artifacts/contracts/invite/InvitesV1.sol/InvitesV1.dbg.json +1 -1
- package/artifacts/contracts/invite/InvitesV2.sol/InvitesV2.dbg.json +1 -1
- package/artifacts/contracts/mocks/AaveMock.sol/AaveMock.dbg.json +1 -1
- package/artifacts/contracts/mocks/AaveUSDMockOracle.sol/AaveUSDMockOracle.dbg.json +1 -1
- package/artifacts/contracts/mocks/BatUSDMockOracle.sol/BatUSDMockOracle.dbg.json +1 -1
- package/artifacts/contracts/mocks/CompUsdMockOracle.sol/CompUSDMockOracle.dbg.json +1 -1
- package/artifacts/contracts/mocks/DAIMock.sol/DAIMock.dbg.json +1 -1
- package/artifacts/contracts/mocks/DaiEthPriceMockOracle.sol/DaiEthPriceMockOracle.dbg.json +1 -1
- package/artifacts/contracts/mocks/DecimalsMock.sol/DecimalsMock.dbg.json +1 -1
- package/artifacts/contracts/mocks/DistributionBridgeMock.sol/DistributionBridgeMock.dbg.json +1 -1
- package/artifacts/contracts/mocks/DistributionHelperTest.sol/DistributionHelperTest.dbg.json +1 -1
- package/artifacts/contracts/mocks/DistributionHelperTest.sol/DistributionHelperTestHelper.dbg.json +1 -1
- package/artifacts/contracts/mocks/EthUSDMockOracle.sol/EthUSDMockOracle.dbg.json +1 -1
- package/artifacts/contracts/mocks/FeesFormularMock.sol/FeesFormulaMock.dbg.json +1 -1
- package/artifacts/contracts/mocks/GasPriceMockOracle.sol/GasPriceMockOracle.dbg.json +1 -1
- package/artifacts/contracts/mocks/GoodCompoundStakingTest.sol/GoodCompoundStakingTest.dbg.json +1 -1
- package/artifacts/contracts/mocks/GoodDollarStakingMock.sol/GoodDollarStakingMock.dbg.json +1 -1
- package/artifacts/contracts/mocks/GoodFundManagerTest.sol/GoodFundManagerTest.dbg.json +1 -1
- package/artifacts/contracts/mocks/IdentityMock.sol/IdentityMock.dbg.json +1 -1
- package/artifacts/contracts/mocks/IncentiveControllerMock.sol/IncentiveControllerMock.dbg.json +1 -1
- package/artifacts/contracts/mocks/LendingPoolMock.sol/LendingPoolMock.dbg.json +1 -1
- package/artifacts/contracts/mocks/MultichainRouterMock.sol/IWrapper.dbg.json +1 -1
- package/artifacts/contracts/mocks/MultichainRouterMock.sol/MultichainRouterMock.dbg.json +1 -1
- package/artifacts/contracts/mocks/OverMintTester.sol/IGoodDollarStakingTest.dbg.json +1 -1
- package/artifacts/contracts/mocks/OverMintTester.sol/OverMintTester.dbg.json +1 -1
- package/artifacts/contracts/mocks/OverMintTesterRegularStake.sol/OverMintTesterRegularStake.dbg.json +1 -1
- package/artifacts/contracts/mocks/PayableMock.sol/PayableMock.dbg.json +1 -1
- package/artifacts/contracts/mocks/SixteenDecimalsTokenMock.sol/SixteenDecimalsTokenMock.dbg.json +1 -1
- package/artifacts/contracts/mocks/StakingMockFixedAPY.sol/StakingMockFixedAPY.dbg.json +1 -1
- package/artifacts/contracts/mocks/SwapHelperTest.sol/SwapHelperTest.dbg.json +1 -1
- package/artifacts/contracts/mocks/TwentyDecimalsTokenMock.sol/TwentyDecimalsTokenMock.dbg.json +1 -1
- package/artifacts/contracts/mocks/UpgradableMocks.sol/UpgradableMock.dbg.json +1 -1
- package/artifacts/contracts/mocks/UpgradableMocks.sol/UpgradableMock2.dbg.json +1 -1
- package/artifacts/contracts/mocks/UpgradableMocks.sol/UpgradableMock3.dbg.json +1 -1
- package/artifacts/contracts/mocks/UpgradableMocks.sol/UpgradableMock4.dbg.json +1 -1
- package/artifacts/contracts/mocks/UsdcMock.sol/USDCMock.dbg.json +1 -1
- package/artifacts/contracts/mocks/cBATMock.sol/cBATMock.dbg.json +1 -1
- package/artifacts/contracts/mocks/cDAILowWorthMock.sol/cDAILowWorthMock.dbg.json +1 -1
- package/artifacts/contracts/mocks/cDAIMock.sol/cDAIMock.dbg.json +1 -1
- package/artifacts/contracts/mocks/cDAINonMintableMock.sol/cDAINonMintableMock.dbg.json +1 -1
- package/artifacts/contracts/mocks/cDecimalsMock.sol/cDecimalsMock.dbg.json +1 -1
- package/artifacts/contracts/mocks/cSDTMock.sol/cSDTMock.dbg.json +1 -1
- package/artifacts/contracts/mocks/cUSDCMock.sol/cUSDCMock.dbg.json +1 -1
- package/artifacts/contracts/reserve/DistributionHelper.sol/DistributionHelper.dbg.json +1 -1
- package/artifacts/contracts/reserve/ExchangeHelper.sol/ExchangeHelper.dbg.json +1 -1
- package/artifacts/contracts/reserve/GoodMarketMaker.sol/GoodMarketMaker.dbg.json +1 -1
- package/artifacts/contracts/reserve/GoodReserveCDai.sol/ContributionCalc.dbg.json +1 -1
- package/artifacts/contracts/reserve/GoodReserveCDai.sol/GoodReserveCDai.dbg.json +1 -1
- package/artifacts/contracts/staking/BaseShareField.sol/BaseShareField.dbg.json +1 -1
- package/artifacts/contracts/staking/BaseShareFieldV2.sol/BaseShareFieldV2.dbg.json +1 -1
- package/artifacts/contracts/staking/DonationsStaking.sol/DonationsStaking.dbg.json +1 -1
- package/artifacts/contracts/staking/FuseStakingV3.sol/FuseStakingV3.dbg.json +1 -1
- package/artifacts/contracts/staking/FuseStakingV3.sol/IConsensus.dbg.json +1 -1
- package/artifacts/contracts/staking/FuseStakingV3.sol/PegSwap.dbg.json +1 -1
- package/artifacts/contracts/staking/GoodFundManager.sol/GoodFundManager.dbg.json +1 -1
- package/artifacts/contracts/staking/SimpleStaking.sol/SimpleStaking.dbg.json +1 -1
- package/artifacts/contracts/staking/SimpleStakingV2.sol/SimpleStakingV2.dbg.json +1 -1
- package/artifacts/contracts/staking/UniswapV2SwapHelper.sol/UniswapV2SwapHelper.dbg.json +1 -1
- package/artifacts/contracts/staking/aave/AaveStakingFactory.sol/AaveStakingFactory.dbg.json +1 -1
- package/artifacts/contracts/staking/aave/GoodAaveStaking.sol/GoodAaveStaking.dbg.json +1 -1
- package/artifacts/contracts/staking/aave/GoodAaveStakingV2.sol/GoodAaveStakingV2.dbg.json +1 -1
- package/artifacts/contracts/staking/compound/CompoundStakingFactory.sol/CompoundStakingFactory.dbg.json +1 -1
- package/artifacts/contracts/staking/compound/GoodCompoundStaking.sol/GoodCompoundStaking.dbg.json +1 -1
- package/artifacts/contracts/staking/compound/GoodCompoundStakingV2.sol/GoodCompoundStakingV2.dbg.json +1 -1
- package/artifacts/contracts/staking/utils/Math64X64.sol/Math64x64.dbg.json +1 -1
- package/artifacts/contracts/staking/utils/StakingRewardsFixedAPY.sol/StakingRewardsFixedAPY.dbg.json +1 -1
- package/artifacts/contracts/token/ERC20PresetMinterPauserUpgradeable.sol/ERC20PresetMinterPauserUpgradeable.dbg.json +1 -1
- package/artifacts/contracts/token/ERC677.sol/ERC677.dbg.json +1 -1
- package/artifacts/contracts/token/ERC677.sol/ERC677Receiver.dbg.json +1 -1
- package/artifacts/contracts/token/FeesFormula.sol/IFeesFormula.dbg.json +1 -1
- package/artifacts/contracts/token/GoodDollar.sol/GoodDollar.dbg.json +1 -1
- package/artifacts/contracts/token/superfluid/ERC20Permit.sol/ERC20Permit.dbg.json +1 -1
- package/artifacts/contracts/token/superfluid/ERC20Permit.sol/SelfApprove.dbg.json +1 -1
- package/artifacts/contracts/token/superfluid/ISuperGoodDollar.sol/IGoodDollarCustom.dbg.json +1 -1
- package/artifacts/contracts/token/superfluid/ISuperGoodDollar.sol/ISuperGoodDollar.dbg.json +1 -1
- package/artifacts/contracts/token/superfluid/SuperGoodDollar.sol/SuperGoodDollar.dbg.json +1 -1
- package/artifacts/contracts/token/superfluid/SuperToken.sol/SuperToken.dbg.json +1 -1
- package/artifacts/contracts/token/superfluid/SuperfluidToken.sol/SuperfluidToken.dbg.json +1 -1
- package/artifacts/contracts/token/superfluid/UUPSProxiable.sol/UUPSProxiable.dbg.json +1 -1
- package/artifacts/contracts/token/superfluid/UUPSProxy.sol/Proxy.dbg.json +1 -1
- package/artifacts/contracts/token/superfluid/UUPSProxy.sol/UUPSProxy.dbg.json +1 -1
- package/artifacts/contracts/token/superfluid/UUPSProxy.sol/UUPSUtils.dbg.json +1 -1
- package/artifacts/contracts/ubi/UBIScheme.sol/UBIScheme.dbg.json +1 -1
- package/artifacts/contracts/ubi/UBISchemeV2.sol/UBISchemeV2.dbg.json +4 -0
- package/artifacts/contracts/ubi/UBISchemeV2.sol/UBISchemeV2.json +789 -0
- package/artifacts/contracts/utils/AdminWallet.sol/AdminWallet.dbg.json +1 -1
- package/artifacts/contracts/utils/AdminWalletFuse.sol/AdminWalletFuse.dbg.json +1 -1
- package/artifacts/contracts/utils/BancorFormula.sol/BancorFormula.dbg.json +1 -1
- package/artifacts/contracts/utils/BulkProof.sol/BulkProof.dbg.json +1 -1
- package/artifacts/contracts/utils/BuyAndBridgeHelper.sol/BuyAndBridgeHelper.dbg.json +1 -1
- package/artifacts/contracts/utils/DAOContract.sol/DAOContract.dbg.json +1 -1
- package/artifacts/contracts/utils/DAOUpgradeableContract.sol/DAOUpgradeableContract.dbg.json +1 -1
- package/artifacts/contracts/utils/DSMath.sol/DSMath.dbg.json +1 -1
- package/artifacts/contracts/utils/DataTypes.sol/DataTypes.dbg.json +1 -1
- package/artifacts/contracts/utils/GoodDollarMintBurnWrapper.sol/GoodDollarMintBurnWrapper.dbg.json +1 -1
- package/artifacts/contracts/utils/GoodDollarMintBurnWrapper.sol/IRouter.dbg.json +1 -1
- package/artifacts/contracts/utils/GoodDollarMintBurnWrapper.sol/PausableControl.dbg.json +1 -1
- package/artifacts/contracts/utils/GoodDollarMintBurnWrapper.sol/TokenOperation.dbg.json +1 -1
- package/artifacts/contracts/utils/IdentityFix.sol/IdentityFix.dbg.json +4 -0
- package/artifacts/contracts/utils/IdentityFix.sol/IdentityFix.json +60 -0
- package/artifacts/contracts/utils/MultiCall.sol/Multicall.dbg.json +1 -1
- package/artifacts/contracts/utils/MultichainBridgeHelper.sol/MultichainBridgeHelper.dbg.json +1 -1
- package/artifacts/contracts/utils/NameService.sol/NameService.dbg.json +1 -1
- package/artifacts/contracts/utils/OneTimePayments.sol/OneTimePayments.dbg.json +1 -1
- package/artifacts/contracts/utils/OneTimePaymentsV2.sol/OneTimePaymentsV2.dbg.json +1 -1
- package/artifacts/contracts/utils/ProtocolUpgrade.sol/OldMarketMaker.dbg.json +1 -1
- package/artifacts/contracts/utils/ProtocolUpgrade.sol/ProtocolUpgrade.dbg.json +1 -1
- package/artifacts/contracts/utils/ProtocolUpgradeFuse.sol/ProtocolUpgradeFuse.dbg.json +1 -1
- package/artifacts/contracts/utils/ProtocolUpgradeFuseRecover.sol/ProtocolUpgradeFuseRecover.dbg.json +1 -1
- package/artifacts/contracts/utils/ProtocolUpgradeRecover.sol/ProtocolUpgradeRecover.dbg.json +1 -1
- package/artifacts/contracts/utils/ProxyFactory1967.sol/ERC1967Proxy.dbg.json +1 -1
- package/artifacts/contracts/utils/ProxyFactory1967.sol/ProxyFactory1967.dbg.json +1 -1
- package/artifacts/contracts/utils/ReputationTestHelper.sol/ReputationTestHelper.dbg.json +1 -1
- package/contracts/fuseFaucet/Faucet.sol +9 -8
- package/contracts/fuseFaucet/FuseFaucetV2.sol +16 -9
- package/contracts/identity/IdentityV2.sol +52 -61
- package/contracts/ubi/UBISchemeV2.sol +470 -0
- package/contracts/utils/IdentityFix.sol +31 -0
- package/package.json +1 -1
- package/scripts/analytics/activeUsersCount.ts +56 -18
- package/scripts/analytics/whitelistsyncIssue.ts +87 -0
- package/scripts/multichain-deploy/helpers.ts +8 -6
- package/scripts/proposals/gip-14_1.ts +5 -9
- package/test/faucet/Faucet.test.ts +166 -130
- package/types/Faucet.ts +50 -21
- package/types/FuseFaucetV2.ts +50 -0
- package/types/IdentityFix.ts +141 -0
- package/types/IdentityV2.ts +39 -0
- package/types/UBISchemeV2.ts +1192 -0
- package/types/factories/Faucet__factory.ts +27 -8
- package/types/factories/FuseFaucetV2__factory.ts +27 -1
- package/types/factories/IdentityFix__factory.ts +110 -0
- package/types/factories/IdentityV2__factory.ts +19 -1
- package/types/factories/UBISchemeV2__factory.ts +837 -0
- package/types/hardhat.d.ts +18 -0
- package/types/index.ts +4 -0
|
@@ -0,0 +1,470 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIXED
|
|
2
|
+
|
|
3
|
+
// License-Identifier: MIT
|
|
4
|
+
pragma solidity >=0.8.0;
|
|
5
|
+
|
|
6
|
+
import "../utils/DAOUpgradeableContract.sol";
|
|
7
|
+
import "../utils/NameService.sol";
|
|
8
|
+
import "../Interfaces.sol";
|
|
9
|
+
import "../governance/ClaimersDistribution.sol";
|
|
10
|
+
|
|
11
|
+
// import "hardhat/console.sol";
|
|
12
|
+
|
|
13
|
+
/* @title Dynamic amount-per-day UBI scheme allowing claim once a day
|
|
14
|
+
* V2 does not keep active user count but adds a "reserve factor" of new claimers based on previous day claimers
|
|
15
|
+
*/
|
|
16
|
+
contract UBISchemeV2 is DAOUpgradeableContract {
|
|
17
|
+
struct Day {
|
|
18
|
+
mapping(address => bool) hasClaimed;
|
|
19
|
+
uint256 amountOfClaimers;
|
|
20
|
+
uint256 claimAmount;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
//daily statistics
|
|
24
|
+
mapping(uint256 => Day) public claimDay;
|
|
25
|
+
|
|
26
|
+
//last ubi claim of user
|
|
27
|
+
mapping(address => uint256) public lastClaimed;
|
|
28
|
+
|
|
29
|
+
//current day since start of contract
|
|
30
|
+
uint256 public currentDay;
|
|
31
|
+
|
|
32
|
+
//starting date of contract, used to determine the hour where daily ubi cycle starts
|
|
33
|
+
uint256 public periodStart;
|
|
34
|
+
|
|
35
|
+
// Result of distribution formula
|
|
36
|
+
// calculated each day
|
|
37
|
+
uint256 public dailyUbi;
|
|
38
|
+
|
|
39
|
+
// Limits the gas for each iteration at `fishMulti`
|
|
40
|
+
uint256 private iterationGasLimit_unused;
|
|
41
|
+
|
|
42
|
+
// Tracks the active users number. It changes when
|
|
43
|
+
// a new user claim for the first time or when a user
|
|
44
|
+
// has been fished
|
|
45
|
+
uint256 private activeUsersCount_unused;
|
|
46
|
+
|
|
47
|
+
// Tracks the last withdrawal day of funds from avatar.
|
|
48
|
+
// Withdraw occures on the first daily claim or the
|
|
49
|
+
// first daily fish only
|
|
50
|
+
uint256 public lastWithdrawDay;
|
|
51
|
+
|
|
52
|
+
// How long can a user be inactive.
|
|
53
|
+
// After those days the user can be fished
|
|
54
|
+
// (see `fish` notes)
|
|
55
|
+
uint256 private maxInactiveDays_unused;
|
|
56
|
+
|
|
57
|
+
// Whether to withdraw GD from avatar
|
|
58
|
+
// before daily ubi calculation
|
|
59
|
+
bool public shouldWithdrawFromDAO;
|
|
60
|
+
|
|
61
|
+
//number of days of each UBI pool cycle
|
|
62
|
+
//dailyPool = Pool/cycleLength
|
|
63
|
+
uint256 public cycleLength;
|
|
64
|
+
|
|
65
|
+
//the amount of G$ UBI pool for each day in the cycle to be divided by active users
|
|
66
|
+
uint256 public dailyCyclePool;
|
|
67
|
+
|
|
68
|
+
//timestamp of current cycle start
|
|
69
|
+
uint256 public startOfCycle;
|
|
70
|
+
|
|
71
|
+
//should be 0 for starters so distributionFormula detects new cycle on first day claim
|
|
72
|
+
uint256 public currentCycleLength;
|
|
73
|
+
|
|
74
|
+
//dont use first claim, and give ubi as usual
|
|
75
|
+
bool private useFirstClaimPool_unused;
|
|
76
|
+
|
|
77
|
+
//minimum amount of users to divide the pool for, renamed from defaultDailyUbi
|
|
78
|
+
uint256 public minActiveUsers;
|
|
79
|
+
|
|
80
|
+
// A pool of GD to give to activated users,
|
|
81
|
+
// since they will enter the UBI pool
|
|
82
|
+
// calculations only in the next day,
|
|
83
|
+
// meaning they can only claim in the next
|
|
84
|
+
// day
|
|
85
|
+
IFirstClaimPool private firstClaimPool_unused;
|
|
86
|
+
|
|
87
|
+
struct Funds {
|
|
88
|
+
// marks if the funds for a specific day has
|
|
89
|
+
// withdrawn from avatar
|
|
90
|
+
bool hasWithdrawn;
|
|
91
|
+
// total GD held after withdrawing
|
|
92
|
+
uint256 openAmount;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Tracks the daily withdraws and the actual amount
|
|
96
|
+
// at the begining of a trading day
|
|
97
|
+
mapping(uint256 => Funds) public dailyUBIHistory;
|
|
98
|
+
|
|
99
|
+
// Marks users that have been fished to avoid
|
|
100
|
+
// double fishing
|
|
101
|
+
mapping(address => bool) private fishedUsersAddresses_unused;
|
|
102
|
+
|
|
103
|
+
// Total claims per user stat
|
|
104
|
+
mapping(address => uint256) public totalClaimsPerUser;
|
|
105
|
+
|
|
106
|
+
bool public paused;
|
|
107
|
+
|
|
108
|
+
uint32 public reserveFactor;
|
|
109
|
+
|
|
110
|
+
// Emits when a withdraw has been succeded
|
|
111
|
+
event WithdrawFromDao(uint256 prevBalance, uint256 newBalance);
|
|
112
|
+
|
|
113
|
+
// Emits when daily ubi is calculated
|
|
114
|
+
event UBICalculated(uint256 day, uint256 dailyUbi, uint256 blockNumber);
|
|
115
|
+
|
|
116
|
+
//Emits whenever a new multi day cycle starts
|
|
117
|
+
event UBICycleCalculated(
|
|
118
|
+
uint256 day,
|
|
119
|
+
uint256 pool,
|
|
120
|
+
uint256 cycleLength,
|
|
121
|
+
uint256 dailyUBIPool
|
|
122
|
+
);
|
|
123
|
+
|
|
124
|
+
event UBIClaimed(address indexed claimer, uint256 amount);
|
|
125
|
+
event CycleLengthSet(uint256 newCycleLength);
|
|
126
|
+
event DaySet(uint256 newDay);
|
|
127
|
+
event ShouldWithdrawFromDAOSet(bool ShouldWithdrawFromDAO);
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* @dev Constructor
|
|
131
|
+
* @param _ns the DAO
|
|
132
|
+
* @param _maxInactiveDays Days of grace without claiming request
|
|
133
|
+
*/
|
|
134
|
+
function initialize(
|
|
135
|
+
INameService _ns,
|
|
136
|
+
uint256 _maxInactiveDays
|
|
137
|
+
) public initializer {
|
|
138
|
+
require(_maxInactiveDays > 0, "Max inactive days cannot be zero");
|
|
139
|
+
setDAO(_ns);
|
|
140
|
+
shouldWithdrawFromDAO = false;
|
|
141
|
+
cycleLength = 30; //30 days
|
|
142
|
+
periodStart = (block.timestamp / (1 days)) * 1 days + 12 hours; //set start time to GMT noon
|
|
143
|
+
startOfCycle = periodStart;
|
|
144
|
+
minActiveUsers = 1000;
|
|
145
|
+
reserveFactor = 500;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* @dev function that gets the amount of people who claimed on the given day
|
|
150
|
+
* @param day the day to get claimer count from, with 0 being the starting day
|
|
151
|
+
* @return an integer indicating the amount of people who claimed that day
|
|
152
|
+
*/
|
|
153
|
+
function getClaimerCount(uint256 day) public view returns (uint256) {
|
|
154
|
+
return claimDay[day].amountOfClaimers;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* @dev function that gets the amount that was claimed on the given day
|
|
159
|
+
* @param day the day to get claimer count from, with 0 being the starting day
|
|
160
|
+
* @return an integer indicating the amount that has been claimed on the given day
|
|
161
|
+
*/
|
|
162
|
+
function getClaimAmount(uint256 day) public view returns (uint256) {
|
|
163
|
+
return claimDay[day].claimAmount;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* @dev function that gets count of claimers and amount claimed for the current day
|
|
168
|
+
* @return the count of claimers and the amount claimed.
|
|
169
|
+
*/
|
|
170
|
+
function getDailyStats() public view returns (uint256, uint256) {
|
|
171
|
+
uint256 today = (block.timestamp - periodStart) / 1 days;
|
|
172
|
+
return (getClaimerCount(today), getClaimAmount(today));
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
modifier requireStarted() {
|
|
176
|
+
require(
|
|
177
|
+
paused == false && periodStart > 0 && block.timestamp >= periodStart,
|
|
178
|
+
"not in periodStarted or paused"
|
|
179
|
+
);
|
|
180
|
+
_;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* @dev On a daily basis UBIScheme withdraws tokens from GoodDao.
|
|
185
|
+
* Emits event with caller address and last day balance and the
|
|
186
|
+
* updated balance.
|
|
187
|
+
*/
|
|
188
|
+
function _withdrawFromDao() internal {
|
|
189
|
+
IGoodDollar token = nativeToken();
|
|
190
|
+
uint256 prevBalance = token.balanceOf(address(this));
|
|
191
|
+
uint256 toWithdraw = token.balanceOf(address(avatar));
|
|
192
|
+
dao.genericCall(
|
|
193
|
+
address(token),
|
|
194
|
+
abi.encodeWithSignature(
|
|
195
|
+
"transfer(address,uint256)",
|
|
196
|
+
address(this),
|
|
197
|
+
toWithdraw
|
|
198
|
+
),
|
|
199
|
+
address(avatar),
|
|
200
|
+
0
|
|
201
|
+
);
|
|
202
|
+
uint256 newBalance = prevBalance + toWithdraw;
|
|
203
|
+
require(
|
|
204
|
+
newBalance == token.balanceOf(address(this)),
|
|
205
|
+
"DAO transfer has failed"
|
|
206
|
+
);
|
|
207
|
+
emit WithdrawFromDao(prevBalance, newBalance);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* @dev sets the ubi calculation cycle length
|
|
212
|
+
* @param _newLength the new length in days
|
|
213
|
+
*/
|
|
214
|
+
function setCycleLength(uint256 _newLength) public {
|
|
215
|
+
_onlyAvatar();
|
|
216
|
+
require(_newLength > 0, "cycle must be at least 1 day long");
|
|
217
|
+
cycleLength = _newLength;
|
|
218
|
+
currentCycleLength = 0; //this will trigger a distributionFormula on next claim day
|
|
219
|
+
emit CycleLengthSet(_newLength);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* @dev returns the day count since start of current cycle
|
|
224
|
+
*/
|
|
225
|
+
function currentDayInCycle() public view returns (uint256) {
|
|
226
|
+
return (block.timestamp - startOfCycle) / (1 days);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* @dev The claim calculation formula. Divide the daily pool with
|
|
231
|
+
* the sum of the active users.
|
|
232
|
+
* the daily balance is determined by dividing current pool by the cycle length
|
|
233
|
+
* @return The amount of GoodDollar the user can claim
|
|
234
|
+
*/
|
|
235
|
+
function distributionFormula() internal returns (uint256) {
|
|
236
|
+
setDay();
|
|
237
|
+
// on first day or once in 24 hrs calculate distribution
|
|
238
|
+
if (currentDay != lastWithdrawDay || dailyUbi == 0) {
|
|
239
|
+
IGoodDollar token = nativeToken();
|
|
240
|
+
uint256 currentBalance = token.balanceOf(address(this));
|
|
241
|
+
//start early cycle if daily pool size is +-%5 previous pool
|
|
242
|
+
uint256 nextDailyPool = currentBalance / cycleLength;
|
|
243
|
+
bool shouldStartEarlyCycle = nextDailyPool >
|
|
244
|
+
(dailyCyclePool * 105) / 100 ||
|
|
245
|
+
nextDailyPool < (dailyCyclePool * 95) / 100;
|
|
246
|
+
|
|
247
|
+
if (
|
|
248
|
+
currentDayInCycle() >= currentCycleLength || shouldStartEarlyCycle
|
|
249
|
+
) //start of cycle or first time
|
|
250
|
+
{
|
|
251
|
+
if (shouldWithdrawFromDAO) {
|
|
252
|
+
_withdrawFromDao();
|
|
253
|
+
currentBalance = token.balanceOf(address(this));
|
|
254
|
+
}
|
|
255
|
+
dailyCyclePool = nextDailyPool;
|
|
256
|
+
currentCycleLength = cycleLength;
|
|
257
|
+
startOfCycle = (block.timestamp / (1 hours)) * 1 hours; //start at a round hour
|
|
258
|
+
emit UBICycleCalculated(
|
|
259
|
+
currentDay,
|
|
260
|
+
currentBalance,
|
|
261
|
+
cycleLength,
|
|
262
|
+
dailyCyclePool
|
|
263
|
+
);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
uint256 prevDayClaimers = claimDay[lastWithdrawDay].amountOfClaimers;
|
|
267
|
+
lastWithdrawDay = currentDay;
|
|
268
|
+
Funds storage funds = dailyUBIHistory[currentDay];
|
|
269
|
+
funds.hasWithdrawn = shouldWithdrawFromDAO;
|
|
270
|
+
funds.openAmount = currentBalance;
|
|
271
|
+
dailyUbi =
|
|
272
|
+
dailyCyclePool /
|
|
273
|
+
max((prevDayClaimers * reserveFactor) / 10000, minActiveUsers);
|
|
274
|
+
//update minActiveUsers as claimers grow
|
|
275
|
+
minActiveUsers = max(prevDayClaimers / 2, minActiveUsers);
|
|
276
|
+
|
|
277
|
+
emit UBICalculated(currentDay, dailyUbi, block.number);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
return dailyUbi;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
function max(uint256 a, uint256 b) private pure returns (uint256) {
|
|
284
|
+
return a >= b ? a : b;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
*@dev Sets the currentDay variable to amount of days
|
|
289
|
+
* since start of contract.
|
|
290
|
+
*/
|
|
291
|
+
function setDay() public {
|
|
292
|
+
uint256 day = (block.timestamp - periodStart) / (1 days);
|
|
293
|
+
if (day > currentDay) {
|
|
294
|
+
currentDay = day;
|
|
295
|
+
emit DaySet(day);
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* @dev Checks if the given account has claimed today
|
|
301
|
+
* @param account to check
|
|
302
|
+
* @return True if the given user has already claimed today
|
|
303
|
+
*/
|
|
304
|
+
function hasClaimed(address account) public view returns (bool) {
|
|
305
|
+
return claimDay[currentDay].hasClaimed[account];
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* @dev Checks if the given account has been owned by a registered user.
|
|
310
|
+
* @param _account to check
|
|
311
|
+
* @return True for an existing user. False for a new user
|
|
312
|
+
*/
|
|
313
|
+
function isNotNewUser(address _account) public view returns (bool) {
|
|
314
|
+
if (lastClaimed[_account] > 0) {
|
|
315
|
+
// the sender is not registered
|
|
316
|
+
return true;
|
|
317
|
+
}
|
|
318
|
+
return false;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* @dev Transfers `amount` DAO tokens to `account`. Updates stats
|
|
323
|
+
* and emits an event in case of claimed.
|
|
324
|
+
* In case that `isFirstTime` is true, it awards the user.
|
|
325
|
+
* @param _account the account which recieves the funds
|
|
326
|
+
* @param _target the recipient of funds
|
|
327
|
+
* @param _amount the amount to transfer
|
|
328
|
+
*/
|
|
329
|
+
function _transferTokens(
|
|
330
|
+
address _account,
|
|
331
|
+
address _target,
|
|
332
|
+
uint256 _amount
|
|
333
|
+
) internal {
|
|
334
|
+
// updates the stats
|
|
335
|
+
claimDay[currentDay].amountOfClaimers += 1;
|
|
336
|
+
claimDay[currentDay].hasClaimed[_account] = true;
|
|
337
|
+
lastClaimed[_account] = block.timestamp;
|
|
338
|
+
totalClaimsPerUser[_account] += 1;
|
|
339
|
+
claimDay[currentDay].claimAmount += _amount;
|
|
340
|
+
|
|
341
|
+
emit UBIClaimed(_account, _amount);
|
|
342
|
+
IGoodDollar token = nativeToken();
|
|
343
|
+
require(token.transfer(_target, _amount), "claim transfer failed");
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
function estimateNextDailyUBI() public view returns (uint256) {
|
|
347
|
+
uint256 currentBalance = nativeToken().balanceOf(address(this));
|
|
348
|
+
//start early cycle if we can increase the daily UBI pool
|
|
349
|
+
uint256 nextDailyPool = currentBalance / cycleLength;
|
|
350
|
+
bool shouldStartEarlyCycle = nextDailyPool > (dailyCyclePool * 105) / 100 ||
|
|
351
|
+
nextDailyPool < (dailyCyclePool * 95) / 100;
|
|
352
|
+
|
|
353
|
+
uint256 _dailyCyclePool = dailyCyclePool;
|
|
354
|
+
uint256 _dailyUbi;
|
|
355
|
+
if (
|
|
356
|
+
(currentDayInCycle() + 1) >= currentCycleLength || shouldStartEarlyCycle
|
|
357
|
+
) //start of cycle or first time
|
|
358
|
+
{
|
|
359
|
+
_dailyCyclePool = currentBalance / cycleLength;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
_dailyUbi =
|
|
363
|
+
_dailyCyclePool /
|
|
364
|
+
max(
|
|
365
|
+
(claimDay[currentDay].amountOfClaimers * reserveFactor) / 10000,
|
|
366
|
+
minActiveUsers
|
|
367
|
+
);
|
|
368
|
+
|
|
369
|
+
return _dailyUbi;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
function checkEntitlement() public view returns (uint256) {
|
|
373
|
+
return checkEntitlement(msg.sender);
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
/**
|
|
377
|
+
* @dev Checks the amount which the sender address is eligible to claim for,
|
|
378
|
+
* regardless if they have been whitelisted or not. In case the user is
|
|
379
|
+
* active, then the current day must be equal to the actual day, i.e. claim
|
|
380
|
+
* or fish has already been executed today.
|
|
381
|
+
* @return The amount of GD tokens the address can claim.
|
|
382
|
+
*/
|
|
383
|
+
function checkEntitlement(address _member) public view returns (uint256) {
|
|
384
|
+
if (block.timestamp < periodStart) return 0; //not started
|
|
385
|
+
|
|
386
|
+
// current day has already been updated which means
|
|
387
|
+
// that the dailyUbi has been updated
|
|
388
|
+
if (
|
|
389
|
+
currentDay == (block.timestamp - periodStart) / (1 days) && dailyUbi > 0
|
|
390
|
+
) {
|
|
391
|
+
return hasClaimed(_member) ? 0 : dailyUbi;
|
|
392
|
+
}
|
|
393
|
+
return estimateNextDailyUBI();
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
/**
|
|
397
|
+
* @dev Function for claiming UBI. Requires contract to be active. Calls distributionFormula,
|
|
398
|
+
* calculats the amount the account can claims, and transfers the amount to the account.
|
|
399
|
+
* Emits the address of account and amount claimed.
|
|
400
|
+
* @param _account The claimer account
|
|
401
|
+
* @param _target recipient of funds
|
|
402
|
+
* @return A bool indicating if UBI was claimed
|
|
403
|
+
*/
|
|
404
|
+
function _claim(address _account, address _target) internal returns (bool) {
|
|
405
|
+
// calculats the formula up today ie on day 0 there are no active users, on day 1 any user
|
|
406
|
+
// (new or active) will trigger the calculation with the active users count of the day before
|
|
407
|
+
// and so on. the new or inactive users that will become active today, will not take into account
|
|
408
|
+
// within the calculation.
|
|
409
|
+
uint256 newDistribution = distributionFormula();
|
|
410
|
+
|
|
411
|
+
// active user which has not claimed today yet, ie user last claimed < today
|
|
412
|
+
if (!hasClaimed(_account)) {
|
|
413
|
+
_transferTokens(_account, _target, newDistribution);
|
|
414
|
+
return true;
|
|
415
|
+
}
|
|
416
|
+
return false;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
/**
|
|
420
|
+
* @dev Function for claiming UBI. Requires contract to be active and claimer to be whitelisted.
|
|
421
|
+
* Calls distributionFormula, calculats the amount the caller can claim, and transfers the amount
|
|
422
|
+
* to the caller. Emits the address of caller and amount claimed.
|
|
423
|
+
* @return A bool indicating if UBI was claimed
|
|
424
|
+
*/
|
|
425
|
+
function claim() public requireStarted returns (bool) {
|
|
426
|
+
address whitelistedRoot = IIdentityV2(nameService.getAddress("IDENTITY"))
|
|
427
|
+
.getWhitelistedRoot(msg.sender);
|
|
428
|
+
require(whitelistedRoot != address(0), "UBIScheme: not whitelisted");
|
|
429
|
+
bool didClaim = _claim(whitelistedRoot, msg.sender);
|
|
430
|
+
address claimerDistribution = nameService.getAddress("GDAO_CLAIMERS");
|
|
431
|
+
if (didClaim && claimerDistribution != address(0)) {
|
|
432
|
+
ClaimersDistribution(claimerDistribution).updateClaim(whitelistedRoot);
|
|
433
|
+
}
|
|
434
|
+
return didClaim;
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
/**
|
|
438
|
+
* @dev Sets whether to also withdraw GD from avatar for UBI
|
|
439
|
+
* @param _shouldWithdraw boolean if to withdraw
|
|
440
|
+
*/
|
|
441
|
+
function setShouldWithdrawFromDAO(bool _shouldWithdraw) public {
|
|
442
|
+
_onlyAvatar();
|
|
443
|
+
shouldWithdrawFromDAO = _shouldWithdraw;
|
|
444
|
+
emit ShouldWithdrawFromDAOSet(shouldWithdrawFromDAO);
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
function pause(bool _pause) public {
|
|
448
|
+
_onlyAvatar();
|
|
449
|
+
paused = _pause;
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
// function upgrade() public {
|
|
453
|
+
// _onlyAvatar();
|
|
454
|
+
// paused = true;
|
|
455
|
+
// activeUsersCount = 50000; //estimated
|
|
456
|
+
// dailyUbi = 0; //required so distributionformula will trigger
|
|
457
|
+
// cycleLength = 30;
|
|
458
|
+
// currentCycleLength = 0; //this will trigger a new cycle calculation in distribution formula
|
|
459
|
+
// startOfCycle = block.timestamp - 91 days; //this will trigger a new calculation in distributionFormula
|
|
460
|
+
// periodStart = 1646136000;
|
|
461
|
+
// maxDailyUBI = 50000;
|
|
462
|
+
// distributionFormula();
|
|
463
|
+
// emit CycleLengthSet(cycleLength);
|
|
464
|
+
// }
|
|
465
|
+
|
|
466
|
+
function setNewClaimersReserveFactor(uint32 _reserveFactor) public {
|
|
467
|
+
_onlyAvatar();
|
|
468
|
+
reserveFactor = _reserveFactor;
|
|
469
|
+
}
|
|
470
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity >=0.8.0;
|
|
3
|
+
|
|
4
|
+
import "../identity/IdentityV2.sol";
|
|
5
|
+
|
|
6
|
+
contract IdentityFix {
|
|
7
|
+
IdentityV2 public identity;
|
|
8
|
+
|
|
9
|
+
constructor(IdentityV2 _identity) {
|
|
10
|
+
identity = _identity;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function fix(address[] memory addrs, uint256[] memory timestamps) public {
|
|
14
|
+
require(
|
|
15
|
+
identity.hasRole(identity.IDENTITY_ADMIN_ROLE(), msg.sender),
|
|
16
|
+
"not admin"
|
|
17
|
+
);
|
|
18
|
+
for (uint256 i = 0; i < addrs.length; i++) {
|
|
19
|
+
identity.authenticateWithTimestamp(addrs[i], timestamps[i]);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function end() public {
|
|
24
|
+
require(
|
|
25
|
+
identity.hasRole(identity.IDENTITY_ADMIN_ROLE(), msg.sender),
|
|
26
|
+
"not admin"
|
|
27
|
+
);
|
|
28
|
+
identity.renounceRole(identity.IDENTITY_ADMIN_ROLE(), address(this));
|
|
29
|
+
selfdestruct(payable(msg.sender));
|
|
30
|
+
}
|
|
31
|
+
}
|
package/package.json
CHANGED
|
@@ -3,14 +3,14 @@ import { ethers as Ethers } from "hardhat";
|
|
|
3
3
|
import fetch from "node-fetch";
|
|
4
4
|
|
|
5
5
|
const ONE_DAY = 24 * 60 * 60;
|
|
6
|
+
const ONE_HOUR = 60 * 60;
|
|
6
7
|
|
|
7
8
|
const main = async () => {
|
|
8
9
|
const signer = (await Ethers.getSigners())[0];
|
|
9
10
|
console.log("signer:", signer.address);
|
|
10
|
-
const ubiScheme = new Ethers.Contract(
|
|
11
|
-
"
|
|
12
|
-
|
|
13
|
-
).connect(signer);
|
|
11
|
+
const ubiScheme = new Ethers.Contract("0xD7aC544F8A570C4d8764c3AAbCF6870CBD960D0D", [
|
|
12
|
+
"function fishMulti(address[] tofish)"
|
|
13
|
+
]).connect(signer);
|
|
14
14
|
const twoWeeksAgo = parseInt((Date.now() / 1000).toFixed(0)); //
|
|
15
15
|
//parseInt((Date.now() / 1000).toFixed(0)) - 24 * 60 * 60 * 14;
|
|
16
16
|
|
|
@@ -28,21 +28,14 @@ const main = async () => {
|
|
|
28
28
|
}
|
|
29
29
|
`;
|
|
30
30
|
|
|
31
|
-
console.log(
|
|
32
|
-
"fetching inactive users since:",
|
|
33
|
-
{ curDay, day },
|
|
34
|
-
JSON.stringify({ query })
|
|
35
|
-
);
|
|
31
|
+
console.log("fetching inactive users since:", { curDay, day }, JSON.stringify({ query }));
|
|
36
32
|
const {
|
|
37
33
|
data: { walletStats }
|
|
38
|
-
} = await fetch(
|
|
39
|
-
"
|
|
40
|
-
{
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
headers: { "Content-Type": "application/json" }
|
|
44
|
-
}
|
|
45
|
-
).then(_ => _.json());
|
|
34
|
+
} = await fetch("https://api.thegraph.com/subgraphs/name/gooddollar/gooddollarfuse", {
|
|
35
|
+
method: "post",
|
|
36
|
+
body: JSON.stringify({ query }),
|
|
37
|
+
headers: { "Content-Type": "application/json" }
|
|
38
|
+
}).then(_ => _.json());
|
|
46
39
|
|
|
47
40
|
console.log("got inactive wallets:", walletStats.length);
|
|
48
41
|
if (walletStats) {
|
|
@@ -62,4 +55,49 @@ const main = async () => {
|
|
|
62
55
|
console.log("active claimers:", unique.length);
|
|
63
56
|
};
|
|
64
57
|
|
|
65
|
-
|
|
58
|
+
const countActive = async () => {
|
|
59
|
+
const twoWeeksAgo = parseInt((Date.now() / 1000).toFixed(0)); //
|
|
60
|
+
|
|
61
|
+
const hoursAgo: number[] = range(0, 24 * 14, 1);
|
|
62
|
+
let curDay = twoWeeksAgo;
|
|
63
|
+
const allActive = [];
|
|
64
|
+
for (let hour of hoursAgo) {
|
|
65
|
+
const query = `
|
|
66
|
+
{
|
|
67
|
+
walletStats(first:1000, where: { lastClaimed_lte: ${curDay},lastClaimed_gt: ${
|
|
68
|
+
curDay - ONE_HOUR
|
|
69
|
+
} isActiveUser: true }) {
|
|
70
|
+
id
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
`;
|
|
74
|
+
|
|
75
|
+
console.log("fetching active users since:", { curDay, hour }, JSON.stringify({ query }));
|
|
76
|
+
const {
|
|
77
|
+
data: { walletStats }
|
|
78
|
+
} = await fetch("https://api.thegraph.com/subgraphs/name/gooddollar/gooddollarfuse", {
|
|
79
|
+
method: "post",
|
|
80
|
+
body: JSON.stringify({ query }),
|
|
81
|
+
headers: { "Content-Type": "application/json" }
|
|
82
|
+
}).then(_ => _.json());
|
|
83
|
+
|
|
84
|
+
console.log("got active wallets:", walletStats.length);
|
|
85
|
+
if (walletStats) {
|
|
86
|
+
const accounts = walletStats.map(_ => _.id);
|
|
87
|
+
allActive.push(...accounts);
|
|
88
|
+
}
|
|
89
|
+
// for (let tofish of chunk(accounts, 50)) {
|
|
90
|
+
// const tx = await ubiScheme.fishMulti(tofish, { gasLimit: 2000000 });
|
|
91
|
+
// console.log("fishing tx:", tx, tofish);
|
|
92
|
+
// const res = await tx.wait();
|
|
93
|
+
// console.log("fishing tx result:", res);
|
|
94
|
+
// }
|
|
95
|
+
|
|
96
|
+
curDay = curDay - ONE_HOUR;
|
|
97
|
+
}
|
|
98
|
+
const unique = uniq(allActive);
|
|
99
|
+
console.log("active claimers:", unique.length);
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
//main();
|
|
103
|
+
countActive();
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { range, chunk, uniq } from "lodash";
|
|
2
|
+
import { ethers } from "hardhat";
|
|
3
|
+
import { Contract, Provider, setMulticallAddress } from "ethers-multicall";
|
|
4
|
+
import fs from "fs";
|
|
5
|
+
import { Retrier } from "@jsier/retrier";
|
|
6
|
+
|
|
7
|
+
setMulticallAddress(122, "0x3CE6158b7278Bf6792e014FA7B4f3c6c46fe9410");
|
|
8
|
+
setMulticallAddress(42220, "0x75F59534dd892c1f8a7B172D639FA854D529ada3");
|
|
9
|
+
const celoProvider = new ethers.providers.JsonRpcBatchProvider("https://forno.celo.org");
|
|
10
|
+
const ethcallProvider = new Provider(celoProvider, 42220);
|
|
11
|
+
const ethcallFuseProvider = new Provider(new ethers.providers.JsonRpcProvider("https://rpc.fuse.io"), 122);
|
|
12
|
+
|
|
13
|
+
const ONE_DAY = 24 * 60 * 60;
|
|
14
|
+
/**
|
|
15
|
+
* find accounts that where whitelisted on celo with diff authentication date than on fuse
|
|
16
|
+
*/
|
|
17
|
+
const main = async () => {
|
|
18
|
+
const identity = await ethers.getContractAt("IdentityV2", "0xC361A6E67822a0EDc17D899227dd9FC50BD62F42");
|
|
19
|
+
const abi = identity.interface.format(ethers.utils.FormatTypes.full);
|
|
20
|
+
const multiIdentity = new Contract(identity.address, abi as string[]);
|
|
21
|
+
const multiIdentityFuse = new Contract("0x2F9C28de9e6d44b71B91b8BA337A5D82e308E7BE", abi as string[]);
|
|
22
|
+
|
|
23
|
+
const celoStartBlock = 18003118;
|
|
24
|
+
const step = 10000;
|
|
25
|
+
const celoLastBlock = await ethers.provider.getBlockNumber();
|
|
26
|
+
const notFuse = [],
|
|
27
|
+
notCelo = [],
|
|
28
|
+
toFixCelo = [],
|
|
29
|
+
toFixFuse = [],
|
|
30
|
+
notBoth = [];
|
|
31
|
+
for (let i = 0; celoStartBlock + step * i < celoLastBlock; i++) {
|
|
32
|
+
try {
|
|
33
|
+
const options = { limit: 3, delay: 2000 };
|
|
34
|
+
const retrier = new Retrier(options);
|
|
35
|
+
|
|
36
|
+
const lastBlock = celoStartBlock + step * (i + 1) + 1;
|
|
37
|
+
await retrier.resolve(async attempt => {
|
|
38
|
+
const events = await identity
|
|
39
|
+
.connect(celoProvider)
|
|
40
|
+
.queryFilter(
|
|
41
|
+
identity.filters["WhitelistedAdded"](),
|
|
42
|
+
celoStartBlock + step * i,
|
|
43
|
+
Math.min(celoLastBlock, lastBlock)
|
|
44
|
+
);
|
|
45
|
+
console.log("found events:", events.length);
|
|
46
|
+
const whitelisted = events.map(_ => _.args?.account);
|
|
47
|
+
let found = 0;
|
|
48
|
+
const ps = chunk(whitelisted, 400).map(async addrChunk => {
|
|
49
|
+
const results = await ethcallProvider.all(addrChunk.map(addr => multiIdentity.lastAuthenticated(addr)));
|
|
50
|
+
const resultsFuse = await ethcallFuseProvider.all(
|
|
51
|
+
addrChunk.map(addr => multiIdentityFuse.lastAuthenticated(addr))
|
|
52
|
+
);
|
|
53
|
+
results.forEach((v, i) => {
|
|
54
|
+
const diff = v.toNumber() - resultsFuse[i].toNumber();
|
|
55
|
+
if (v.eq(0) || diff > 3600) {
|
|
56
|
+
found++;
|
|
57
|
+
// console.log("diff:", { i, addr: whitelisted[i], celo: v, fuse: resultsFuse[i] });
|
|
58
|
+
if (v.eq(0) && resultsFuse[i].eq(0)) {
|
|
59
|
+
// notBoth.push(addrChunk[i]);
|
|
60
|
+
} else if (v.eq(0)) {
|
|
61
|
+
notCelo.push(addrChunk[i]);
|
|
62
|
+
} else if (resultsFuse[i].eq(0)) {
|
|
63
|
+
notFuse.push([addrChunk[i], v.toNumber()]);
|
|
64
|
+
} else if (diff > 0) {
|
|
65
|
+
// console.log("mismatch:", addrChunk[i], { diff });
|
|
66
|
+
toFixCelo.push([addrChunk[i], resultsFuse[i].toNumber()]);
|
|
67
|
+
} else {
|
|
68
|
+
toFixFuse.push([addrChunk[i], v.toNumber()]);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
await Promise.all(ps);
|
|
74
|
+
console.log("done day:", { i, attempt, found });
|
|
75
|
+
});
|
|
76
|
+
} catch (e) {
|
|
77
|
+
console.log("failed day:", i, e.message.slice(0, 100));
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
fs.writeFileSync("whitelistissue.json", JSON.stringify({ toFixCelo, toFixFuse, notCelo, notFuse }));
|
|
81
|
+
console.log({ toFixFuse: toFixFuse.length, toFixCelo: toFixCelo.length, notCelo, notFuse });
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
const fix = async () => {
|
|
85
|
+
const { toFix, notFuse } = JSON.parse(fs.readFileSync("whitelistissue.json").toString());
|
|
86
|
+
};
|
|
87
|
+
main();
|