From 7bf74a20634e3ffd49ef4eefd8bb15fbed1c669e Mon Sep 17 00:00:00 2001 From: garyghayrat Date: Mon, 9 Sep 2024 16:07:24 -0400 Subject: [PATCH] Commit types folder that was initially ignore by .gitignore --- .../contracts/utils/types/Time.sol | 143 ++++++++++++++++++ 1 file changed, 143 insertions(+) create mode 100644 src/lib/openzeppelin-contracts-upgradeable-v5/lib/openzeppelin-contracts/contracts/utils/types/Time.sol diff --git a/src/lib/openzeppelin-contracts-upgradeable-v5/lib/openzeppelin-contracts/contracts/utils/types/Time.sol b/src/lib/openzeppelin-contracts-upgradeable-v5/lib/openzeppelin-contracts/contracts/utils/types/Time.sol new file mode 100644 index 00000000..779870b0 --- /dev/null +++ b/src/lib/openzeppelin-contracts-upgradeable-v5/lib/openzeppelin-contracts/contracts/utils/types/Time.sol @@ -0,0 +1,143 @@ +// SPDX-License-Identifier: MIT +// OpenZeppelin Contracts (last updated v5.0.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 updatedDelay, uint48 effect) + { + uint32 value = self.get(); + uint32 setback = uint32(Math.max(minSetback, value > newValue ? value - newValue : 0)); + 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 valueBefore, uint32 valueAfter, uint48 effect) + { + uint112 raw = Delay.unwrap(self); + + valueAfter = uint32(raw); + valueBefore = uint32(raw >> 32); + 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)); + } +}