Skip to content

Commit 2d05dc3

Browse files
author
Valdorff
committed
Enable arbitrage on minipool exit
- Non-owners must now do a 2-step process to distribute - The balance and status must meet requirements for non-owner distribution during each of the steps - There is an enforced minimum 14 days between the two steps, so the owner has plenty of time to arb if desired
1 parent 24e7a6e commit 2d05dc3

File tree

1 file changed

+28
-12
lines changed

1 file changed

+28
-12
lines changed

contracts/contract/minipool/RocketMinipoolDelegate.sol

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,8 @@ contract RocketMinipoolDelegate is RocketMinipoolStorageLayout, RocketMinipoolIn
124124
rocketMinipoolPenalty = getContractAddress("rocketMinipoolPenalty");
125125
// Intialise storage state
126126
storageState = StorageState.Initialised;
127+
// Initialise non-owner distribute prep time
128+
prepareNonOwnerDistributeTime = 0;
127129
}
128130

129131
// Assign the node deposit to the minipool
@@ -282,8 +284,9 @@ contract RocketMinipoolDelegate is RocketMinipoolStorageLayout, RocketMinipoolIn
282284
}
283285

284286
// Distributes the contract's balance
285-
// When called during staking status, requires 16 ether in the pool
286-
// When called by non-owner with less than 16 ether, requires 14 days to have passed since being made withdrawable
287+
// - Can normally only be called by owner
288+
// - To handle cases where an owner _doesn't_ call this, anyone can call this if they first
289+
// call prepareNonOwnerDistribute() and wait 14 days.
287290
function distributeBalance() override external onlyInitialised {
288291
// Must be called while staking or withdrawable
289292
require(status == MinipoolStatus.Staking || status == MinipoolStatus.Withdrawable, "Minipool must be staking or withdrawable");
@@ -293,21 +296,34 @@ contract RocketMinipoolDelegate is RocketMinipoolStorageLayout, RocketMinipoolIn
293296
address nodeWithdrawalAddress = rocketStorage.getNodeWithdrawalAddress(nodeAddress);
294297
// If it's not the owner calling
295298
if (msg.sender != nodeAddress && msg.sender != nodeWithdrawalAddress) {
296-
// And the pool is in staking status
297-
if (status == MinipoolStatus.Staking) {
298-
// Then balance must be greater than 16 ETH
299-
require(totalBalance >= 16 ether, "Balance must be greater than 16 ETH");
300-
} else {
301-
// Then enough time must have elapsed
302-
require(block.timestamp > statusTime.add(14 days), "Non-owner must wait 14 days after withdrawal to distribute balance");
303-
// And balance must be greater than 4 ETH
304-
require(address(this).balance >= 4 ether, "Balance must be greater than 4 ETH");
305-
}
299+
require(_canNonOwnerDistribute(), "Minipool doesn't meet conditions to allow non-owner distribution");
300+
require(prepareNonOwnerDistributeTime != 0, "prepareNonOwnerDistribute must be called before distributeBalance");
301+
require(block.timestamp > prepareNonOwnerDistributeTime.add(14 days), "prepareNonOwnerDistribute must be called at least 14 days before distributeBalance");
306302
}
307303
// Process withdrawal
308304
_distributeBalance(totalBalance);
309305
}
310306

307+
// Non-owner distribution has two steps
308+
// First, this function is called
309+
// Then, after at least 14 days, distributeBalance() can be called
310+
function prepareNonOwnerDistribute() override external onlyInitialised {
311+
require(_canNonOwnerDistribute(), "Minipool doesn't meet conditions to allow non-owner distribution");
312+
prepareNonOwnerDistributeTime = block.timestamp;
313+
}
314+
315+
// Returns true when conditions allow for non-owner distribution
316+
// Note that this gets checked by both prepareNonOwnerDistribute and distributeBalacnce
317+
function _canNonOwnerDistribute() override external view onlyInitialised returns (bool) {
318+
if (status == MinipoolStatus.Staking && totalBalance >= 16 ether) {
319+
return true;
320+
} else if (status == MinipoolStatus.Withdrawable && address(this).balance >= 4 ether) {
321+
// TODO: Why doesn't this use totalBalance? I copied from previous version
322+
return true;
323+
}
324+
return false;
325+
}
326+
311327
// Perform any slashings, refunds, and unlock NO's stake
312328
function _finalise() private {
313329
// Get contracts

0 commit comments

Comments
 (0)