Explorar o código

Add docs for the `Time` library (#5684)

Co-authored-by: Ernesto García <ernestognw@gmail.com>
Gonzalo Othacehe hai 4 meses
pai
achega
de89798004
Modificáronse 2 ficheiros con 81 adicións e 0 borrados
  1. 3 0
      contracts/utils/README.adoc
  2. 78 0
      docs/modules/ROOT/pages/utilities.adoc

+ 3 - 0
contracts/utils/README.adoc

@@ -49,6 +49,7 @@ Miscellaneous contracts and libraries containing utility functions you can use t
  * {AbstractSigner}: Abstract contract for internal signature validation in smart contracts.
  * {ERC7739}: An abstract contract to validate signatures following the rehashing scheme from `ERC7739Utils`.
  * {ERC7739Utils}: Utilities library that implements a defensive rehashing mechanism to prevent replayability of smart contract signatures based on ERC-7739.
+ * {Time}: A library that provides helpers for manipulating time-related objects, including a `Delay` type.
  
 [NOTE]
 ====
@@ -170,3 +171,5 @@ Ethereum contracts have no native concept of an interface, so applications must
 {{CAIP10}}
 
 {{Blockhash}}
+
+{{Time}}

+ 78 - 0
docs/modules/ROOT/pages/utilities.adoc

@@ -405,3 +405,81 @@ contract L1Inbox {
 ----
 
 IMPORTANT: After EIP-2935 activation, it takes 8,191 blocks to completely fill the history storage. Before that, only block hashes since the fork block will be available.
+
+=== Time
+
+The xref:api:utils.adoc#Time[`Time`] library provides helpers for manipulating time-related objects in a type-safe manner. It uses `uint48` for timepoints and `uint32` for durations, helping to reduce gas costs while providing adequate precision.
+
+One of its key features is the `Delay` type, which represents a duration that can automatically change its value at a specified point in the future while maintaining delay guarantees. For example, when reducing a delay value (e.g., from 7 days to 1 day), the change only takes effect after the difference between the old and new delay (i.e. a 6 days) or a minimum setback period, preventing an attacker who gains admin access from immediately reducing security timeouts and executing sensitive operations. This is particularly useful for governance and security mechanisms where timelock periods need to be enforced.
+
+Consider this example for using and safely updating Delays:   
+[source,solidity]
+----
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.27;
+
+import {Time} from "contracts/utils/types/Time.sol";
+
+contract MyDelayedContract {
+    using Time for *;
+    
+    Time.Delay private _delay;
+
+    constructor() {
+        _delay = Time.toDelay(3 days);
+    }
+
+    function schedule(bytes32 operationId) external {
+        // Get the current `_delay` value, respecting any pending delay changes if they've taken effect
+        uint32 currentDelay = _delay.get();
+        uint48 executionTime = Time.timestamp() + currentDelay;
+        
+        // ... schedule the operation at `executionTime`
+    }
+    
+    function execute(bytes32 operationId) external {
+        uint48 executionTime = getExecutionTime(operationId);
+        require(executionTime > 0, "Operation not scheduled");
+        require(Time.timestamp() >= executionTime, "Delay not elapsed yet");
+
+        // ... execute the operation
+    }
+    
+    // Update the delay with `Time`'s safety mechanism
+    function updateDelay(uint32 newDelay) external {
+        (Time.Delay updatedDelay, uint48 effect) = _delay.withUpdate(
+            newDelay,    // The new delay value
+            5 days       // Minimum setback if reducing the delay
+        );
+        
+        _delay = updatedDelay;
+
+        // ... emit events
+    }
+    
+    // Get complete delay details including pending changes
+    function getDelayDetails() external view returns (
+        uint32 currentValue, // The current delay value
+        uint32 pendingValue, // The pending delay value
+        uint48 effectTime    // The timepoint when the pending delay change takes effect
+    ) {
+        return _delay.getFull();
+    }
+}
+----
+
+This pattern is used extensively in OpenZeppelin's xref:api:access.adoc#AccessManager[AccessManager] for implementing secure time-based access control. For example, when changing an admin delay:
+
+[source,solidity]
+----
+// From AccessManager.sol
+function _setTargetAdminDelay(address target, uint32 newDelay) internal virtual {
+    uint48 effect;
+    (_targets[target].adminDelay, effect) = _targets[target].adminDelay.withUpdate(
+        newDelay,
+        minSetback()
+    );
+
+    emit TargetAdminDelayUpdated(target, newDelay, effect);
+}
+----