Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 47 additions & 10 deletions solidity/ecdsa/contracts/WalletRegistry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,8 @@ contract WalletRegistry is

event AuthorizationParametersUpdated(
uint96 minimumAuthorization,
uint64 authorizationDecreaseDelay
uint64 authorizationDecreaseDelay,
uint64 authorizationDecreaseChangePeriod
);

event RewardParametersUpdated(
Expand Down Expand Up @@ -263,6 +264,7 @@ contract WalletRegistry is
// slither-disable-next-line too-many-digits
authorization.setMinimumAuthorization(400000e18); // 400k T
authorization.setAuthorizationDecreaseDelay(5184000); // 60 days
authorization.setAuthorizationDecreaseChangePeriod(5184000);

dkg.init(_sortitionPool, _ecdsaDkgValidator);
dkg.setSeedTimeout(1440); // ~6h assuming 15s block time
Expand Down Expand Up @@ -457,18 +459,25 @@ contract WalletRegistry is
/// @param _minimumAuthorization New minimum authorization amount
/// @param _authorizationDecreaseDelay New authorization decrease delay in
/// seconds
/// @param _authorizationDecreaseChangePeriod New authorization decrease
/// change period in seconds
function updateAuthorizationParameters(
uint96 _minimumAuthorization,
uint64 _authorizationDecreaseDelay
uint64 _authorizationDecreaseDelay,
uint64 _authorizationDecreaseChangePeriod
) external onlyGovernance {
authorization.setMinimumAuthorization(_minimumAuthorization);
authorization.setAuthorizationDecreaseDelay(
_authorizationDecreaseDelay
);
authorization.setAuthorizationDecreaseChangePeriod(
_authorizationDecreaseChangePeriod
);

emit AuthorizationParametersUpdated(
_minimumAuthorization,
_authorizationDecreaseDelay
_authorizationDecreaseDelay,
_authorizationDecreaseChangePeriod
);
}

Expand Down Expand Up @@ -951,13 +960,6 @@ contract WalletRegistry is
return authorization.parameters.minimumAuthorization;
}

/// @notice Delay in seconds that needs to pass between the time
/// authorization decrease is requested and the time that request
/// can get approved.
function authorizationDecreaseDelay() external view returns (uint64) {
return authorization.parameters.authorizationDecreaseDelay;
}

/// @notice Returns the current value of the staking provider's eligible
/// stake. Eligible stake is defined as the currently authorized
/// stake minus the pending authorization decrease. Eligible stake
Expand Down Expand Up @@ -1057,6 +1059,41 @@ contract WalletRegistry is
return dkg.parameters;
}

/// @notice Returns authorization-related parameters.
/// @dev The minimum authorization is also returned by `minimumAuthorization()`
/// function, as a requirement of `IApplication` interface.
/// @return minimumAuthorization The minimum authorization amount required
/// so that operator can participate in the random beacon. This
/// amount is required to execute slashing for providing a malicious
/// DKG result or when a relay entry times out.
/// @return authorizationDecreaseDelay Delay in seconds that needs to pass
/// between the time authorization decrease is requested and the
/// time that request gets approved. Protects against free-riders
/// earning rewards and not being active in the network.
/// @return authorizationDecreaseChangePeriod Authorization decrease change
/// period in seconds. It is the time, before authorization decrease
/// delay end, during which the pending authorization decrease
/// request can be overwritten.
/// If set to 0, pending authorization decrease request can not be
/// overwritten until the endire `authorizationDecreaseDelay` ends.
/// If set to value equal `authorizationDecreaseDelay`, request can
/// always be overwritten.
function authorizationParameters()
external
view
returns (
uint96 minimumAuthorization,
uint64 authorizationDecreaseDelay,
uint64 authorizationDecreaseChangePeriod
)
{
return (
authorization.parameters.minimumAuthorization,
authorization.parameters.authorizationDecreaseDelay,
authorization.parameters.authorizationDecreaseChangePeriod
);
}

