Skip to content

Commit 1f22011

Browse files
alcuecaaliersh
andauthored
Update natspec in SaferSafes (#17976)
* Added a flowchart to the liveness module * Added version compatibility notice * patch version bump * Title for the state diagram * Trimmed comments to 100 characters * One extra slash slashed * semver-lock * semver-lock * refactor(prompt): enhance test quality guidance and add commit strategy (#17950) - add fuzz constraint for bounding value amounts to prevent overflow - change version testing from length checks to SemverComp.parse() validation - add version testing example showing wrong vs right approaches - add commit strategy guidance in methodology phases - add commit strategy section in PR submission guidelines * Added a flowchart to the liveness module * Added version compatibility notice * Title for the state diagram * Trimmed comments to 100 characters * One extra slash slashed * semver-lock * Remove the nonce-independent comment * We can't do state changes in `checkTransaction` * Revert "We can't do state changes in `checkTransaction`" This reverts commit ae5f394. --------- Co-authored-by: Ariel Diaz <[email protected]>
1 parent 690a1a6 commit 1f22011

File tree

4 files changed

+198
-148
lines changed

4 files changed

+198
-148
lines changed

packages/contracts-bedrock/snapshots/semver-lock.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -208,8 +208,8 @@
208208
"sourceCodeHash": "0x7fc4789b082bc8ecd29c4c75a06058f0ff0b72f1c1028a42db6f1c35269c8865"
209209
},
210210
"src/safe/SaferSafes.sol:SaferSafes": {
211-
"initCodeHash": "0x54eb5d9d4dd6c7a6ac5c223c7e166cf30e93e11acb8caefab73eac596dba5af7",
212-
"sourceCodeHash": "0xeb7745b3f5626573d1e935affbbb0e6b455e729f1d8b2da84ab0d5a46f848377"
211+
"initCodeHash": "0xe8ff14ba3d023064046251967c3f4d0eb7bc3c2eee6519523f1175b37c0f9ac9",
212+
"sourceCodeHash": "0x046424a35624e13badd3d3f91993c27d4d6058b4696cba8bdda27b09bc972785"
213213
},
214214
"src/universal/OptimismMintableERC20.sol:OptimismMintableERC20": {
215215
"initCodeHash": "0x3c85eed0d017dca8eda6396aa842ddc12492587b061e8c756a8d32c4610a9658",

packages/contracts-bedrock/src/safe/LivenessModule2.sol

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,41 @@ import { GuardManager } from "safe-contracts/base/GuardManager.sol";
1212
/// when the Safe becomes unresponsive. The fallback owner can initiate a challenge,
1313
/// and if the Safe doesn't respond within the challenge period, ownership transfers
1414
/// to the fallback owner.
15+
/// This contract is compatible only with the Safe contract version 1.4.1.
1516
/// @dev This is a singleton contract. To use it:
1617
/// 1. The Safe must first enable this module using ModuleManager.enableModule()
1718
/// 2. The Safe must then configure the module by calling configure() with params
19+
///
20+
/// Follows a state machine diagram for the lifecycle of this contract:
21+
/// +----------------------+
22+
/// | Start (no challenge) |<---------------------------+
23+
/// +----------------------+ |
24+
/// | | respond() by Safe
25+
/// | challenge() by fallbackOwner | OR
26+
/// | | configureLivenessModule() by Safe
27+
/// v | OR
28+
/// +--------------------------------------+ | clearLivenessModule() by Safe
29+
/// | Challenge Started | |
30+
/// | challengeStartTime = block.timestamp |------------+
31+
/// +--------------------------------------+ |
32+
/// | |
33+
/// | block.timestamp >= challengeStartTime + |
34+
/// | livenessResponsePeriod |
35+
/// v |
36+
/// +-----+-----------------------------------------+ |
37+
/// | Ready to transfer ownership to fallback owner |---+
38+
/// +-----+-----------------------------------------+
39+
/// |
40+
/// | changeOwnershipToFallback() by fallbackOwner
41+
/// |
42+
/// v
43+
/// +------------------------------+
44+
/// | Ownership Transferred |
45+
/// | - fallback owner sole owner |
46+
/// | - guard cleared |
47+
/// | - challenge cleared |
48+
/// +------------------------------+
49+
///
1850
abstract contract LivenessModule2 {
1951
/// @notice Configuration for a Safe's liveness module.
2052
/// @custom:field livenessResponsePeriod The duration in seconds that Safe owners have to
@@ -169,8 +201,8 @@ abstract contract LivenessModule2 {
169201
/// 1. Safe disables the module via ModuleManager.disableModule().
170202
/// 2. Safe calls this clearLivenessModule() function to remove stored configuration.
171203
/// 3. If Safe later re-enables the module, it must call configureLivenessModule() again.
172-
/// Never calling clearLivenessModule() after disabling keeps configuration data persistent
173-
/// for potential future re-enabling.
204+
/// Never calling clearLivenessModule() after disabling keeps configuration data
205+
/// persistent for potential future re-enabling.
174206
function clearLivenessModule() external {
175207
Safe callingSafe = Safe(payable(msg.sender));
176208

@@ -301,8 +333,8 @@ abstract contract LivenessModule2 {
301333

302334
// Disable the guard
303335
// Note that this will remove whichever guard is currently set on the Safe,
304-
// even if it is not the SaferSafes guard. This is intentional, as it is possible that the guard
305-
// itself was the cause of the liveness failure which resulted in the transfer of ownership to
336+
// even if it is not the SaferSafes guard. This is intentional, as it is possible that the
337+
// guard was the cause of the liveness failure which resulted in the transfer of ownership to
306338
// the fallback owner.
307339
_safe.execTransactionFromModule({
308340
to: address(_safe),
@@ -317,8 +349,9 @@ abstract contract LivenessModule2 {
317349
// Internal View Functions //
318350
////////////////////////////////////////////////////////////////
319351

320-
/// @notice Internal helper function which can be overriden in a child contract to check if the guard's
321-
/// configuration is valid in the context of other extensions that are enabled on the Safe.
352+
/// @notice Internal helper function which can be overriden in a child contract to check if the
353+
/// guard's configuration is valid in the context of other extensions that are enabled
354+
/// on the Safe.
322355
function _checkCombinedConfig(Safe _safe) internal view virtual;
323356

324357
/// @notice Asserts that the module is configured for the given Safe.

packages/contracts-bedrock/src/safe/SaferSafes.sol

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,30 +10,35 @@ import { TimelockGuard } from "./TimelockGuard.sol";
1010
import { ISemver } from "interfaces/universal/ISemver.sol";
1111

1212
/// @title SaferSafes
13-
/// @notice Combined Safe extensions providing both liveness module and timelock guard functionality
13+
/// @notice Combined Safe extensions providing both liveness module and timelock guard
14+
/// functionality
15+
/// This contract is compatible only with the Safe contract version 1.4.1.
1416
/// @dev This contract can be enabled simultaneously as both a module and a guard on a Safe:
1517
/// - As a module: provides liveness challenge functionality to prevent multisig deadlock
1618
/// - As a guard: provides timelock functionality for transaction delays and cancellation
17-
/// The two components in this contract are almost entirely independent of each other, and can be treated as
18-
/// separate extensions to the Safe. The only shared logic is the _checkCombinedConfig which runs at the end of the
19-
/// configuration functions for both components and ensures that the resulting configuration is valid.
20-
/// Either component can be enabled or disabled independently of the other.
21-
/// When installing either component, it should first be enabled, and then configured. If a component's
22-
/// functionality is not desired, then there is no need to enable or configure it.
19+
/// The two components in this contract are almost entirely independent of each other, and can
20+
/// be treated as separate extensions to the Safe. The only shared logic is the
21+
/// _checkCombinedConfig which runs at the end of the configuration functions for both
22+
/// components and ensures that the resulting configuration is valid. Either component can be
23+
/// enabled or disabled independently of the other. When installing either component, it
24+
/// should first be enabled, and then configured. If a component's functionality is not
25+
/// desired, then there is no need to enable or configure it.
2326
contract SaferSafes is LivenessModule2, TimelockGuard, ISemver {
2427
/// @notice Semantic version.
25-
/// @custom:semver 1.5.0
26-
string public constant version = "1.5.0";
28+
/// @custom:semver 1.5.2
29+
string public constant version = "1.5.2";
2730

2831
/// @notice Error for when the liveness response period is insufficient.
2932
error SaferSafes_InsufficientLivenessResponsePeriod();
3033

31-
/// @notice Internal helper function which can be overriden in a child contract to check if the guard's
32-
/// configuration is valid in the context of other extensions that are enabled on the Safe.
33-
/// This function acts as a FREI-PI invariant check to ensure the resulting config is valid, it MUST be
34-
/// called at the end of any configuration functions in the parent contract.
34+
/// @notice Internal helper function which can be overriden in a child contract to check if the
35+
/// guard's configuration is valid in the context of other extensions that are enabled
36+
/// on the Safe. This function acts as a FREI-PI invariant check to ensure the
37+
/// resulting config is valid, it MUST be called at the end of any configuration
38+
/// functions in the parent contract.
3539
function _checkCombinedConfig(Safe _safe) internal view override(LivenessModule2, TimelockGuard) {
36-
// We only need to perform this check if both the guard and the module are enabled on the Safe
40+
// We only need to perform this check if both the guard and the module are enabled on the
41+
// Safe
3742
if (!(_isGuardEnabled(_safe) && _safe.isModuleEnabled(address(this)))) {
3843
return;
3944
}
@@ -47,15 +52,16 @@ contract SaferSafes is LivenessModule2, TimelockGuard, ISemver {
4752
return;
4853
}
4954

50-
// If the liveness response period is 0, then the liveness module is enabled but not configured.
55+
// If the liveness response period is 0, then the liveness module is enabled but not
56+
// configured.
5157
// Challenging is not possible, so we don't need to perform any further checks.
5258
if (livenessResponsePeriod == 0) {
5359
return;
5460
}
5561

56-
// The liveness response period must be at least twice the timelock delay, this is necessary to prevent a
57-
// situation in which a Safe is not able to respond because there is insufficient time to respond to a challenge
58-
// after the timelock delay has expired.
62+
// The liveness response period must be at least twice the timelock delay, this is
63+
// necessary to prevent a situation in which a Safe is not able to respond because there is
64+
// insufficient time to respond to a challenge after the timelock delay has expired.
5965
if (livenessResponsePeriod < 2 * timelockDelay) {
6066
revert SaferSafes_InsufficientLivenessResponsePeriod();
6167
}

0 commit comments

Comments
 (0)