Update docs
This commit is contained in:
126
contracts/utils/types/Time.sol
Normal file
126
contracts/utils/types/Time.sol
Normal file
@ -0,0 +1,126 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// OpenZeppelin Contracts (last updated v5.0.0-rc.0) (utils/types/Time.sol)
|
||||
|
||||
pragma solidity ^0.8.20;
|
||||
|
||||
import {Math} from "../math/Math.sol";
|
||||
import {SafeCast} from "../math/SafeCast.sol";
|
||||
|
||||
/**
|
||||
* @dev This library provides helpers for manipulating time-related objects.
|
||||
*
|
||||
* It uses the following types:
|
||||
* - `uint48` for timepoints
|
||||
* - `uint32` for durations
|
||||
*
|
||||
* While the library doesn't provide specific types for timepoints and duration, it does provide:
|
||||
* - a `Delay` type to represent duration that can be programmed to change value automatically at a given point
|
||||
* - additional helper functions
|
||||
*/
|
||||
library Time {
|
||||
using Time for *;
|
||||
|
||||
/**
|
||||
* @dev Get the block timestamp as a Timepoint.
|
||||
*/
|
||||
function timestamp() internal view returns (uint48) {
|
||||
return SafeCast.toUint48(block.timestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Get the block number as a Timepoint.
|
||||
*/
|
||||
function blockNumber() internal view returns (uint48) {
|
||||
return SafeCast.toUint48(block.number);
|
||||
}
|
||||
|
||||
// ==================================================== Delay =====================================================
|
||||
/**
|
||||
* @dev A `Delay` is a uint32 duration that can be programmed to change value automatically at a given point in the
|
||||
* future. The "effect" timepoint describes when the transitions happens from the "old" value to the "new" value.
|
||||
* This allows updating the delay applied to some operation while keeping some guarantees.
|
||||
*
|
||||
* In particular, the {update} function guarantees that if the delay is reduced, the old delay still applies for
|
||||
* some time. For example if the delay is currently 7 days to do an upgrade, the admin should not be able to set
|
||||
* the delay to 0 and upgrade immediately. If the admin wants to reduce the delay, the old delay (7 days) should
|
||||
* still apply for some time.
|
||||
*
|
||||
*
|
||||
* The `Delay` type is 112 bits long, and packs the following:
|
||||
*
|
||||
* ```
|
||||
* | [uint48]: effect date (timepoint)
|
||||
* | | [uint32]: value before (duration)
|
||||
* ↓ ↓ ↓ [uint32]: value after (duration)
|
||||
* 0xAAAAAAAAAAAABBBBBBBBCCCCCCCC
|
||||
* ```
|
||||
*
|
||||
* NOTE: The {get} and {withUpdate} functions operate using timestamps. Block number based delays are not currently
|
||||
* supported.
|
||||
*/
|
||||
type Delay is uint112;
|
||||
|
||||
/**
|
||||
* @dev Wrap a duration into a Delay to add the one-step "update in the future" feature
|
||||
*/
|
||||
function toDelay(uint32 duration) internal pure returns (Delay) {
|
||||
return Delay.wrap(duration);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Get the value at a given timepoint plus the pending value and effect timepoint if there is a scheduled
|
||||
* change after this timepoint. If the effect timepoint is 0, then the pending value should not be considered.
|
||||
*/
|
||||
function _getFullAt(Delay self, uint48 timepoint) private pure returns (uint32, uint32, uint48) {
|
||||
(uint32 valueBefore, uint32 valueAfter, uint48 effect) = self.unpack();
|
||||
return effect <= timepoint ? (valueAfter, 0, 0) : (valueBefore, valueAfter, effect);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Get the current value plus the pending value and effect timepoint if there is a scheduled change. If the
|
||||
* effect timepoint is 0, then the pending value should not be considered.
|
||||
*/
|
||||
function getFull(Delay self) internal view returns (uint32, uint32, uint48) {
|
||||
return _getFullAt(self, timestamp());
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Get the current value.
|
||||
*/
|
||||
function get(Delay self) internal view returns (uint32) {
|
||||
(uint32 delay, , ) = self.getFull();
|
||||
return delay;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Update a Delay object so that it takes a new duration after a timepoint that is automatically computed to
|
||||
* enforce the old delay at the moment of the update. Returns the updated Delay object and the timestamp when the
|
||||
* new delay becomes effective.
|
||||
*/
|
||||
function withUpdate(Delay self, uint32 newValue, uint32 minSetback) internal view returns (Delay, uint48) {
|
||||
uint32 value = self.get();
|
||||
uint32 setback = uint32(Math.max(minSetback, value > newValue ? value - newValue : 0));
|
||||
uint48 effect = timestamp() + setback;
|
||||
return (pack(value, newValue, effect), effect);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Split a delay into its components: valueBefore, valueAfter and effect (transition timepoint).
|
||||
*/
|
||||
function unpack(Delay self) internal pure returns (uint32, uint32, uint48) {
|
||||
uint112 raw = Delay.unwrap(self);
|
||||
|
||||
uint32 valueAfter = uint32(raw);
|
||||
uint32 valueBefore = uint32(raw >> 32);
|
||||
uint48 effect = uint48(raw >> 64);
|
||||
|
||||
return (valueBefore, valueAfter, effect);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev pack the components into a Delay object.
|
||||
*/
|
||||
function pack(uint32 valueBefore, uint32 valueAfter, uint48 effect) internal pure returns (Delay) {
|
||||
return Delay.wrap((uint112(effect) << 64) | (uint112(valueBefore) << 32) | uint112(valueAfter));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user