Skip to content

Commit

Permalink
Generalize governance to stake changes subscriber
Browse files Browse the repository at this point in the history
  • Loading branch information
thaarok committed Nov 7, 2024
1 parent e964bc0 commit 1e3457c
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 28 deletions.
2 changes: 1 addition & 1 deletion contracts/interfaces/ISFC.sol
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ interface ISFC {

function setGenesisDelegation(address delegator, uint256 toValidatorID, uint256 stake) external;

function updateVoteBookAddress(address v) external;
function updateStakeSubscriberAddress(address v) external;

function voteBookAddress() external view returns (address);

Expand Down
42 changes: 15 additions & 27 deletions contracts/sfc/SFC.sol
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,8 @@ contract SFC is Initializable, Ownable, Version {

ConstantsManager internal c;

// the governance contract (to recalculate votes when the stake changes)
address public voteBookAddress;
// the contract subscribed to stake changes notifications
address public stakeSubscriberAddress;

// address derived from the validator pubkey => validator id
mapping(address pubkeyAddress => uint256 validatorID) public pubkeyAddressToValidatorID;
Expand Down Expand Up @@ -161,8 +161,8 @@ contract SFC is Initializable, Ownable, Version {
error TransfersNotAllowed();
error TransferFailed();

// governance
error GovVotesRecountFailed();
// stake changes subscriber
error StateSubscriberFailed();

// staking
error InsufficientSelfStake();
Expand Down Expand Up @@ -369,18 +369,6 @@ contract SFC is Initializable, Ownable, Version {
emit UpdatedSlashingRefundRatio(validatorID, refundRatio);
}

/// Recount votes for a delegator and a validator.
/// Forces applying validators weights changes in governance voting.
function recountVotes(address delegator, address validatorAuth, bool strict, uint256 gas) external {
// solhint-disable-next-line avoid-low-level-calls
(bool success, ) = voteBookAddress.call{gas: gas}(
abi.encodeWithSignature("recountVotes(address,address)", delegator, validatorAuth)
);
if (!success && strict) {
revert GovVotesRecountFailed();
}
}

/// Delegate stake to a validator.
function delegate(uint256 toValidatorID) external payable {
_delegate(msg.sender, toValidatorID, msg.value);
Expand All @@ -402,7 +390,7 @@ contract SFC is Initializable, Ownable, Version {
_setValidatorDeactivated(validatorID, status);
_syncValidator(validatorID, false);
address validatorAddr = getValidator[validatorID].auth;
_recountVotes(validatorAddr, validatorAddr, false);
_notifyStakeSubscriber(validatorAddr, validatorAddr, false);
}

/// Stash rewards for a delegator.
Expand All @@ -428,8 +416,8 @@ contract SFC is Initializable, Ownable, Version {
}

/// Update voteBook address.
function updateVoteBookAddress(address v) external onlyOwner {
voteBookAddress = v;
function updateStakeSubscriberAddress(address v) external onlyOwner {
stakeSubscriberAddress = v;
}

/// Get consts address.
Expand Down Expand Up @@ -598,7 +586,7 @@ contract SFC is Initializable, Ownable, Version {

emit Delegated(delegator, toValidatorID, amount);

_recountVotes(delegator, getValidator[toValidatorID].auth, strict);
_notifyStakeSubscriber(delegator, getValidator[toValidatorID].auth, strict);
}

/// Un-delegate stake from a validator.
Expand Down Expand Up @@ -633,7 +621,7 @@ contract SFC is Initializable, Ownable, Version {
_setValidatorDeactivated(toValidatorID, WITHDRAWN_BIT);
}

_recountVotes(delegator, getValidator[toValidatorID].auth, strict);
_notifyStakeSubscriber(delegator, getValidator[toValidatorID].auth, strict);
}

/// Get slashing penalty for a stake.
Expand Down Expand Up @@ -977,16 +965,16 @@ contract SFC is Initializable, Ownable, Version {

/// Recount votes for a delegator and a validator.
/// Force applying validators weights changes in governance voting.
function _recountVotes(address delegator, address validatorAuth, bool strict) internal {
if (voteBookAddress != address(0)) {
function _notifyStakeSubscriber(address delegator, address validatorAuth, bool strict) internal {
if (stakeSubscriberAddress != address(0)) {
// Don't allow recountVotes to use up all the gas
// solhint-disable-next-line avoid-low-level-calls
(bool success, ) = voteBookAddress.call{gas: 8000000}(
abi.encodeWithSignature("recountVotes(address,address)", delegator, validatorAuth)
(bool success, ) = stakeSubscriberAddress.call{gas: 8000000}(
abi.encodeWithSignature("announceStakeChange(address,address)", delegator, validatorAuth)
);
// Don't revert if recountVotes failed unless strict mode enabled
// Don't revert if announceStakeChange failed unless strict mode enabled
if (!success && strict) {
revert GovVotesRecountFailed();
revert StateSubscriberFailed();
}
}
}
Expand Down

0 comments on commit 1e3457c

Please sign in to comment.