Commit 26c1ac54 authored by Maurelian's avatar Maurelian

feat(ctb): Document requirements for non-reverting in the Guard

Also reorders the functions in the order they are called.
parent 2c7ddd0e
...@@ -15,6 +15,9 @@ import { EnumerableSet } from "@openzeppelin/contracts/utils/structs/EnumerableS ...@@ -15,6 +15,9 @@ import { EnumerableSet } from "@openzeppelin/contracts/utils/structs/EnumerableS
/// If an owner does not participate in a transaction for a certain period of time, they are considered inactive. /// If an owner does not participate in a transaction for a certain period of time, they are considered inactive.
/// This Guard is intended to be used in conjunction with the LivenessModule contract, but does /// This Guard is intended to be used in conjunction with the LivenessModule contract, but does
/// not depend on it. /// not depend on it.
/// Note: Both `checkTransaction` and `checkAfterExecution` are called once each by the Safe contract
/// before and after the execution of a transaction. It is critical that neither function revert,
/// otherwise the Safe contract will be unable to execute a transaction.
contract LivenessGuard is ISemver, BaseGuard { contract LivenessGuard is ISemver, BaseGuard {
using EnumerableSet for EnumerableSet.AddressSet; using EnumerableSet for EnumerableSet.AddressSet;
...@@ -44,35 +47,8 @@ contract LivenessGuard is ISemver, BaseGuard { ...@@ -44,35 +47,8 @@ contract LivenessGuard is ISemver, BaseGuard {
SAFE = _safe; SAFE = _safe;
} }
/// @notice We use this post execution hook to compare the set of owners before and after.
/// If the set of owners has changed then we:
/// 1. Add new owners to the lastLive mapping
/// 2. Delete removed owners from the lastLive mapping
function checkAfterExecution(bytes32, bool) external {
// Get the current set of owners
address[] memory ownersAfter = SAFE.getOwners();
// Iterate over the current owners, and remove one at a time from the ownersBefore set.
uint256 ownersAfterLength = ownersAfter.length;
for (uint256 i = 0; i < ownersAfterLength; i++) {
// If the value was present, remove() returns true.
address ownerAfter = ownersAfter[i];
if (ownersBefore.remove(ownerAfter) == false) {
// This address was not already an owner, add it to the lastLive mapping
lastLive[ownerAfter] = block.timestamp;
}
}
// Now iterate over the remaining ownersBefore entries. Any remaining addresses are no longer an owner, so we
// delete them from the lastLive mapping.
for (uint256 j = 0; j < ownersBefore.length(); j++) {
address ownerBefore = ownersBefore.at(j);
delete lastLive[ownerBefore];
}
}
/// @notice Records the most recent time which any owner has signed a transaction. /// @notice Records the most recent time which any owner has signed a transaction.
/// @dev This method is called by the Safe contract, it is critical that it does not revert, otherwise /// @dev Called by the Safe contract before execution of a transaction.
/// the Safe contract will be unable to execute transactions.
function checkTransaction( function checkTransaction(
address to, address to,
uint256 value, uint256 value,
...@@ -122,6 +98,35 @@ contract LivenessGuard is ISemver, BaseGuard { ...@@ -122,6 +98,35 @@ contract LivenessGuard is ISemver, BaseGuard {
emit SignersRecorded(txHash, signers); emit SignersRecorded(txHash, signers);
} }
/// @notice Update the lastLive mapping according to the set of owners before and after execution.
/// @dev Called by the Safe contract after the execution of a transaction.
/// We use this post execution hook to compare the set of owners before and after.
/// If the set of owners has changed then we:
/// 1. Add new owners to the lastLive mapping
/// 2. Delete removed owners from the lastLive mapping
function checkAfterExecution(bytes32, bool) external {
// Get the current set of owners
address[] memory ownersAfter = SAFE.getOwners();
// Iterate over the current owners, and remove one at a time from the ownersBefore set.
uint256 ownersAfterLength = ownersAfter.length;
for (uint256 i = 0; i < ownersAfterLength; i++) {
// If the value was present, remove() returns true.
address ownerAfter = ownersAfter[i];
if (ownersBefore.remove(ownerAfter) == false) {
// This address was not already an owner, add it to the lastLive mapping
lastLive[ownerAfter] = block.timestamp;
}
}
// Now iterate over the remaining ownersBefore entries. Any remaining addresses are no longer an owner, so we
// delete them from the lastLive mapping.
for (uint256 j = 0; j < ownersBefore.length(); j++) {
address ownerBefore = ownersBefore.at(j);
delete lastLive[ownerBefore];
}
}
/// @notice Enables an owner to demonstrate liveness by calling this method directly. /// @notice Enables an owner to demonstrate liveness by calling this method directly.
/// This is useful for owners who have not recently signed a transaction via the Safe. /// This is useful for owners who have not recently signed a transaction via the Safe.
function showLiveness() external { function showLiveness() external {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment