-
Notifications
You must be signed in to change notification settings - Fork 5
IPC-361: Pre-release and minor fixes #271
Changes from 5 commits
745b5a5
097b57a
6305aef
cc225d8
c36cccc
3fbf215
12a8f6d
8e4db46
217159f
f2b97f9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,7 @@ | ||
// SPDX-License-Identifier: MIT OR Apache-2.0 | ||
pragma solidity 0.8.19; | ||
|
||
import {SubnetAlreadyBootstrapped, NotEnoughFunds, CollateralIsZero, CannotReleaseZero, NotOwnerOfPublicKey, EmptyAddress, NotEnoughBalanceForRewards, NotEnoughCollateral, NotValidator, NotAllValidatorsHaveLeft, NotStakedBefore, InvalidSignatureErr, InvalidCheckpointEpoch, InvalidCheckpointMessagesHash, InvalidPublicKeyLength} from "../errors/IPCErrors.sol"; | ||
import {SubnetAlreadyBootstrapped, NotEnoughFunds, CollateralIsZero, CannotReleaseZero, NotOwnerOfPublicKey, EmptyAddress, NotEnoughBalance, NotEnoughBalanceForRewards, NotEnoughCollateral, NotValidator, NotAllValidatorsHaveLeft, NotStakedBefore, InvalidSignatureErr, InvalidCheckpointEpoch, InvalidCheckpointMessagesHash, InvalidPublicKeyLength} from "../errors/IPCErrors.sol"; | ||
import {IGateway} from "../interfaces/IGateway.sol"; | ||
import {ISubnetActor} from "../interfaces/ISubnetActor.sol"; | ||
import {BottomUpCheckpoint, CrossMsg} from "../structs/Checkpoint.sol"; | ||
|
@@ -109,6 +109,31 @@ | |
s.genesisCircSupply += msg.value; | ||
} | ||
|
||
/// @notice method to remove funds from the initial balance of a subnet. | ||
/// @dev This method can be used by users looking to recover part of their | ||
/// initial balance before the subnet bootstraps. | ||
function preRelease(uint256 amount) external nonReentrant { | ||
if (amount == 0) { | ||
revert NotEnoughFunds(); | ||
} | ||
|
||
if (s.bootstrapped) { | ||
revert SubnetAlreadyBootstrapped(); | ||
} | ||
|
||
if (s.genesisBalance[msg.sender] == 0) { | ||
adlrocha marked this conversation as resolved.
Show resolved
Hide resolved
|
||
revert NotEnoughBalance(); | ||
} | ||
|
||
s.genesisBalance[msg.sender] -= amount; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I guess this can't go negative, right? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It reverts on underflow/overflow There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These are In spite of this, do you think we should add a sanity-check just to be safe? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, okay, I recommended the |
||
s.genesisCircSupply -= amount; | ||
|
||
if (s.genesisBalance[msg.sender] == 0) { | ||
rmAddressFromBalanceKey(msg.sender); | ||
payable(msg.sender).sendValue(amount); | ||
adlrocha marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
} | ||
|
||
/// @notice method that allows a validator to join the subnet | ||
/// @param publicKey The off-chain 65 byte public key that should be associated with the validator | ||
function join(bytes calldata publicKey) external payable nonReentrant notKilled { | ||
|
@@ -196,7 +221,9 @@ | |
} | ||
|
||
/// @notice method that allows a validator to leave the subnet | ||
function leave() external notKilled { | ||
/// @dev it also return the validators initial balance if the | ||
/// subnet was not yet bootstrapped. | ||
function leave() external notKilled nonReentrant { | ||
// remove bootstrap nodes added by this validator | ||
|
||
uint256 amount = LibStaking.totalValidatorCollateral(msg.sender); | ||
|
@@ -210,6 +237,15 @@ | |
|
||
if (!s.bootstrapped) { | ||
LibStaking.withdrawWithConfirm(msg.sender, amount); | ||
|
||
// check if the validator had some initial balance and return it if not bootstrapped | ||
uint256 genesisBalance = s.genesisBalance[msg.sender]; | ||
if (genesisBalance != 0) { | ||
s.genesisBalance[msg.sender] == 0; | ||
s.genesisCircSupply -= genesisBalance; | ||
rmAddressFromBalanceKey(msg.sender); | ||
payable(msg.sender).sendValue(genesisBalance); | ||
} | ||
return; | ||
} | ||
LibStaking.withdraw(msg.sender, amount); | ||
|
@@ -319,4 +355,20 @@ | |
bytes32 hashed = keccak256(publicKey[1:]); | ||
return address(uint160(uint256(hashed))); | ||
} | ||
|
||
/// @notice Removes an address from the initial balance keys | ||
function rmAddressFromBalanceKey(address addr) internal { | ||
uint length = s.genesisBalanceKeys.length; | ||
for (uint i = 0; i < length; ) { | ||
if (s.genesisBalanceKeys[i] == addr) { | ||
s.genesisBalanceKeys[i] = s.genesisBalanceKeys[length - 1]; | ||
s.genesisBalanceKeys.pop(); | ||
// exit after removing the key | ||
break; | ||
} | ||
unchecked { | ||
++i; | ||
} | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's see if I understand this: the stake is added to the gateway in one go when the subnet registers itself, right? So it makes sense that before that, this should not be trying to release anything.
Strange we haven't caught any issues with this 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know. I feel that there were a bunch of tests that were commented so we lost track of this. But I included a few to catch it. Good that you raised this issue, as it already uncovered this bug :)