@@ -10,7 +10,7 @@ import {
1010 RocketMinipoolPenalty ,
1111 RocketNetworkPenalties ,
1212 RocketNodeDeposit ,
13- RocketNodeManager ,
13+ RocketNodeManager , RocketNodeStaking ,
1414} from '../../test/_utils/artifacts' ;
1515import { shouldRevert } from '../../test/_utils/testing' ;
1616import { createVacantMinipool , minipoolStates , promoteMinipool , stakeMinipool } from '../../test/_helpers/minipool' ;
@@ -21,6 +21,8 @@ import { getValidatorPubkey } from '../../test/_utils/beacon';
2121import { deployMegapool } from '../../test/_helpers/megapool' ;
2222import { beginUserDistribute , withdrawValidatorBalance } from '../../test/minipool/scenario-withdraw-validator-balance' ;
2323import { setDAOProtocolBootstrapSetting } from '../../test/dao/scenario-dao-protocol-bootstrap' ;
24+ import { close } from '../../test/minipool/scenario-close' ;
25+ import { unstakeLegacyRpl } from '../../test/node/scenario-unstake-legacy-rpl' ;
2426const { assertBN } = require ( '../../test/_helpers/bn' ) ;
2527const { beforeEach, describe, before, it } = require ( 'mocha' ) ;
2628const { globalSnapShot } = require ( '../../test/_utils/snapshotting' ) ;
@@ -236,7 +238,7 @@ export default function() {
236238 await setNodeTrusted ( trustedNode3 , 'saas_3' , 'node@home.com' , owner ) ;
237239 // Set max penalty rate
238240 let rocketMinipoolPenalty = await RocketMinipoolPenalty . deployed ( ) ;
239- rocketMinipoolPenalty . setMaxPenaltyRate ( '1' . ether , { from : owner } ) ;
241+ await rocketMinipoolPenalty . connect ( owner ) . setMaxPenaltyRate ( '1' . ether ) ;
240242 } )
241243
242244 it ( printTitle ( 'node' , 'can not bond reduce after upgrade' ) , async ( ) => {
@@ -265,6 +267,24 @@ export default function() {
265267 await withdrawAndCheck ( minipool , '36' , node , false , '17.8' , '18.2' ) ;
266268 } ) ;
267269
270+ it ( printTitle ( 'node' , 'can exit a staking minipool and get slashed below minimum RPL requirement' ) , async ( ) => {
271+ const rocketNodeStaking = await RocketNodeStaking . deployed ( )
272+ const stakedRPLBefore = await rocketNodeStaking . getNodeLegacyStakedRPL ( node . address )
273+ await withdrawAndCheck ( minipool , '15' , node , false , '15' , '0' ) ;
274+ const stakedRPLAfter = await rocketNodeStaking . getNodeLegacyStakedRPL ( node . address )
275+ // RPL price is 0.01 ETH so should slash 100 RPL
276+ assertBN . equal ( stakedRPLBefore - stakedRPLAfter , '100' . ether ) ;
277+ } ) ;
278+
279+ it ( printTitle ( 'node' , 'can be slashed greater than legacy staked RPL balance' ) , async ( ) => {
280+ const rocketNodeStaking = await RocketNodeStaking . deployed ( )
281+ // Return 10 ETH which results int 600 RPL slashing
282+ await withdrawAndCheck ( minipool , '10' , node , false , '10' , '0' ) ;
283+ const stakedRPLAfter = await rocketNodeStaking . getNodeLegacyStakedRPL ( node . address )
284+ // RPL price is 0.01 ETH so should slash 100 RPL
285+ assertBN . equal ( stakedRPLAfter , 0n ) ;
286+ } ) ;
287+
268288 it ( printTitle ( 'trusted node' , 'can submit minipool penalties' ) , async ( ) => {
269289 let minipoolAddress = minipool . target ;
270290 const rocketNetworkPenalties = await RocketNetworkPenalties . deployed ( )
@@ -300,5 +320,64 @@ export default function() {
300320 } )
301321
302322 } )
323+
324+ describe ( 'With multiple staking legacy minipool' , ( ) => {
325+ let minipool1 ,
326+ minipool2 ,
327+ minipool3
328+
329+ beforeEach ( async ( ) => {
330+ // Register node and create a 16 ETH minipool
331+ await registerNode ( { from : node } ) ;
332+ const minipoolRplStake = await getMinipoolMinimumRPLStake ( ) ;
333+ await mintRPL ( owner , node , minipoolRplStake * 3n ) ;
334+ await stakeRPL ( node , minipoolRplStake * 3n ) ;
335+ minipool1 = ( await createMinipool ( { from : node , value : '16' . ether } ) ) . connect ( node ) ;
336+ minipool2 = ( await createMinipool ( { from : node , value : '16' . ether } ) ) . connect ( node ) ;
337+ minipool3 = ( await createMinipool ( { from : node , value : '16' . ether } ) ) . connect ( node ) ;
338+ // Execute upgrade
339+ await executeUpgrade ( owner , upgradeContract , rocketStorageAddress ) ;
340+ // Perform 3 user deposit that will assign all 3 minipools
341+ await userDeposit ( { from : random , value : '32' . ether } ) ;
342+ await userDeposit ( { from : random , value : '32' . ether } ) ;
343+ await userDeposit ( { from : random , value : '32' . ether } ) ;
344+ // Wait for scrub period
345+ await helpers . time . increase ( 60 * 60 * 12 + 1 )
346+ // Stake
347+ await stakeMinipool ( minipool1 , { from : node } )
348+ await stakeMinipool ( minipool2 , { from : node } )
349+ await stakeMinipool ( minipool3 , { from : node } )
350+ // Register trusted nodes
351+ await registerNode ( { from : trustedNode1 } ) ;
352+ await registerNode ( { from : trustedNode2 } ) ;
353+ await registerNode ( { from : trustedNode3 } ) ;
354+ await setNodeTrusted ( trustedNode1 , 'saas_1' , 'node@home.com' , owner ) ;
355+ await setNodeTrusted ( trustedNode2 , 'saas_2' , 'node@home.com' , owner ) ;
356+ await setNodeTrusted ( trustedNode3 , 'saas_3' , 'node@home.com' , owner ) ;
357+ // Set max penalty rate
358+ let rocketMinipoolPenalty = await RocketMinipoolPenalty . deployed ( ) ;
359+ await rocketMinipoolPenalty . connect ( owner ) . setMaxPenaltyRate ( '1' . ether ) ;
360+ } )
361+
362+ it ( printTitle ( 'node' , 'can not unstake legacy staked RPL while below minimum after slashing' ) , async ( ) => {
363+ const rocketNodeStaking = await RocketNodeStaking . deployed ( )
364+ const stakedRPLBefore = await rocketNodeStaking . getNodeLegacyStakedRPL ( node . address )
365+ await withdrawAndCheck ( minipool1 , '15' , node , false , '15' , '0' ) ;
366+ // Try to unstake 100 RPL which would bring node operator under requirement
367+ await shouldRevert (
368+ unstakeLegacyRpl ( '100' . ether , { from : node } ) ,
369+ 'Was able to unstake while below 15% minimum' ,
370+ 'Insufficient legacy staked RPL'
371+ ) ;
372+ // Exit other 2 validators with further 200 RPL slashing
373+ await withdrawAndCheck ( minipool2 , '15' , node , false , '15' , '0' ) ;
374+ await withdrawAndCheck ( minipool3 , '15' , node , false , '15' , '0' ) ;
375+ // User should have been slashed 300 RPL in total
376+ const stakedRPLAfter = await rocketNodeStaking . getNodeLegacyStakedRPL ( node . address )
377+ assertBN . equal ( stakedRPLBefore - stakedRPLAfter , '300' . ether ) ;
378+ // Withdraw remaining
379+ await unstakeLegacyRpl ( stakedRPLAfter , { from : node } )
380+ } ) ;
381+ } )
303382 } ) ;
304383}
0 commit comments