/// @notice Retrieves reward-related parameters.
/// @return maliciousDkgResultNotificationRewardMultiplier Percentage of the
/// staking contract malicious behavior notification reward which
Expand Down
88 changes: 85 additions & 3 deletions solidity/ecdsa/contracts/WalletRegistryGovernance.sol
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ contract WalletRegistryGovernance is Ownable {
uint64 public newAuthorizationDecreaseDelay;
uint256 public authorizationDecreaseDelayChangeInitiated;

uint64 public newAuthorizationDecreaseChangePeriod;
uint256 public authorizationDecreaseChangePeriodChangeInitiated;

uint96 public newMaliciousDkgResultSlashingAmount;
uint256 public maliciousDkgResultSlashingAmountChangeInitiated;

Expand Down Expand Up @@ -107,6 +110,15 @@ contract WalletRegistryGovernance is Ownable {
);
event AuthorizationDecreaseDelayUpdated(uint64 authorizationDecreaseDelay);

event AuthorizationDecreaseChangePeriodUpdateStarted(
uint64 authorizationDecreaseChangePeriod,
uint256 timestamp
);

event AuthorizationDecreaseChangePeriodUpdated(
uint64 authorizationDecreaseChangePeriod
);

event MaliciousDkgResultSlashingAmountUpdateStarted(
uint256 maliciousDkgResultSlashingAmount,
uint256 timestamp
Expand Down Expand Up @@ -357,10 +369,16 @@ contract WalletRegistryGovernance is Ownable {
onlyAfterGovernanceDelay(minimumAuthorizationChangeInitiated)
{
emit MinimumAuthorizationUpdated(newMinimumAuthorization);
(
,
uint64 authorizationDecreaseDelay,
uint64 authorizationDecreaseChangePeriod
) = walletRegistry.authorizationParameters();
// slither-disable-next-line reentrancy-no-eth
walletRegistry.updateAuthorizationParameters(
newMinimumAuthorization,
walletRegistry.authorizationDecreaseDelay()
authorizationDecreaseDelay,
authorizationDecreaseChangePeriod
);
minimumAuthorizationChangeInitiated = 0;
newMinimumAuthorization = 0;
Expand Down Expand Up @@ -391,15 +409,65 @@ contract WalletRegistryGovernance is Ownable {
onlyAfterGovernanceDelay(authorizationDecreaseDelayChangeInitiated)
{
emit AuthorizationDecreaseDelayUpdated(newAuthorizationDecreaseDelay);
(
uint96 minimumAuthorization,
uint64 authorizationDecreaseChangePeriod,

) = walletRegistry.authorizationParameters();
// slither-disable-next-line reentrancy-no-eth
walletRegistry.updateAuthorizationParameters(
walletRegistry.minimumAuthorization(),
newAuthorizationDecreaseDelay
minimumAuthorization,
newAuthorizationDecreaseDelay,
authorizationDecreaseChangePeriod
);
authorizationDecreaseDelayChangeInitiated = 0;
newAuthorizationDecreaseDelay = 0;
}

/// @notice Begins the authorization decrease change period update process.
/// @dev Can be called only by the contract owner.
/// @param _newAuthorizationDecreaseChangePeriod New authorization decrease change period
function beginAuthorizationDecreaseChangePeriodUpdate(
uint64 _newAuthorizationDecreaseChangePeriod
) external onlyOwner {
/* solhint-disable not-rely-on-time */
newAuthorizationDecreaseChangePeriod = _newAuthorizationDecreaseChangePeriod;
authorizationDecreaseChangePeriodChangeInitiated = block.timestamp;
emit AuthorizationDecreaseChangePeriodUpdateStarted(
_newAuthorizationDecreaseChangePeriod,
block.timestamp
);
/* solhint-enable not-rely-on-time */
}

/// @notice Finalizes the authorization decrease change period update process.
/// @dev Can be called only by the contract owner, after the governance
/// delay elapses.
function finalizeAuthorizationDecreaseChangePeriodUpdate()
external
onlyOwner
onlyAfterGovernanceDelay(
authorizationDecreaseChangePeriodChangeInitiated
)
{
emit AuthorizationDecreaseChangePeriodUpdated(
newAuthorizationDecreaseChangePeriod
);
(
uint96 minimumAuthorization,
uint64 authorizationDecreaseDelay,

) = walletRegistry.authorizationParameters();
// slither-disable-next-line reentrancy-no-eth
walletRegistry.updateAuthorizationParameters(
minimumAuthorization,
authorizationDecreaseDelay,
newAuthorizationDecreaseChangePeriod
);
authorizationDecreaseChangePeriodChangeInitiated = 0;
newAuthorizationDecreaseChangePeriod = 0;
}

/// @notice Begins the malicious DKG result slashing amount update process.
/// @dev Can be called only by the contract owner.
/// @param _newMaliciousDkgResultSlashingAmount New malicious DKG result
Expand Down Expand Up @@ -911,6 +979,20 @@ contract WalletRegistryGovernance is Ownable {
getRemainingChangeTime(authorizationDecreaseDelayChangeInitiated);
}

/// @notice Get the time remaining until the authorization decrease change
/// period can be updated.
/// @return Remaining time in seconds.
function getRemainingAuthorizationDecreaseChangePeriodUpdateTime()
external
view
returns (uint256)
{
return
getRemainingChangeTime(
authorizationDecreaseChangePeriodChangeInitiated
);
}

/// @notice Get the time remaining until the malicious DKG result
/// slashing amount can be updated.
/// @return Remaining time in seconds.
Expand Down
87 changes: 80 additions & 7 deletions solidity/ecdsa/contracts/libraries/EcdsaAuthorization.sol
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,46 @@ library EcdsaAuthorization {
// authorization decrease amount is small, significant, or if it is
// a decrease to zero.
uint64 authorizationDecreaseDelay;
// The time period before the authorization decrease delay end,
// during which the authorization decrease request can be overwritten.
//
// When the request is overwritten, the authorization decrease delay is
// reset.
//
// For example, if `authorizationDecraseChangePeriod` is set to 4
// days, `authorizationDecreaseDelay` is set to 14 days, and someone
// requested authorization decrease, it means they can not
// request another decrease for the first 10 days. After 10 days pass,
// they can request again and overwrite the previous authorization
// decrease request. The delay time will reset for them and they
// will have to wait another 10 days to alter it and 14 days to
// approve it.
//
// This value protects against malicious operators who manipulate
// their weight by overwriting authorization decrease request, and
// lowering or increasing their eligible stake this way.
//
// If set to a value equal to `authorizationDecreaseDelay, it means
// that authorization decrease request can be always overwritten.
// If set to zero, it means authorization decrease request can not be
// overwritten until the delay end, and one needs to wait for the entire
// authorization decrease delay to approve their decrease and request
// for another one or to overwrite the pending one.
//
// (1) authorization decrease requested timestamp
// (2) from this moment authorization decrease request can be
// overwritten
// (3) from this moment authorization decrease request can be
// approved, assuming it was NOT overwritten in (2)
//
// (1) (2) (3)
// --x------------------------------x--------------------------x---->
// | \________________________/
// | authorizationDecreaseChangePeriod
// \______________________________________________________/
// authorizationDecreaseDelay
//
uint64 authorizationDecreaseChangePeriod;
}

struct AuthorizationDecrease {
Expand Down Expand Up @@ -107,6 +147,19 @@ library EcdsaAuthorization {
.authorizationDecreaseDelay = _authorizationDecreaseDelay;
}

/// @notice Sets the authorization decrease change period. It is the time
/// period before the authorization decrease delay end,
/// during which the authorization decrease request can be
/// overwritten.
function setAuthorizationDecreaseChangePeriod(
Data storage self,
uint64 _authorizationDecreaseChangePeriod
) internal {
self
.parameters
.authorizationDecreaseChangePeriod = _authorizationDecreaseChangePeriod;
}

/// @notice Used by staking provider to set operator address that will
/// operate ECDSA node. The given staking provider can set operator
/// address only one time. The operator address can not be changed
Expand Down Expand Up @@ -191,6 +244,10 @@ library EcdsaAuthorization {
/// Reverts if the amount after deauthorization would be non-zero
/// and lower than the minimum authorization.
///
/// Reverts if another authorization decrease request is pending for
/// the staking provider and not enough time passed since the
/// original request (see `authorizationDecreaseChangePeriod`).
///
/// If the operator is not known (`registerOperator` was not called)
/// it lets to `approveAuthorizationDecrease` immediately. If the
/// operator is known (`registerOperator` was called), the operator
Expand All @@ -204,7 +261,8 @@ library EcdsaAuthorization {
/// `approveAuthorizationDecrease` function.
///
/// If there is a pending authorization decrease request, it is
/// overwritten.
/// overwritten, but only if enough time passed since the original
/// request. Otherwise, the function reverts.
///
/// @dev Should only be callable by T staking contract.
function authorizationDecreaseRequested(
Expand Down Expand Up @@ -239,17 +297,32 @@ library EcdsaAuthorization {
// For now, we set `decreasingAt` as "never decreasing" and let
// it be updated by `joinSortitionPool` or `updateOperatorStatus`
// once we know the sortition pool is in sync.

// solhint-disable-next-line not-rely-on-time
decreasingAt = type(uint64).max;
}

uint96 decreasingBy = fromAmount - toAmount;

self.pendingDecreases[stakingProvider] = AuthorizationDecrease(
decreasingBy,
decreasingAt
);
AuthorizationDecrease storage decreaseRequest = self.pendingDecreases[
stakingProvider
];

uint64 pendingDecreaseAt = decreaseRequest.decreasingAt;
if (pendingDecreaseAt != 0 && pendingDecreaseAt != type(uint64).max) {
// If there is already a pending authorization decrease request for
// this staking provider and that request has been activated
// (sortition pool was updated), require enough time to pass before
// it can be overwritten.
require(
// solhint-disable-next-line not-rely-on-time
block.timestamp >=
pendingDecreaseAt -
self.parameters.authorizationDecreaseChangePeriod,
"Not enough time passed since the original request"
);
}

decreaseRequest.decreasingBy = decreasingBy;
decreaseRequest.decreasingAt = decreasingAt;

emit AuthorizationDecreaseRequested(
stakingProvider,
Expand Down
Loading