mirror of
https://github.com/vacp2p/staking-reward-streamer.git
synced 2026-01-07 22:43:53 -05:00
chore(RLN): import rln-contracts
This commit is contained in:
committed by
r4bbit
parent
bfba516b28
commit
458e07cc70
8
.env
Normal file
8
.env
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
GOERLI_RPC_URL=https://rpc.ankr.com/eth_goerli
|
||||||
|
ERC20TOKEN=0xA13dE8dF4Ef9D6016F0826858D48045848429390
|
||||||
|
MINIMAL_DEPOSIT=100
|
||||||
|
MAXIMAL_RATE=65535
|
||||||
|
DEPTH=20
|
||||||
|
FEE_PERCENTAGE=5
|
||||||
|
FEE_RECEIVER=0x90579a82BB296A6DA61D4d035E42Fc1aD75f090e
|
||||||
|
FREEZE_PERIOD=100
|
||||||
8
.env.example
Normal file
8
.env.example
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
GOERLI_RPC_URL=https://rpc.ankr.com/eth_goerli
|
||||||
|
ERC20TOKEN=0xA13dE8dF4Ef9D6016F0826858D48045848429390
|
||||||
|
MINIMAL_DEPOSIT=100
|
||||||
|
MAXIMAL_RATE=65535
|
||||||
|
DEPTH=20
|
||||||
|
FEE_PERCENTAGE=5
|
||||||
|
FEE_RECEIVER=0x90579a82BB296A6DA61D4d035E42Fc1aD75f090e
|
||||||
|
FREEZE_PERIOD=100
|
||||||
118
.gas-report
118
.gas-report
@@ -186,7 +186,7 @@
|
|||||||
|--------------------------------------------+-----------------+--------+--------+--------+---------|
|
|--------------------------------------------+-----------------+--------+--------+--------+---------|
|
||||||
| getAccountVaults | 5230 | 5230 | 5230 | 5230 | 4 |
|
| getAccountVaults | 5230 | 5230 | 5230 | 5230 | 4 |
|
||||||
|--------------------------------------------+-----------------+--------+--------+--------+---------|
|
|--------------------------------------------+-----------------+--------+--------+--------+---------|
|
||||||
| getVault | 13653 | 13653 | 13653 | 13653 | 4182 |
|
| getVault | 13653 | 13653 | 13653 | 13653 | 4181 |
|
||||||
|--------------------------------------------+-----------------+--------+--------+--------+---------|
|
|--------------------------------------------+-----------------+--------+--------+--------+---------|
|
||||||
| initialize | 92752 | 92752 | 92752 | 92752 | 95 |
|
| initialize | 92752 | 92752 | 92752 | 92752 | 95 |
|
||||||
|--------------------------------------------+-----------------+--------+--------+--------+---------|
|
|--------------------------------------------+-----------------+--------+--------+--------+---------|
|
||||||
@@ -194,7 +194,7 @@
|
|||||||
|--------------------------------------------+-----------------+--------+--------+--------+---------|
|
|--------------------------------------------+-----------------+--------+--------+--------+---------|
|
||||||
| leave | 66348 | 66348 | 66348 | 66348 | 2 |
|
| leave | 66348 | 66348 | 66348 | 66348 | 2 |
|
||||||
|--------------------------------------------+-----------------+--------+--------+--------+---------|
|
|--------------------------------------------+-----------------+--------+--------+--------+---------|
|
||||||
| lock | 7040 | 43591 | 46713 | 87964 | 1034 |
|
| lock | 7040 | 43473 | 46713 | 87673 | 1034 |
|
||||||
|--------------------------------------------+-----------------+--------+--------+--------+---------|
|
|--------------------------------------------+-----------------+--------+--------+--------+---------|
|
||||||
| migrateToVault | 9294 | 53513 | 17021 | 170715 | 4 |
|
| migrateToVault | 9294 | 53513 | 17021 | 170715 | 4 |
|
||||||
|--------------------------------------------+-----------------+--------+--------+--------+---------|
|
|--------------------------------------------+-----------------+--------+--------+--------+---------|
|
||||||
@@ -212,7 +212,7 @@
|
|||||||
|--------------------------------------------+-----------------+--------+--------+--------+---------|
|
|--------------------------------------------+-----------------+--------+--------+--------+---------|
|
||||||
| rewardStartTime | 2364 | 2364 | 2364 | 2364 | 2 |
|
| rewardStartTime | 2364 | 2364 | 2364 | 2364 | 2 |
|
||||||
|--------------------------------------------+-----------------+--------+--------+--------+---------|
|
|--------------------------------------------+-----------------+--------+--------+--------+---------|
|
||||||
| rewardsBalanceOf | 20295 | 24430 | 25908 | 26129 | 268 |
|
| rewardsBalanceOf | 20295 | 24409 | 25908 | 26129 | 268 |
|
||||||
|--------------------------------------------+-----------------+--------+--------+--------+---------|
|
|--------------------------------------------+-----------------+--------+--------+--------+---------|
|
||||||
| rewardsBalanceOfAccount | 62220 | 62220 | 62220 | 62220 | 1 |
|
| rewardsBalanceOfAccount | 62220 | 62220 | 62220 | 62220 | 1 |
|
||||||
|--------------------------------------------+-----------------+--------+--------+--------+---------|
|
|--------------------------------------------+-----------------+--------+--------+--------+---------|
|
||||||
@@ -222,33 +222,33 @@
|
|||||||
|--------------------------------------------+-----------------+--------+--------+--------+---------|
|
|--------------------------------------------+-----------------+--------+--------+--------+---------|
|
||||||
| setTrustedCodehash | 24238 | 24238 | 24238 | 24238 | 95 |
|
| setTrustedCodehash | 24238 | 24238 | 24238 | 24238 | 95 |
|
||||||
|--------------------------------------------+-----------------+--------+--------+--------+---------|
|
|--------------------------------------------+-----------------+--------+--------+--------+---------|
|
||||||
| stake | 2639 | 131862 | 60725 | 228623 | 2670 |
|
| stake | 2639 | 132481 | 60725 | 228623 | 2670 |
|
||||||
|--------------------------------------------+-----------------+--------+--------+--------+---------|
|
|--------------------------------------------+-----------------+--------+--------+--------+---------|
|
||||||
| stakedBalanceOf | 2622 | 2622 | 2622 | 2622 | 1 |
|
| stakedBalanceOf | 2622 | 2622 | 2622 | 2622 | 1 |
|
||||||
|--------------------------------------------+-----------------+--------+--------+--------+---------|
|
|--------------------------------------------+-----------------+--------+--------+--------+---------|
|
||||||
| totalMP | 6805 | 8257 | 8257 | 9710 | 6 |
|
| totalMP | 6805 | 8257 | 8257 | 9710 | 6 |
|
||||||
|--------------------------------------------+-----------------+--------+--------+--------+---------|
|
|--------------------------------------------+-----------------+--------+--------+--------+---------|
|
||||||
| totalMPAccrued | 2385 | 2385 | 2385 | 2385 | 4162 |
|
| totalMPAccrued | 2385 | 2385 | 2385 | 2385 | 4161 |
|
||||||
|--------------------------------------------+-----------------+--------+--------+--------+---------|
|
|--------------------------------------------+-----------------+--------+--------+--------+---------|
|
||||||
| totalMPStaked | 2429 | 2429 | 2429 | 2429 | 4165 |
|
| totalMPStaked | 2429 | 2429 | 2429 | 2429 | 4164 |
|
||||||
|--------------------------------------------+-----------------+--------+--------+--------+---------|
|
|--------------------------------------------+-----------------+--------+--------+--------+---------|
|
||||||
| totalMaxMP | 2407 | 2407 | 2407 | 2407 | 4162 |
|
| totalMaxMP | 2407 | 2407 | 2407 | 2407 | 4161 |
|
||||||
|--------------------------------------------+-----------------+--------+--------+--------+---------|
|
|--------------------------------------------+-----------------+--------+--------+--------+---------|
|
||||||
| totalRewardsAccrued | 2407 | 2407 | 2407 | 2407 | 3 |
|
| totalRewardsAccrued | 2407 | 2407 | 2407 | 2407 | 3 |
|
||||||
|--------------------------------------------+-----------------+--------+--------+--------+---------|
|
|--------------------------------------------+-----------------+--------+--------+--------+---------|
|
||||||
| totalRewardsSupply | 6737 | 11068 | 11792 | 11903 | 290 |
|
| totalRewardsSupply | 6737 | 11058 | 11792 | 11903 | 290 |
|
||||||
|--------------------------------------------+-----------------+--------+--------+--------+---------|
|
|--------------------------------------------+-----------------+--------+--------+--------+---------|
|
||||||
| totalShares | 4597 | 4597 | 4597 | 4597 | 6 |
|
| totalShares | 4597 | 4597 | 4597 | 4597 | 6 |
|
||||||
|--------------------------------------------+-----------------+--------+--------+--------+---------|
|
|--------------------------------------------+-----------------+--------+--------+--------+---------|
|
||||||
| totalStaked | 2408 | 2408 | 2408 | 2408 | 4169 |
|
| totalStaked | 2408 | 2408 | 2408 | 2408 | 4168 |
|
||||||
|--------------------------------------------+-----------------+--------+--------+--------+---------|
|
|--------------------------------------------+-----------------+--------+--------+--------+---------|
|
||||||
| unstake | 9886 | 41391 | 39781 | 79550 | 271 |
|
| unstake | 9886 | 41170 | 39781 | 79550 | 271 |
|
||||||
|--------------------------------------------+-----------------+--------+--------+--------+---------|
|
|--------------------------------------------+-----------------+--------+--------+--------+---------|
|
||||||
| updateAccount | 347677 | 347677 | 347677 | 347677 | 1 |
|
| updateAccount | 347677 | 347677 | 347677 | 347677 | 1 |
|
||||||
|--------------------------------------------+-----------------+--------+--------+--------+---------|
|
|--------------------------------------------+-----------------+--------+--------+--------+---------|
|
||||||
| updateGlobalState | 15820 | 25876 | 29230 | 29230 | 8 |
|
| updateGlobalState | 15820 | 25876 | 29230 | 29230 | 8 |
|
||||||
|--------------------------------------------+-----------------+--------+--------+--------+---------|
|
|--------------------------------------------+-----------------+--------+--------+--------+---------|
|
||||||
| updateVault | 31948 | 34543 | 31948 | 110579 | 1024 |
|
| updateVault | 31948 | 34668 | 31948 | 110579 | 1023 |
|
||||||
|--------------------------------------------+-----------------+--------+--------+--------+---------|
|
|--------------------------------------------+-----------------+--------+--------+--------+---------|
|
||||||
| upgradeTo | 10279 | 10772 | 10279 | 12745 | 5 |
|
| upgradeTo | 10279 | 10772 | 10279 | 12745 | 5 |
|
||||||
|--------------------------------------------+-----------------+--------+--------+--------+---------|
|
|--------------------------------------------+-----------------+--------+--------+--------+---------|
|
||||||
@@ -276,9 +276,9 @@
|
|||||||
|----------------------------------------+-----------------+--------+--------+--------+---------|
|
|----------------------------------------+-----------------+--------+--------+--------+---------|
|
||||||
| leave | 12223 | 113137 | 84120 | 356508 | 5 |
|
| leave | 12223 | 113137 | 84120 | 356508 | 5 |
|
||||||
|----------------------------------------+-----------------+--------+--------+--------+---------|
|
|----------------------------------------+-----------------+--------+--------+--------+---------|
|
||||||
| lock | 12151 | 59083 | 62251 | 103499 | 1035 |
|
| lock | 12151 | 58965 | 62251 | 103208 | 1035 |
|
||||||
|----------------------------------------+-----------------+--------+--------+--------+---------|
|
|----------------------------------------+-----------------+--------+--------+--------+---------|
|
||||||
| lockUntil | 2363 | 2363 | 2363 | 2363 | 7769 |
|
| lockUntil | 2363 | 2363 | 2363 | 2363 | 7766 |
|
||||||
|----------------------------------------+-----------------+--------+--------+--------+---------|
|
|----------------------------------------+-----------------+--------+--------+--------+---------|
|
||||||
| migrateToVault | 24910 | 77530 | 32637 | 219937 | 4 |
|
| migrateToVault | 24910 | 77530 | 32637 | 219937 | 4 |
|
||||||
|----------------------------------------+-----------------+--------+--------+--------+---------|
|
|----------------------------------------+-----------------+--------+--------+--------+---------|
|
||||||
@@ -286,15 +286,15 @@
|
|||||||
|----------------------------------------+-----------------+--------+--------+--------+---------|
|
|----------------------------------------+-----------------+--------+--------+--------+---------|
|
||||||
| register | 12742 | 78218 | 78761 | 78761 | 374 |
|
| register | 12742 | 78218 | 78761 | 78761 | 374 |
|
||||||
|----------------------------------------+-----------------+--------+--------+--------+---------|
|
|----------------------------------------+-----------------+--------+--------+--------+---------|
|
||||||
| stake | 12131 | 166249 | 76290 | 284275 | 2671 |
|
| stake | 12131 | 167018 | 76290 | 284275 | 2671 |
|
||||||
|----------------------------------------+-----------------+--------+--------+--------+---------|
|
|----------------------------------------+-----------------+--------+--------+--------+---------|
|
||||||
| stakeManager | 393 | 393 | 393 | 393 | 373 |
|
| stakeManager | 393 | 393 | 393 | 393 | 373 |
|
||||||
|----------------------------------------+-----------------+--------+--------+--------+---------|
|
|----------------------------------------+-----------------+--------+--------+--------+---------|
|
||||||
| trustStakeManager | 7650 | 7650 | 7650 | 7650 | 1 |
|
| trustStakeManager | 7650 | 7650 | 7650 | 7650 | 1 |
|
||||||
|----------------------------------------+-----------------+--------+--------+--------+---------|
|
|----------------------------------------+-----------------+--------+--------+--------+---------|
|
||||||
| unstake | 12108 | 58059 | 55296 | 110656 | 272 |
|
| unstake | 12108 | 57840 | 55296 | 110656 | 272 |
|
||||||
|----------------------------------------+-----------------+--------+--------+--------+---------|
|
|----------------------------------------+-----------------+--------+--------+--------+---------|
|
||||||
| updateLockUntil | 4432 | 20722 | 21532 | 21532 | 524 |
|
| updateLockUntil | 4432 | 20702 | 21532 | 21532 | 532 |
|
||||||
|----------------------------------------+-----------------+--------+--------+--------+---------|
|
|----------------------------------------+-----------------+--------+--------+--------+---------|
|
||||||
| withdraw | 20817 | 20817 | 20817 | 20817 | 1 |
|
| withdraw | 20817 | 20817 | 20817 | 20817 | 1 |
|
||||||
|----------------------------------------+-----------------+--------+--------+--------+---------|
|
|----------------------------------------+-----------------+--------+--------+--------+---------|
|
||||||
@@ -312,9 +312,9 @@
|
|||||||
|----------------------------------------------------+-----------------+-------+--------+--------+---------|
|
|----------------------------------------------------+-----------------+-------+--------+--------+---------|
|
||||||
| Function Name | Min | Avg | Median | Max | # Calls |
|
| Function Name | Min | Avg | Median | Max | # Calls |
|
||||||
|----------------------------------------------------+-----------------+-------+--------+--------+---------|
|
|----------------------------------------------------+-----------------+-------+--------+--------+---------|
|
||||||
| fallback | 5208 | 12842 | 7353 | 374054 | 23167 |
|
| fallback | 5208 | 12845 | 7353 | 374054 | 23161 |
|
||||||
|----------------------------------------------------+-----------------+-------+--------+--------+---------|
|
|----------------------------------------------------+-----------------+-------+--------+--------+---------|
|
||||||
| implementation | 346 | 2131 | 2346 | 2346 | 4886 |
|
| implementation | 346 | 2128 | 2346 | 2346 | 4894 |
|
||||||
╰----------------------------------------------------+-----------------+-------+--------+--------+---------╯
|
╰----------------------------------------------------+-----------------+-------+--------+--------+---------╯
|
||||||
|
|
||||||
╭--------------------------------------------+-----------------+--------+--------+--------+---------╮
|
╭--------------------------------------------+-----------------+--------+--------+--------+---------╮
|
||||||
@@ -373,6 +373,82 @@
|
|||||||
| urlSuffix | 3228 | 3228 | 3228 | 3228 | 1 |
|
| urlSuffix | 3228 | 3228 | 3228 | 3228 | 1 |
|
||||||
╰------------------------------------------------------------------------------------------+-----------------+-------+--------+-------+---------╯
|
╰------------------------------------------------------------------------------------------+-----------------+-------+--------+-------+---------╯
|
||||||
|
|
||||||
|
╭------------------------------+-----------------+--------+--------+--------+---------╮
|
||||||
|
| src/rln/RLN.sol:RLN Contract | | | | | |
|
||||||
|
+=====================================================================================+
|
||||||
|
| Deployment Cost | Deployment Size | | | | |
|
||||||
|
|------------------------------+-----------------+--------+--------+--------+---------|
|
||||||
|
| 1396408 | 7094 | | | | |
|
||||||
|
|------------------------------+-----------------+--------+--------+--------+---------|
|
||||||
|
| | | | | | |
|
||||||
|
|------------------------------+-----------------+--------+--------+--------+---------|
|
||||||
|
| Function Name | Min | Avg | Median | Max | # Calls |
|
||||||
|
|------------------------------+-----------------+--------+--------+--------+---------|
|
||||||
|
| FEE_PERCENTAGE | 217 | 217 | 217 | 217 | 1 |
|
||||||
|
|------------------------------+-----------------+--------+--------+--------+---------|
|
||||||
|
| FEE_RECEIVER | 226 | 226 | 226 | 226 | 1 |
|
||||||
|
|------------------------------+-----------------+--------+--------+--------+---------|
|
||||||
|
| FREEZE_PERIOD | 218 | 218 | 218 | 218 | 1 |
|
||||||
|
|------------------------------+-----------------+--------+--------+--------+---------|
|
||||||
|
| MINIMAL_DEPOSIT | 241 | 241 | 241 | 241 | 1 |
|
||||||
|
|------------------------------+-----------------+--------+--------+--------+---------|
|
||||||
|
| SET_SIZE | 284 | 284 | 284 | 284 | 1 |
|
||||||
|
|------------------------------+-----------------+--------+--------+--------+---------|
|
||||||
|
| identityCommitmentIndex | 2362 | 2362 | 2362 | 2362 | 27 |
|
||||||
|
|------------------------------+-----------------+--------+--------+--------+---------|
|
||||||
|
| members | 6826 | 6826 | 6826 | 6826 | 18 |
|
||||||
|
|------------------------------+-----------------+--------+--------+--------+---------|
|
||||||
|
| register | 23877 | 105927 | 123897 | 126709 | 18 |
|
||||||
|
|------------------------------+-----------------+--------+--------+--------+---------|
|
||||||
|
| release | 28093 | 37708 | 28192 | 66355 | 4 |
|
||||||
|
|------------------------------+-----------------+--------+--------+--------+---------|
|
||||||
|
| slash | 23015 | 49020 | 34650 | 99415 | 6 |
|
||||||
|
|------------------------------+-----------------+--------+--------+--------+---------|
|
||||||
|
| token | 292 | 292 | 292 | 292 | 1 |
|
||||||
|
|------------------------------+-----------------+--------+--------+--------+---------|
|
||||||
|
| verifier | 272 | 272 | 272 | 272 | 1 |
|
||||||
|
|------------------------------+-----------------+--------+--------+--------+---------|
|
||||||
|
| withdraw | 29336 | 79495 | 106774 | 106774 | 8 |
|
||||||
|
|------------------------------+-----------------+--------+--------+--------+---------|
|
||||||
|
| withdrawals | 6792 | 6792 | 6792 | 6792 | 5 |
|
||||||
|
╰------------------------------+-----------------+--------+--------+--------+---------╯
|
||||||
|
|
||||||
|
╭--------------------------------------+-----------------+-------+--------+-------+---------╮
|
||||||
|
| test/RLN.t.sol:MockVerifier Contract | | | | | |
|
||||||
|
+===========================================================================================+
|
||||||
|
| Deployment Cost | Deployment Size | | | | |
|
||||||
|
|--------------------------------------+-----------------+-------+--------+-------+---------|
|
||||||
|
| 204321 | 642 | | | | |
|
||||||
|
|--------------------------------------+-----------------+-------+--------+-------+---------|
|
||||||
|
| | | | | | |
|
||||||
|
|--------------------------------------+-----------------+-------+--------+-------+---------|
|
||||||
|
| Function Name | Min | Avg | Median | Max | # Calls |
|
||||||
|
|--------------------------------------+-----------------+-------+--------+-------+---------|
|
||||||
|
| changeResult | 21649 | 21649 | 21649 | 21649 | 2 |
|
||||||
|
|--------------------------------------+-----------------+-------+--------+-------+---------|
|
||||||
|
| result | 2298 | 2298 | 2298 | 2298 | 5 |
|
||||||
|
|--------------------------------------+-----------------+-------+--------+-------+---------|
|
||||||
|
| verifyProof | 4790 | 4790 | 4790 | 4790 | 9 |
|
||||||
|
╰--------------------------------------+-----------------+-------+--------+-------+---------╯
|
||||||
|
|
||||||
|
╭-----------------------------------+-----------------+-------+--------+-------+---------╮
|
||||||
|
| test/RLN.t.sol:TestERC20 Contract | | | | | |
|
||||||
|
+========================================================================================+
|
||||||
|
| Deployment Cost | Deployment Size | | | | |
|
||||||
|
|-----------------------------------+-----------------+-------+--------+-------+---------|
|
||||||
|
| 765176 | 3558 | | | | |
|
||||||
|
|-----------------------------------+-----------------+-------+--------+-------+---------|
|
||||||
|
| | | | | | |
|
||||||
|
|-----------------------------------+-----------------+-------+--------+-------+---------|
|
||||||
|
| Function Name | Min | Avg | Median | Max | # Calls |
|
||||||
|
|-----------------------------------+-----------------+-------+--------+-------+---------|
|
||||||
|
| approve | 46175 | 46179 | 46175 | 46199 | 18 |
|
||||||
|
|-----------------------------------+-----------------+-------+--------+-------+---------|
|
||||||
|
| balanceOf | 2561 | 2561 | 2561 | 2561 | 62 |
|
||||||
|
|-----------------------------------+-----------------+-------+--------+-------+---------|
|
||||||
|
| mint | 51064 | 64368 | 68164 | 68188 | 18 |
|
||||||
|
╰-----------------------------------+-----------------+-------+--------+-------+---------╯
|
||||||
|
|
||||||
╭-------------------------------------------------------------------+-----------------+-------+--------+-------+---------╮
|
╭-------------------------------------------------------------------+-----------------+-------+--------+-------+---------╮
|
||||||
| test/mocks/KarmaDistributorMock.sol:KarmaDistributorMock Contract | | | | | |
|
| test/mocks/KarmaDistributorMock.sol:KarmaDistributorMock Contract | | | | | |
|
||||||
+========================================================================================================================+
|
+========================================================================================================================+
|
||||||
@@ -418,11 +494,11 @@
|
|||||||
|---------------------------------------------+-----------------+-------+--------+-------+---------|
|
|---------------------------------------------+-----------------+-------+--------+-------+---------|
|
||||||
| Function Name | Min | Avg | Median | Max | # Calls |
|
| Function Name | Min | Avg | Median | Max | # Calls |
|
||||||
|---------------------------------------------+-----------------+-------+--------+-------+---------|
|
|---------------------------------------------+-----------------+-------+--------+-------+---------|
|
||||||
| approve | 29075 | 31544 | 29183 | 46259 | 2676 |
|
| approve | 29075 | 31546 | 29183 | 46259 | 2676 |
|
||||||
|---------------------------------------------+-----------------+-------+--------+-------+---------|
|
|---------------------------------------------+-----------------+-------+--------+-------+---------|
|
||||||
| balanceOf | 2561 | 2561 | 2561 | 2561 | 4960 |
|
| balanceOf | 2561 | 2561 | 2561 | 2561 | 4959 |
|
||||||
|---------------------------------------------+-----------------+-------+--------+-------+---------|
|
|---------------------------------------------+-----------------+-------+--------+-------+---------|
|
||||||
| mint | 33964 | 37189 | 34072 | 68248 | 2685 |
|
| mint | 33964 | 37192 | 34072 | 68248 | 2685 |
|
||||||
╰---------------------------------------------+-----------------+-------+--------+-------+---------╯
|
╰---------------------------------------------+-----------------+-------+--------+-------+---------╯
|
||||||
|
|
||||||
╭-----------------------------------------------------------------------------+-----------------+--------+--------+--------+---------╮
|
╭-----------------------------------------------------------------------------+-----------------+--------+--------+--------+---------╮
|
||||||
|
|||||||
@@ -16,15 +16,15 @@ EmergencyExitTest:test_EmergencyExitToAlternateAddress() (gas: 479110)
|
|||||||
EmergencyExitTest:test_EmergencyExitWithLock() (gas: 452444)
|
EmergencyExitTest:test_EmergencyExitWithLock() (gas: 452444)
|
||||||
EmergencyExitTest:test_EmergencyExitWithRewards() (gas: 484810)
|
EmergencyExitTest:test_EmergencyExitWithRewards() (gas: 484810)
|
||||||
EmergencyExitTest:test_OnlyOwnerCanEnableEmergencyMode() (gas: 39176)
|
EmergencyExitTest:test_OnlyOwnerCanEnableEmergencyMode() (gas: 39176)
|
||||||
FuzzTests:testFuzz_AccrueMP(uint128,uint64,uint64) (runs: 1009, μ: 586777, ~: 549070)
|
FuzzTests:testFuzz_AccrueMP(uint128,uint64,uint64) (runs: 1024, μ: 587151, ~: 549070)
|
||||||
FuzzTests:testFuzz_AccrueMP_Relock(uint128,uint64,uint64,uint64) (runs: 1009, μ: 811994, ~: 777237)
|
FuzzTests:testFuzz_AccrueMP_Relock(uint128,uint64,uint64,uint64) (runs: 1024, μ: 812396, ~: 777234)
|
||||||
FuzzTests:testFuzz_EmergencyExit(uint256,uint256) (runs: 1001, μ: 588323, ~: 578267)
|
FuzzTests:testFuzz_EmergencyExit(uint256,uint256) (runs: 1007, μ: 588350, ~: 578267)
|
||||||
FuzzTests:testFuzz_Lock(uint256,uint64) (runs: 1008, μ: 961825, ~: 961235)
|
FuzzTests:testFuzz_Lock(uint256,uint64) (runs: 1025, μ: 961806, ~: 961235)
|
||||||
FuzzTests:testFuzz_Relock(uint256,uint64,uint64) (runs: 1008, μ: 598425, ~: 574225)
|
FuzzTests:testFuzz_Relock(uint256,uint64,uint64) (runs: 1025, μ: 599078, ~: 574234)
|
||||||
FuzzTests:testFuzz_Rewards(uint256,uint256,uint256,uint16,uint16) (runs: 1001, μ: 650378, ~: 653205)
|
FuzzTests:testFuzz_Rewards(uint256,uint256,uint256,uint16,uint16) (runs: 1001, μ: 650369, ~: 653205)
|
||||||
FuzzTests:testFuzz_Stake(uint256,uint64) (runs: 1008, μ: 375317, ~: 346086)
|
FuzzTests:testFuzz_Stake(uint256,uint64) (runs: 1025, μ: 376001, ~: 346086)
|
||||||
FuzzTests:testFuzz_Unstake(uint128,uint64,uint16,uint128) (runs: 1009, μ: 806735, ~: 780622)
|
FuzzTests:testFuzz_Unstake(uint128,uint64,uint16,uint128) (runs: 1024, μ: 806573, ~: 780622)
|
||||||
FuzzTests:testFuzz_UpdateVault(uint128,uint64,uint64) (runs: 1009, μ: 586800, ~: 549093)
|
FuzzTests:testFuzz_UpdateVault(uint128,uint64,uint64) (runs: 1024, μ: 587174, ~: 549093)
|
||||||
IntegrationTest:testStakeFoo() (gas: 2348931)
|
IntegrationTest:testStakeFoo() (gas: 2348931)
|
||||||
KarmaNFTTest:testApproveNotAllowed() (gas: 10507)
|
KarmaNFTTest:testApproveNotAllowed() (gas: 10507)
|
||||||
KarmaNFTTest:testGetApproved() (gas: 10531)
|
KarmaNFTTest:testGetApproved() (gas: 10531)
|
||||||
@@ -58,7 +58,7 @@ LeaveTest:test_LeaveShouldKeepFundsLockedInStakeVault() (gas: 9938411)
|
|||||||
LeaveTest:test_LeaveShouldProperlyUpdateAccounting() (gas: 10011059)
|
LeaveTest:test_LeaveShouldProperlyUpdateAccounting() (gas: 10011059)
|
||||||
LeaveTest:test_RevertWhenStakeManagerIsTrusted() (gas: 333238)
|
LeaveTest:test_RevertWhenStakeManagerIsTrusted() (gas: 333238)
|
||||||
LeaveTest:test_TrustNewStakeManager() (gas: 9944491)
|
LeaveTest:test_TrustNewStakeManager() (gas: 9944491)
|
||||||
LockTest:test_LockFailsWithInvalidPeriod(uint256) (runs: 1008, μ: 384561, ~: 384588)
|
LockTest:test_LockFailsWithInvalidPeriod(uint256) (runs: 1025, μ: 384562, ~: 384588)
|
||||||
LockTest:test_LockFailsWithNoStake() (gas: 89700)
|
LockTest:test_LockFailsWithNoStake() (gas: 89700)
|
||||||
LockTest:test_LockFailsWithZero() (gas: 343310)
|
LockTest:test_LockFailsWithZero() (gas: 343310)
|
||||||
LockTest:test_LockMultipleTimesExceedMaxLock() (gas: 746921)
|
LockTest:test_LockMultipleTimesExceedMaxLock() (gas: 746921)
|
||||||
@@ -89,6 +89,23 @@ OverflowTest:testTotalSupply() (gas: 359166)
|
|||||||
OverflowTest:testTransfersNotAllowed() (gas: 61763)
|
OverflowTest:testTransfersNotAllowed() (gas: 61763)
|
||||||
OverflowTest:test_RevertWhen_MintingCausesOverflow() (gas: 129464)
|
OverflowTest:test_RevertWhen_MintingCausesOverflow() (gas: 129464)
|
||||||
OverflowTest:test_RevertWhen_SettingRewardCausesOverflow() (gas: 127792)
|
OverflowTest:test_RevertWhen_SettingRewardCausesOverflow() (gas: 127792)
|
||||||
|
RLNTest:test_initial_state() (gas: 65400)
|
||||||
|
RLNTest:test_register_fails_when_amount_lt_minimal_deposit() (gas: 161453)
|
||||||
|
RLNTest:test_register_fails_when_duplicate_identity_commitments() (gas: 444949)
|
||||||
|
RLNTest:test_register_fails_when_index_exceeds_set_size() (gas: 2824923)
|
||||||
|
RLNTest:test_register_succeeds() (gas: 579610)
|
||||||
|
RLNTest:test_release_fails_when_freeze_period() (gas: 529887)
|
||||||
|
RLNTest:test_release_fails_when_no_withdrawal() (gas: 38343)
|
||||||
|
RLNTest:test_release_succeeds() (gas: 576511)
|
||||||
|
RLNTest:test_slash_fails_when_invalid_proof() (gas: 399809)
|
||||||
|
RLNTest:test_slash_fails_when_not_registered() (gas: 59667)
|
||||||
|
RLNTest:test_slash_fails_when_receiver_is_zero() (gas: 351215)
|
||||||
|
RLNTest:test_slash_fails_when_self_slashing() (gas: 360067)
|
||||||
|
RLNTest:test_slash_succeeds() (gas: 1024025)
|
||||||
|
RLNTest:test_withdraw_fails_when_already_underways() (gas: 468594)
|
||||||
|
RLNTest:test_withdraw_fails_when_invalid_proof() (gas: 399356)
|
||||||
|
RLNTest:test_withdraw_fails_when_not_registered() (gas: 57129)
|
||||||
|
RLNTest:test_withdraw_succeeds() (gas: 480413)
|
||||||
RemoveRewardDistributorTest:testAddKarmaDistributorOnlyAdmin() (gas: 438045)
|
RemoveRewardDistributorTest:testAddKarmaDistributorOnlyAdmin() (gas: 438045)
|
||||||
RemoveRewardDistributorTest:testBalanceOf() (gas: 449366)
|
RemoveRewardDistributorTest:testBalanceOf() (gas: 449366)
|
||||||
RemoveRewardDistributorTest:testBalanceOfWithNoSystemTotalKarma() (gas: 69633)
|
RemoveRewardDistributorTest:testBalanceOfWithNoSystemTotalKarma() (gas: 69633)
|
||||||
|
|||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -4,7 +4,6 @@ node_modules
|
|||||||
out
|
out
|
||||||
|
|
||||||
# files
|
# files
|
||||||
*.env
|
|
||||||
*.log
|
*.log
|
||||||
.DS_Store
|
.DS_Store
|
||||||
.pnp.*
|
.pnp.*
|
||||||
|
|||||||
27
script/RLN.s.sol
Normal file
27
script/RLN.s.sol
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
// SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||||
|
pragma solidity ^0.8.17;
|
||||||
|
|
||||||
|
import "forge-std/Script.sol";
|
||||||
|
import "../src/rln/RLN.sol";
|
||||||
|
import "../src/rln/Verifier.sol";
|
||||||
|
|
||||||
|
contract RLNScript is Script {
|
||||||
|
function run() public {
|
||||||
|
uint256 minimalDeposit = vm.envUint("MINIMAL_DEPOSIT");
|
||||||
|
uint256 maximalRate = vm.envUint("MAXIMAL_RATE");
|
||||||
|
uint256 depth = vm.envUint("DEPTH");
|
||||||
|
uint8 feePercentage = uint8(vm.envUint("FEE_PERCENTAGE"));
|
||||||
|
address feeReceiver = vm.envAddress("FEE_RECEIVER");
|
||||||
|
uint256 freezePeriod = vm.envUint("FREEZE_PERIOD");
|
||||||
|
address token = vm.envAddress("ERC20TOKEN");
|
||||||
|
|
||||||
|
vm.startBroadcast();
|
||||||
|
|
||||||
|
Groth16Verifier verifier = new Groth16Verifier();
|
||||||
|
RLN rln = new RLN(
|
||||||
|
minimalDeposit, maximalRate, depth, feePercentage, feeReceiver, freezePeriod, token, address(verifier)
|
||||||
|
);
|
||||||
|
|
||||||
|
vm.stopBroadcast();
|
||||||
|
}
|
||||||
|
}
|
||||||
14
src/rln/IVerifier.sol
Normal file
14
src/rln/IVerifier.sol
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
// SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||||
|
pragma solidity ^0.8.17;
|
||||||
|
|
||||||
|
interface IVerifier {
|
||||||
|
function verifyProof(
|
||||||
|
uint256[2] calldata a,
|
||||||
|
uint256[2][2] calldata b,
|
||||||
|
uint256[2] calldata c,
|
||||||
|
uint256[2] calldata input
|
||||||
|
)
|
||||||
|
external
|
||||||
|
view
|
||||||
|
returns (bool);
|
||||||
|
}
|
||||||
209
src/rln/RLN.sol
Normal file
209
src/rln/RLN.sol
Normal file
@@ -0,0 +1,209 @@
|
|||||||
|
// SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||||
|
pragma solidity ^0.8.17;
|
||||||
|
|
||||||
|
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
||||||
|
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
|
||||||
|
import { IVerifier } from "./IVerifier.sol";
|
||||||
|
|
||||||
|
/// @title Rate-Limiting Nullifier registry contract
|
||||||
|
/// @dev This contract allows you to register RLN commitment and withdraw/slash.
|
||||||
|
contract RLN {
|
||||||
|
using SafeERC20 for IERC20;
|
||||||
|
|
||||||
|
/// @dev User metadata struct.
|
||||||
|
/// @param userAddress: address of depositor;
|
||||||
|
/// @param messageLimit: user's message limit (stakeAmount / MINIMAL_DEPOSIT).
|
||||||
|
struct User {
|
||||||
|
address userAddress;
|
||||||
|
uint256 messageLimit;
|
||||||
|
uint256 index;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Withdrawal time-lock struct
|
||||||
|
/// @param blockNumber: number of block when a withdraw was initialized;
|
||||||
|
/// @param messageLimit: amount of tokens to freeze/release;
|
||||||
|
/// @param receiver: address of receiver.
|
||||||
|
struct Withdrawal {
|
||||||
|
uint256 blockNumber;
|
||||||
|
uint256 amount;
|
||||||
|
address receiver;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Minimal membership deposit (stake amount) value - cost of 1 message.
|
||||||
|
uint256 public immutable MINIMAL_DEPOSIT;
|
||||||
|
|
||||||
|
/// @dev Maximal rate.
|
||||||
|
uint256 public immutable MAXIMAL_RATE;
|
||||||
|
|
||||||
|
/// @dev Registry set size (1 << DEPTH).
|
||||||
|
uint256 public immutable SET_SIZE;
|
||||||
|
|
||||||
|
/// @dev Address of the fee receiver.
|
||||||
|
address public immutable FEE_RECEIVER;
|
||||||
|
|
||||||
|
/// @dev Fee percentage.
|
||||||
|
uint8 public immutable FEE_PERCENTAGE;
|
||||||
|
|
||||||
|
/// @dev Freeze period - number of blocks for which the withdrawal of money is frozen.
|
||||||
|
uint256 public immutable FREEZE_PERIOD;
|
||||||
|
|
||||||
|
/// @dev Current index where identityCommitment will be stored.
|
||||||
|
uint256 public identityCommitmentIndex;
|
||||||
|
|
||||||
|
/// @dev Registry set. The keys are `identityCommitment`s.
|
||||||
|
/// The values are addresses of accounts that call `register` transaction.
|
||||||
|
mapping(uint256 => User) public members;
|
||||||
|
|
||||||
|
/// @dev Withdrawals logic.
|
||||||
|
mapping(uint256 => Withdrawal) public withdrawals;
|
||||||
|
|
||||||
|
/// @dev ERC20 Token used for staking.
|
||||||
|
IERC20 public immutable token;
|
||||||
|
|
||||||
|
/// @dev Groth16 verifier.
|
||||||
|
IVerifier public immutable verifier;
|
||||||
|
|
||||||
|
/// @dev Emmited when a new member registered.
|
||||||
|
/// @param identityCommitment: `identityCommitment`;
|
||||||
|
/// @param messageLimit: user's message limit;
|
||||||
|
/// @param index: idCommitmentIndex value.
|
||||||
|
event MemberRegistered(uint256 identityCommitment, uint256 messageLimit, uint256 index);
|
||||||
|
|
||||||
|
/// @dev Emmited when a member was withdrawn.
|
||||||
|
/// @param index: index of `identityCommitment`;
|
||||||
|
event MemberWithdrawn(uint256 index);
|
||||||
|
|
||||||
|
/// @dev Emmited when a member was slashed.
|
||||||
|
/// @param index: index of `identityCommitment`;
|
||||||
|
/// @param slasher: address of slasher (msg.sender).
|
||||||
|
event MemberSlashed(uint256 index, address slasher);
|
||||||
|
|
||||||
|
/// @param minimalDeposit: minimal membership deposit;
|
||||||
|
/// @param maximalRate: maximal rate;
|
||||||
|
/// @param depth: depth of the merkle tree;
|
||||||
|
/// @param feePercentage: fee percentage;
|
||||||
|
/// @param feeReceiver: address of the fee receiver;
|
||||||
|
/// @param freezePeriod: amount of blocks for withdrawal time-lock;
|
||||||
|
/// @param _token: address of the ERC20 contract;
|
||||||
|
/// @param _verifier: address of the Groth16 Verifier.
|
||||||
|
constructor(
|
||||||
|
uint256 minimalDeposit,
|
||||||
|
uint256 maximalRate,
|
||||||
|
uint256 depth,
|
||||||
|
uint8 feePercentage,
|
||||||
|
address feeReceiver,
|
||||||
|
uint256 freezePeriod,
|
||||||
|
address _token,
|
||||||
|
address _verifier
|
||||||
|
) {
|
||||||
|
require(feeReceiver != address(0), "RLN, constructor: fee receiver cannot be 0x0 address");
|
||||||
|
|
||||||
|
MINIMAL_DEPOSIT = minimalDeposit;
|
||||||
|
MAXIMAL_RATE = maximalRate;
|
||||||
|
SET_SIZE = 1 << depth;
|
||||||
|
|
||||||
|
FEE_PERCENTAGE = feePercentage;
|
||||||
|
FEE_RECEIVER = feeReceiver;
|
||||||
|
FREEZE_PERIOD = freezePeriod;
|
||||||
|
|
||||||
|
token = IERC20(_token);
|
||||||
|
verifier = IVerifier(_verifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Adds `identityCommitment` to the registry set and takes the necessary stake amount.
|
||||||
|
///
|
||||||
|
/// NOTE: The set must not be full.
|
||||||
|
///
|
||||||
|
/// @param identityCommitment: `identityCommitment`;
|
||||||
|
/// @param amount: stake amount.
|
||||||
|
function register(uint256 identityCommitment, uint256 amount) external {
|
||||||
|
uint256 index = identityCommitmentIndex;
|
||||||
|
|
||||||
|
require(index < SET_SIZE, "RLN, register: set is full");
|
||||||
|
require(amount >= MINIMAL_DEPOSIT, "RLN, register: amount is lower than minimal deposit");
|
||||||
|
require(amount % MINIMAL_DEPOSIT == 0, "RLN, register: amount should be a multiple of minimal deposit");
|
||||||
|
require(members[identityCommitment].userAddress == address(0), "RLN, register: idCommitment already registered");
|
||||||
|
|
||||||
|
uint256 messageLimit = amount / MINIMAL_DEPOSIT;
|
||||||
|
require(messageLimit <= MAXIMAL_RATE, "RLN, register: message limit cannot be more than MAXIMAL_RATE");
|
||||||
|
|
||||||
|
token.safeTransferFrom(msg.sender, address(this), amount);
|
||||||
|
|
||||||
|
members[identityCommitment] = User(msg.sender, messageLimit, index);
|
||||||
|
emit MemberRegistered(identityCommitment, messageLimit, index);
|
||||||
|
|
||||||
|
unchecked {
|
||||||
|
identityCommitmentIndex = index + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Request for withdraw and freeze the stake to prevent self-slashing. Stake can be
|
||||||
|
/// released after FREEZE_PERIOD blocks.
|
||||||
|
/// @param identityCommitment: `identityCommitment`;
|
||||||
|
/// @param proof: snarkjs's format generated proof (without public inputs) packed consequently.
|
||||||
|
function withdraw(uint256 identityCommitment, uint256[8] calldata proof) external {
|
||||||
|
User memory member = members[identityCommitment];
|
||||||
|
require(member.userAddress != address(0), "RLN, withdraw: member doesn't exist");
|
||||||
|
require(withdrawals[identityCommitment].blockNumber == 0, "RLN, release: such withdrawal exists");
|
||||||
|
require(_verifyProof(identityCommitment, member.userAddress, proof), "RLN, withdraw: invalid proof");
|
||||||
|
|
||||||
|
uint256 withdrawAmount = member.messageLimit * MINIMAL_DEPOSIT;
|
||||||
|
withdrawals[identityCommitment] = Withdrawal(block.number, withdrawAmount, member.userAddress);
|
||||||
|
emit MemberWithdrawn(member.index);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Releases stake amount.
|
||||||
|
/// @param identityCommitment: `identityCommitment` of withdrawn user.
|
||||||
|
function release(uint256 identityCommitment) external {
|
||||||
|
Withdrawal memory withdrawal = withdrawals[identityCommitment];
|
||||||
|
require(withdrawal.blockNumber != 0, "RLN, release: no such withdrawals");
|
||||||
|
require(block.number - withdrawal.blockNumber > FREEZE_PERIOD, "RLN, release: cannot release yet");
|
||||||
|
|
||||||
|
delete withdrawals[identityCommitment];
|
||||||
|
delete members[identityCommitment];
|
||||||
|
|
||||||
|
token.safeTransfer(withdrawal.receiver, withdrawal.amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Slashes identity with identityCommitment.
|
||||||
|
/// @param identityCommitment: `identityCommitment`;
|
||||||
|
/// @param receiver: stake receiver;
|
||||||
|
/// @param proof: snarkjs's format generated proof (without public inputs) packed consequently.
|
||||||
|
function slash(uint256 identityCommitment, address receiver, uint256[8] calldata proof) external {
|
||||||
|
require(receiver != address(0), "RLN, slash: empty receiver address");
|
||||||
|
|
||||||
|
User memory member = members[identityCommitment];
|
||||||
|
require(member.userAddress != address(0), "RLN, slash: member doesn't exist");
|
||||||
|
require(member.userAddress != receiver, "RLN, slash: self-slashing is prohibited");
|
||||||
|
|
||||||
|
require(_verifyProof(identityCommitment, receiver, proof), "RLN, slash: invalid proof");
|
||||||
|
|
||||||
|
delete members[identityCommitment];
|
||||||
|
delete withdrawals[identityCommitment];
|
||||||
|
|
||||||
|
uint256 withdrawAmount = member.messageLimit * MINIMAL_DEPOSIT;
|
||||||
|
uint256 feeAmount = (FEE_PERCENTAGE * withdrawAmount) / 100;
|
||||||
|
|
||||||
|
token.safeTransfer(receiver, withdrawAmount - feeAmount);
|
||||||
|
token.safeTransfer(FEE_RECEIVER, feeAmount);
|
||||||
|
emit MemberSlashed(member.index, receiver);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @dev Groth16 proof verification
|
||||||
|
function _verifyProof(
|
||||||
|
uint256 identityCommitment,
|
||||||
|
address receiver,
|
||||||
|
uint256[8] calldata proof
|
||||||
|
)
|
||||||
|
internal
|
||||||
|
view
|
||||||
|
returns (bool)
|
||||||
|
{
|
||||||
|
return verifier.verifyProof(
|
||||||
|
[proof[0], proof[1]],
|
||||||
|
[[proof[2], proof[3]], [proof[4], proof[5]]],
|
||||||
|
[proof[6], proof[7]],
|
||||||
|
[identityCommitment, uint256(uint160(receiver))]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
202
src/rln/Verifier.sol
Normal file
202
src/rln/Verifier.sol
Normal file
@@ -0,0 +1,202 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-3.0
|
||||||
|
/*
|
||||||
|
Copyright 2021 0KIMS association.
|
||||||
|
|
||||||
|
This file is generated with [snarkJS](https://github.com/iden3/snarkjs).
|
||||||
|
|
||||||
|
snarkJS is a free software: you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
snarkJS is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||||
|
License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with snarkJS. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
pragma solidity >=0.7.0 <0.9.0;
|
||||||
|
|
||||||
|
contract Groth16Verifier {
|
||||||
|
// Scalar field size
|
||||||
|
uint256 constant r =
|
||||||
|
21_888_242_871_839_275_222_246_405_745_257_275_088_548_364_400_416_034_343_698_204_186_575_808_495_617;
|
||||||
|
// Base field size
|
||||||
|
uint256 constant q =
|
||||||
|
21_888_242_871_839_275_222_246_405_745_257_275_088_696_311_157_297_823_662_689_037_894_645_226_208_583;
|
||||||
|
|
||||||
|
// Verification Key data
|
||||||
|
uint256 constant alphax =
|
||||||
|
20_491_192_805_390_485_299_153_009_773_594_534_940_189_261_866_228_447_918_068_658_471_970_481_763_042;
|
||||||
|
uint256 constant alphay =
|
||||||
|
9_383_485_363_053_290_200_918_347_156_157_836_566_562_967_994_039_712_273_449_902_621_266_178_545_958;
|
||||||
|
uint256 constant betax1 =
|
||||||
|
4_252_822_878_758_300_859_123_897_981_450_591_353_533_073_413_197_771_768_651_442_665_752_259_397_132;
|
||||||
|
uint256 constant betax2 =
|
||||||
|
6_375_614_351_688_725_206_403_948_262_868_962_793_625_744_043_794_305_715_222_011_528_459_656_738_731;
|
||||||
|
uint256 constant betay1 =
|
||||||
|
21_847_035_105_528_745_403_288_232_691_147_584_728_191_162_732_299_865_338_377_159_692_350_059_136_679;
|
||||||
|
uint256 constant betay2 =
|
||||||
|
10_505_242_626_370_262_277_552_901_082_094_356_697_409_835_680_220_590_971_873_171_140_371_331_206_856;
|
||||||
|
uint256 constant gammax1 =
|
||||||
|
11_559_732_032_986_387_107_991_004_021_392_285_783_925_812_861_821_192_530_917_403_151_452_391_805_634;
|
||||||
|
uint256 constant gammax2 =
|
||||||
|
10_857_046_999_023_057_135_944_570_762_232_829_481_370_756_359_578_518_086_990_519_993_285_655_852_781;
|
||||||
|
uint256 constant gammay1 =
|
||||||
|
4_082_367_875_863_433_681_332_203_403_145_435_568_316_851_327_593_401_208_105_741_076_214_120_093_531;
|
||||||
|
uint256 constant gammay2 =
|
||||||
|
8_495_653_923_123_431_417_604_973_247_489_272_438_418_190_587_263_600_148_770_280_649_306_958_101_930;
|
||||||
|
uint256 constant deltax1 =
|
||||||
|
11_551_021_181_461_167_826_461_759_140_322_976_337_427_023_987_127_500_996_455_457_136_635_486_400_849;
|
||||||
|
uint256 constant deltax2 =
|
||||||
|
16_440_331_697_014_556_916_876_897_072_677_669_680_121_386_347_171_004_539_353_252_116_876_383_229_648;
|
||||||
|
uint256 constant deltay1 =
|
||||||
|
16_935_666_883_311_644_237_478_257_793_713_075_046_951_222_500_094_443_222_621_864_730_929_684_383_196;
|
||||||
|
uint256 constant deltay2 =
|
||||||
|
15_542_122_065_551_809_636_611_024_015_159_689_732_218_122_471_819_623_718_488_423_844_152_861_811_271;
|
||||||
|
|
||||||
|
uint256 constant IC0x =
|
||||||
|
19_490_069_286_251_317_200_471_893_224_761_952_280_235_157_078_692_599_655_063_040_494_106_083_015_102;
|
||||||
|
uint256 constant IC0y =
|
||||||
|
15_613_730_057_977_833_735_664_106_983_317_680_013_118_142_165_231_654_768_046_521_650_638_333_652_991;
|
||||||
|
|
||||||
|
uint256 constant IC1x =
|
||||||
|
1_563_543_155_852_853_229_359_605_494_188_815_884_199_915_022_658_219_002_707_722_789_976_065_966_419;
|
||||||
|
uint256 constant IC1y =
|
||||||
|
858_819_375_930_654_753_672_617_171_465_307_097_688_802_650_498_051_619_587_167_586_479_724_200_799;
|
||||||
|
|
||||||
|
uint256 constant IC2x =
|
||||||
|
3_808_889_614_445_935_800_597_561_392_085_733_302_718_838_702_771_107_544_944_545_050_886_958_022_904;
|
||||||
|
uint256 constant IC2y =
|
||||||
|
13_293_649_293_049_947_010_793_838_294_353_767_499_934_999_769_633_605_908_974_566_715_226_392_122_400;
|
||||||
|
|
||||||
|
// Memory data
|
||||||
|
uint16 constant pVk = 0;
|
||||||
|
uint16 constant pPairing = 128;
|
||||||
|
|
||||||
|
uint16 constant pLastMem = 896;
|
||||||
|
|
||||||
|
function verifyProof(
|
||||||
|
uint256[2] calldata _pA,
|
||||||
|
uint256[2][2] calldata _pB,
|
||||||
|
uint256[2] calldata _pC,
|
||||||
|
uint256[2] calldata _pubSignals
|
||||||
|
)
|
||||||
|
public
|
||||||
|
view
|
||||||
|
returns (bool)
|
||||||
|
{
|
||||||
|
assembly {
|
||||||
|
function checkField(v) {
|
||||||
|
if iszero(lt(v, q)) {
|
||||||
|
mstore(0, 0)
|
||||||
|
return(0, 0x20)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// G1 function to multiply a G1 value(x,y) to value in an address
|
||||||
|
function g1_mulAccC(pR, x, y, s) {
|
||||||
|
let success
|
||||||
|
let mIn := mload(0x40)
|
||||||
|
mstore(mIn, x)
|
||||||
|
mstore(add(mIn, 32), y)
|
||||||
|
mstore(add(mIn, 64), s)
|
||||||
|
|
||||||
|
success := staticcall(sub(gas(), 2000), 7, mIn, 96, mIn, 64)
|
||||||
|
|
||||||
|
if iszero(success) {
|
||||||
|
mstore(0, 0)
|
||||||
|
return(0, 0x20)
|
||||||
|
}
|
||||||
|
|
||||||
|
mstore(add(mIn, 64), mload(pR))
|
||||||
|
mstore(add(mIn, 96), mload(add(pR, 32)))
|
||||||
|
|
||||||
|
success := staticcall(sub(gas(), 2000), 6, mIn, 128, pR, 64)
|
||||||
|
|
||||||
|
if iszero(success) {
|
||||||
|
mstore(0, 0)
|
||||||
|
return(0, 0x20)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkPairing(pA, pB, pC, pubSignals, pMem) -> isOk {
|
||||||
|
let _pPairing := add(pMem, pPairing)
|
||||||
|
let _pVk := add(pMem, pVk)
|
||||||
|
|
||||||
|
mstore(_pVk, IC0x)
|
||||||
|
mstore(add(_pVk, 32), IC0y)
|
||||||
|
|
||||||
|
// Compute the linear combination vk_x
|
||||||
|
|
||||||
|
g1_mulAccC(_pVk, IC1x, IC1y, calldataload(add(pubSignals, 0)))
|
||||||
|
|
||||||
|
g1_mulAccC(_pVk, IC2x, IC2y, calldataload(add(pubSignals, 32)))
|
||||||
|
|
||||||
|
// -A
|
||||||
|
mstore(_pPairing, calldataload(pA))
|
||||||
|
mstore(add(_pPairing, 32), mod(sub(q, calldataload(add(pA, 32))), q))
|
||||||
|
|
||||||
|
// B
|
||||||
|
mstore(add(_pPairing, 64), calldataload(pB))
|
||||||
|
mstore(add(_pPairing, 96), calldataload(add(pB, 32)))
|
||||||
|
mstore(add(_pPairing, 128), calldataload(add(pB, 64)))
|
||||||
|
mstore(add(_pPairing, 160), calldataload(add(pB, 96)))
|
||||||
|
|
||||||
|
// alpha1
|
||||||
|
mstore(add(_pPairing, 192), alphax)
|
||||||
|
mstore(add(_pPairing, 224), alphay)
|
||||||
|
|
||||||
|
// beta2
|
||||||
|
mstore(add(_pPairing, 256), betax1)
|
||||||
|
mstore(add(_pPairing, 288), betax2)
|
||||||
|
mstore(add(_pPairing, 320), betay1)
|
||||||
|
mstore(add(_pPairing, 352), betay2)
|
||||||
|
|
||||||
|
// vk_x
|
||||||
|
mstore(add(_pPairing, 384), mload(add(pMem, pVk)))
|
||||||
|
mstore(add(_pPairing, 416), mload(add(pMem, add(pVk, 32))))
|
||||||
|
|
||||||
|
// gamma2
|
||||||
|
mstore(add(_pPairing, 448), gammax1)
|
||||||
|
mstore(add(_pPairing, 480), gammax2)
|
||||||
|
mstore(add(_pPairing, 512), gammay1)
|
||||||
|
mstore(add(_pPairing, 544), gammay2)
|
||||||
|
|
||||||
|
// C
|
||||||
|
mstore(add(_pPairing, 576), calldataload(pC))
|
||||||
|
mstore(add(_pPairing, 608), calldataload(add(pC, 32)))
|
||||||
|
|
||||||
|
// delta2
|
||||||
|
mstore(add(_pPairing, 640), deltax1)
|
||||||
|
mstore(add(_pPairing, 672), deltax2)
|
||||||
|
mstore(add(_pPairing, 704), deltay1)
|
||||||
|
mstore(add(_pPairing, 736), deltay2)
|
||||||
|
|
||||||
|
let success := staticcall(sub(gas(), 2000), 8, _pPairing, 768, _pPairing, 0x20)
|
||||||
|
|
||||||
|
isOk := and(success, mload(_pPairing))
|
||||||
|
}
|
||||||
|
|
||||||
|
let pMem := mload(0x40)
|
||||||
|
mstore(0x40, add(pMem, pLastMem))
|
||||||
|
|
||||||
|
// Validate that all evaluations ∈ F
|
||||||
|
|
||||||
|
checkField(calldataload(add(_pubSignals, 0)))
|
||||||
|
|
||||||
|
checkField(calldataload(add(_pubSignals, 32)))
|
||||||
|
|
||||||
|
checkField(calldataload(add(_pubSignals, 64)))
|
||||||
|
|
||||||
|
// Validate all evaluations
|
||||||
|
let isValid := checkPairing(_pA, _pB, _pC, _pubSignals, pMem)
|
||||||
|
|
||||||
|
mstore(0, isValid)
|
||||||
|
return(0, 0x20)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
395
test/RLN.t.sol
Normal file
395
test/RLN.t.sol
Normal file
@@ -0,0 +1,395 @@
|
|||||||
|
// SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||||
|
pragma solidity ^0.8.17;
|
||||||
|
|
||||||
|
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
|
||||||
|
|
||||||
|
import "forge-std/Test.sol";
|
||||||
|
|
||||||
|
import "../src/rln/RLN.sol";
|
||||||
|
import { IVerifier } from "../src/rln/IVerifier.sol";
|
||||||
|
|
||||||
|
// A ERC20 token contract which allows arbitrary minting for testing
|
||||||
|
contract TestERC20 is ERC20 {
|
||||||
|
constructor() ERC20("TestERC20", "TST") { }
|
||||||
|
|
||||||
|
function mint(address to, uint256 amount) external {
|
||||||
|
_mint(to, amount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// A mock verifier which makes us skip the proof verification.
|
||||||
|
contract MockVerifier is IVerifier {
|
||||||
|
bool public result;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function verifyProof(
|
||||||
|
uint256[2] memory,
|
||||||
|
uint256[2][2] memory,
|
||||||
|
uint256[2] memory,
|
||||||
|
uint256[2] memory
|
||||||
|
)
|
||||||
|
external
|
||||||
|
view
|
||||||
|
returns (bool)
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function changeResult(bool _result) external {
|
||||||
|
result = _result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
contract RLNTest is Test {
|
||||||
|
event MemberRegistered(uint256 identityCommitment, uint256 messageLimit, uint256 index);
|
||||||
|
event MemberWithdrawn(uint256 index);
|
||||||
|
event MemberSlashed(uint256 index, address slasher);
|
||||||
|
|
||||||
|
RLN rln;
|
||||||
|
TestERC20 token;
|
||||||
|
MockVerifier verifier;
|
||||||
|
|
||||||
|
uint256 rlnInitialTokenBalance = 1_000_000;
|
||||||
|
uint256 minimalDeposit = 100;
|
||||||
|
uint256 maximalRate = 1 << 16 - 1;
|
||||||
|
uint256 depth = 20;
|
||||||
|
uint8 feePercentage = 10;
|
||||||
|
address feeReceiver = makeAddr("feeReceiver");
|
||||||
|
uint256 freezePeriod = 1;
|
||||||
|
|
||||||
|
uint256 identityCommitment0 = 1234;
|
||||||
|
uint256 identityCommitment1 = 5678;
|
||||||
|
|
||||||
|
address user0 = makeAddr("user0");
|
||||||
|
address user1 = makeAddr("user1");
|
||||||
|
address slashedReceiver = makeAddr("slashedReceiver");
|
||||||
|
|
||||||
|
uint256 messageLimit0 = 2;
|
||||||
|
uint256 messageLimit1 = 3;
|
||||||
|
|
||||||
|
uint256[8] mockProof =
|
||||||
|
[uint256(0), uint256(1), uint256(2), uint256(3), uint256(4), uint256(5), uint256(6), uint256(7)];
|
||||||
|
|
||||||
|
function setUp() public {
|
||||||
|
token = new TestERC20();
|
||||||
|
verifier = new MockVerifier();
|
||||||
|
rln = new RLN(
|
||||||
|
minimalDeposit,
|
||||||
|
maximalRate,
|
||||||
|
depth,
|
||||||
|
feePercentage,
|
||||||
|
feeReceiver,
|
||||||
|
freezePeriod,
|
||||||
|
address(token),
|
||||||
|
address(verifier)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_initial_state() public {
|
||||||
|
assertEq(rln.MINIMAL_DEPOSIT(), minimalDeposit);
|
||||||
|
assertEq(rln.SET_SIZE(), 1 << depth);
|
||||||
|
assertEq(rln.FEE_PERCENTAGE(), feePercentage);
|
||||||
|
assertEq(rln.FEE_RECEIVER(), feeReceiver);
|
||||||
|
assertEq(rln.FREEZE_PERIOD(), freezePeriod);
|
||||||
|
assertEq(address(rln.token()), address(token));
|
||||||
|
assertEq(address(rln.verifier()), address(verifier));
|
||||||
|
assertEq(rln.identityCommitmentIndex(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* register */
|
||||||
|
|
||||||
|
function test_register_succeeds() public {
|
||||||
|
// Test: register one user
|
||||||
|
register(user0, identityCommitment0, messageLimit0);
|
||||||
|
// Test: register second user
|
||||||
|
register(user1, identityCommitment1, messageLimit1);
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_register_fails_when_index_exceeds_set_size() public {
|
||||||
|
// Set size is (1 << smallDepth) = 2, and thus there can
|
||||||
|
// only be 2 members, otherwise reverts.
|
||||||
|
uint256 smallDepth = 1;
|
||||||
|
TestERC20 _token = new TestERC20();
|
||||||
|
RLN smallRLN = new RLN(
|
||||||
|
minimalDeposit, maximalRate, smallDepth, feePercentage, feeReceiver, 0, address(_token), address(verifier)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Register the first user
|
||||||
|
_token.mint(user0, minimalDeposit);
|
||||||
|
vm.startPrank(user0);
|
||||||
|
_token.approve(address(smallRLN), minimalDeposit);
|
||||||
|
smallRLN.register(identityCommitment0, minimalDeposit);
|
||||||
|
vm.stopPrank();
|
||||||
|
// Register the second user
|
||||||
|
_token.mint(user1, minimalDeposit);
|
||||||
|
vm.startPrank(user1);
|
||||||
|
_token.approve(address(smallRLN), minimalDeposit);
|
||||||
|
smallRLN.register(identityCommitment1, minimalDeposit);
|
||||||
|
vm.stopPrank();
|
||||||
|
// Now tree (set) is full. Try register the third. It should revert.
|
||||||
|
address user2 = makeAddr("user2");
|
||||||
|
uint256 identityCommitment2 = 9999;
|
||||||
|
token.mint(user2, minimalDeposit);
|
||||||
|
vm.startPrank(user2);
|
||||||
|
token.approve(address(smallRLN), minimalDeposit);
|
||||||
|
// `register` should revert
|
||||||
|
vm.expectRevert("RLN, register: set is full");
|
||||||
|
smallRLN.register(identityCommitment2, minimalDeposit);
|
||||||
|
vm.stopPrank();
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_register_fails_when_amount_lt_minimal_deposit() public {
|
||||||
|
uint256 insufficientAmount = minimalDeposit - 1;
|
||||||
|
token.mint(user0, rlnInitialTokenBalance);
|
||||||
|
vm.startPrank(user0);
|
||||||
|
token.approve(address(rln), rlnInitialTokenBalance);
|
||||||
|
vm.expectRevert("RLN, register: amount is lower than minimal deposit");
|
||||||
|
rln.register(identityCommitment0, insufficientAmount);
|
||||||
|
vm.stopPrank();
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_register_fails_when_duplicate_identity_commitments() public {
|
||||||
|
// Register first with user0 with identityCommitment0
|
||||||
|
register(user0, identityCommitment0, messageLimit0);
|
||||||
|
// Register again with user1 with identityCommitment0
|
||||||
|
token.mint(user1, rlnInitialTokenBalance);
|
||||||
|
vm.startPrank(user1);
|
||||||
|
token.approve(address(rln), rlnInitialTokenBalance);
|
||||||
|
// `register` should revert
|
||||||
|
vm.expectRevert("RLN, register: idCommitment already registered");
|
||||||
|
rln.register(identityCommitment0, rlnInitialTokenBalance);
|
||||||
|
vm.stopPrank();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* withdraw */
|
||||||
|
|
||||||
|
function test_withdraw_succeeds() public {
|
||||||
|
// Register first
|
||||||
|
register(user0, identityCommitment0, messageLimit0);
|
||||||
|
// Make sure proof verification is skipped
|
||||||
|
assertEq(verifier.result(), true);
|
||||||
|
|
||||||
|
// Withdraw user0
|
||||||
|
// Ensure event is emitted
|
||||||
|
(,, uint256 index) = rln.members(identityCommitment0);
|
||||||
|
vm.expectEmit(true, true, false, true);
|
||||||
|
emit MemberWithdrawn(index);
|
||||||
|
rln.withdraw(identityCommitment0, mockProof);
|
||||||
|
// Check withdrawal entry is set correctly
|
||||||
|
(uint256 blockNumber, uint256 amount, address receiver) = rln.withdrawals(identityCommitment0);
|
||||||
|
assertEq(blockNumber, block.number);
|
||||||
|
assertEq(amount, getRegisterAmount(messageLimit0));
|
||||||
|
assertEq(receiver, user0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_withdraw_fails_when_not_registered() public {
|
||||||
|
// Withdraw fails if the user has not registered before
|
||||||
|
vm.expectRevert("RLN, withdraw: member doesn't exist");
|
||||||
|
rln.withdraw(identityCommitment0, mockProof);
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_withdraw_fails_when_already_underways() public {
|
||||||
|
// Register first
|
||||||
|
register(user0, identityCommitment0, messageLimit0);
|
||||||
|
// Withdraw user0
|
||||||
|
rln.withdraw(identityCommitment0, mockProof);
|
||||||
|
// Withdraw again and it should fail
|
||||||
|
vm.expectRevert("RLN, release: such withdrawal exists");
|
||||||
|
rln.withdraw(identityCommitment0, mockProof);
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_withdraw_fails_when_invalid_proof() public {
|
||||||
|
// Register first
|
||||||
|
register(user0, identityCommitment0, messageLimit0);
|
||||||
|
// Make sure mock verifier always return false
|
||||||
|
// And thus the proof is always considered invalid
|
||||||
|
verifier.changeResult(false);
|
||||||
|
assertEq(verifier.result(), false);
|
||||||
|
vm.expectRevert("RLN, withdraw: invalid proof");
|
||||||
|
rln.withdraw(identityCommitment0, mockProof);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* release */
|
||||||
|
|
||||||
|
function test_release_succeeds() public {
|
||||||
|
// Register first
|
||||||
|
register(user0, identityCommitment0, messageLimit0);
|
||||||
|
// Withdraw user0
|
||||||
|
// Make sure proof verification is skipped
|
||||||
|
assertEq(verifier.result(), true);
|
||||||
|
rln.withdraw(identityCommitment0, mockProof);
|
||||||
|
|
||||||
|
// Test: release succeeds after freeze period
|
||||||
|
// Set block.number to `blockNumbersToRelease`
|
||||||
|
uint256 blockNumbersToRelease = getUnfrozenBlockHeight();
|
||||||
|
vm.roll(blockNumbersToRelease);
|
||||||
|
|
||||||
|
uint256 user0BalanceBefore = token.balanceOf(user0);
|
||||||
|
uint256 rlnBalanceBefore = token.balanceOf(address(rln));
|
||||||
|
// Calls release and check balances
|
||||||
|
rln.release(identityCommitment0);
|
||||||
|
uint256 user0BalanceDiff = token.balanceOf(user0) - user0BalanceBefore;
|
||||||
|
uint256 rlnBalanceDiff = rlnBalanceBefore - token.balanceOf(address(rln));
|
||||||
|
uint256 expectedUser0BalanceDiff = getRegisterAmount(messageLimit0);
|
||||||
|
assertEq(user0BalanceDiff, expectedUser0BalanceDiff);
|
||||||
|
assertEq(rlnBalanceDiff, expectedUser0BalanceDiff);
|
||||||
|
checkUserIsDeleted(identityCommitment0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_release_fails_when_no_withdrawal() public {
|
||||||
|
// Release fails if there is no withdrawal for the user
|
||||||
|
vm.expectRevert("RLN, release: no such withdrawals");
|
||||||
|
rln.release(identityCommitment0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_release_fails_when_freeze_period() public {
|
||||||
|
// Register first
|
||||||
|
register(user0, identityCommitment0, messageLimit0);
|
||||||
|
// Make sure mock verifier always return true to skip proof verification
|
||||||
|
assertEq(verifier.result(), true);
|
||||||
|
// Withdraw user0
|
||||||
|
rln.withdraw(identityCommitment0, mockProof);
|
||||||
|
// Ensure withdrawal is set
|
||||||
|
(uint256 blockNumber, uint256 amount, address receiver) = rln.withdrawals(identityCommitment0);
|
||||||
|
assertEq(blockNumber, block.number);
|
||||||
|
assertEq(amount, getRegisterAmount(messageLimit0));
|
||||||
|
assertEq(receiver, user0);
|
||||||
|
|
||||||
|
// Test: release fails in freeze period
|
||||||
|
vm.expectRevert("RLN, release: cannot release yet");
|
||||||
|
rln.release(identityCommitment0);
|
||||||
|
// Set block.number to blockNumbersToRelease - 1, which is still in freeze period
|
||||||
|
uint256 blockNumbersToRelease = getUnfrozenBlockHeight();
|
||||||
|
vm.roll(blockNumbersToRelease - 1);
|
||||||
|
vm.expectRevert("RLN, release: cannot release yet");
|
||||||
|
rln.release(identityCommitment0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* slash */
|
||||||
|
|
||||||
|
function test_slash_succeeds() public {
|
||||||
|
// Test: register and get slashed
|
||||||
|
register(user0, identityCommitment0, messageLimit0);
|
||||||
|
uint256 registerAmount = getRegisterAmount(messageLimit0);
|
||||||
|
uint256 slashFee = getSlashFee(registerAmount);
|
||||||
|
uint256 slashReward = registerAmount - slashFee;
|
||||||
|
uint256 slashedReceiverBalanceBefore = token.balanceOf(slashedReceiver);
|
||||||
|
uint256 rlnBalanceBefore = token.balanceOf(address(rln));
|
||||||
|
uint256 feeReceiverBalanceBefore = token.balanceOf(feeReceiver);
|
||||||
|
// ensure event is emitted
|
||||||
|
(,, uint256 index) = rln.members(identityCommitment0);
|
||||||
|
vm.expectEmit(true, true, false, true);
|
||||||
|
emit MemberSlashed(index, slashedReceiver);
|
||||||
|
// Slash and check balances
|
||||||
|
rln.slash(identityCommitment0, slashedReceiver, mockProof);
|
||||||
|
uint256 slashedReceiverBalanceDiff = token.balanceOf(slashedReceiver) - slashedReceiverBalanceBefore;
|
||||||
|
uint256 rlnBalanceDiff = rlnBalanceBefore - token.balanceOf(address(rln));
|
||||||
|
uint256 feeReceiverBalanceDiff = token.balanceOf(feeReceiver) - feeReceiverBalanceBefore;
|
||||||
|
assertEq(slashedReceiverBalanceDiff, slashReward);
|
||||||
|
assertEq(rlnBalanceDiff, registerAmount);
|
||||||
|
assertEq(feeReceiverBalanceDiff, slashFee);
|
||||||
|
// Check the record of user0 has been deleted
|
||||||
|
checkUserIsDeleted(identityCommitment0);
|
||||||
|
|
||||||
|
// Test: register, withdraw, ang get slashed before release
|
||||||
|
register(user1, identityCommitment1, messageLimit1);
|
||||||
|
rln.withdraw(identityCommitment1, mockProof);
|
||||||
|
rln.slash(identityCommitment1, slashedReceiver, mockProof);
|
||||||
|
// Check the record of user1 has been deleted
|
||||||
|
checkUserIsDeleted(identityCommitment1);
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_slash_fails_when_receiver_is_zero() public {
|
||||||
|
// Register first
|
||||||
|
register(user0, identityCommitment0, messageLimit0);
|
||||||
|
// Try slash user0 and it fails because of the zero address
|
||||||
|
vm.expectRevert("RLN, slash: empty receiver address");
|
||||||
|
rln.slash(identityCommitment0, address(0), mockProof);
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_slash_fails_when_not_registered() public {
|
||||||
|
// It fails if the user is not registered yet
|
||||||
|
vm.expectRevert("RLN, slash: member doesn't exist");
|
||||||
|
rln.slash(identityCommitment0, slashedReceiver, mockProof);
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_slash_fails_when_self_slashing() public {
|
||||||
|
// `slash` fails when receiver is the same as the registered msg.sender
|
||||||
|
register(user0, identityCommitment0, messageLimit0);
|
||||||
|
vm.expectRevert("RLN, slash: self-slashing is prohibited");
|
||||||
|
rln.slash(identityCommitment0, user0, mockProof);
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_slash_fails_when_invalid_proof() public {
|
||||||
|
// It fails if the proof is invalid
|
||||||
|
// Register first
|
||||||
|
register(user0, identityCommitment0, messageLimit0);
|
||||||
|
// Make sure mock verifier always return false
|
||||||
|
// And thus the proof is always considered invalid
|
||||||
|
verifier.changeResult(false);
|
||||||
|
assertEq(verifier.result(), false);
|
||||||
|
vm.expectRevert("RLN, slash: invalid proof");
|
||||||
|
// Slash fails because of the invalid proof
|
||||||
|
rln.slash(identityCommitment0, slashedReceiver, mockProof);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Helpers */
|
||||||
|
function getRegisterAmount(uint256 messageLimit) public view returns (uint256) {
|
||||||
|
return messageLimit * minimalDeposit;
|
||||||
|
}
|
||||||
|
|
||||||
|
function register(address user, uint256 identityCommitment, uint256 messageLimit) public {
|
||||||
|
// Mint to user first
|
||||||
|
uint256 registerTokenAmount = getRegisterAmount(messageLimit);
|
||||||
|
token.mint(user, registerTokenAmount);
|
||||||
|
// Remember the balance for later check
|
||||||
|
uint256 tokenRLNBefore = token.balanceOf(address(rln));
|
||||||
|
uint256 tokenUserBefore = token.balanceOf(user);
|
||||||
|
uint256 identityCommitmentIndexBefore = rln.identityCommitmentIndex();
|
||||||
|
// User approves to rln and calls register
|
||||||
|
vm.startPrank(user);
|
||||||
|
token.approve(address(rln), registerTokenAmount);
|
||||||
|
// Ensure event is emitted
|
||||||
|
vm.expectEmit(true, true, false, true);
|
||||||
|
emit MemberRegistered(identityCommitment, messageLimit, identityCommitmentIndexBefore);
|
||||||
|
rln.register(identityCommitment, registerTokenAmount);
|
||||||
|
vm.stopPrank();
|
||||||
|
|
||||||
|
// Check states
|
||||||
|
uint256 tokenRLNDiff = token.balanceOf(address(rln)) - tokenRLNBefore;
|
||||||
|
uint256 tokenUserDiff = tokenUserBefore - token.balanceOf(user);
|
||||||
|
// RLN state
|
||||||
|
assertEq(rln.identityCommitmentIndex(), identityCommitmentIndexBefore + 1);
|
||||||
|
assertEq(tokenRLNDiff, registerTokenAmount);
|
||||||
|
// User state
|
||||||
|
(address userAddress, uint256 actualMessageLimit, uint256 index) = rln.members(identityCommitment);
|
||||||
|
assertEq(userAddress, user);
|
||||||
|
assertEq(actualMessageLimit, messageLimit);
|
||||||
|
assertEq(index, identityCommitmentIndexBefore);
|
||||||
|
assertEq(tokenUserDiff, registerTokenAmount);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getUnfrozenBlockHeight() public view returns (uint256) {
|
||||||
|
return block.number + freezePeriod + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkUserIsDeleted(uint256 identityCommitment) public {
|
||||||
|
// User state
|
||||||
|
(address userAddress, uint256 actualMessageLimit, uint256 index) = rln.members(identityCommitment);
|
||||||
|
assertEq(userAddress, address(0));
|
||||||
|
assertEq(actualMessageLimit, 0);
|
||||||
|
assertEq(index, 0);
|
||||||
|
// Withdrawal state
|
||||||
|
(uint256 blockNumber, uint256 amount, address receiver) = rln.withdrawals(identityCommitment);
|
||||||
|
assertEq(blockNumber, 0);
|
||||||
|
assertEq(amount, 0);
|
||||||
|
assertEq(receiver, address(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSlashFee(uint256 registerAmount) public view returns (uint256) {
|
||||||
|
return registerAmount * feePercentage / 100;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user