Source Code
Overview
ETH Balance
0 ETH
More Info
ContractCreator
Multichain Info
N/A
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
TimeConstraints
Compiler Version
v0.8.26+commit.8a97fa7a
Optimization Enabled:
Yes with 200 runs
Other Settings:
cancun EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-FileCopyrightText: 2024 Lido <[email protected]> // SPDX-License-Identifier: MIT pragma solidity 0.8.26; import {Durations, Duration} from "contracts/types/Duration.sol"; import {Timestamps, Timestamp} from "contracts/types/Timestamp.sol"; import {ITimeConstraints} from "scripts/upgrade/interfaces/ITimeConstraints.sol"; /// @title Time Constraints Contract /// @notice Provides mechanisms to validate time-based constraints against the current /// network time (`block.timestamp`). Can be used within a transaction to ensure /// that time conditions are met. /// @dev Supports the following types of time validations: /// - Time windows within a day, including both standard (e.g., 09:00 – 17:00) and /// overnight ranges (e.g., 20:00 – 06:00). /// - A deadline: checks that the current time is before a specified timestamp. /// - A start time: checks that the current time is after a specified timestamp. contract TimeConstraints is ITimeConstraints { // --- // Events // --- event TimeWithinDayTimeChecked(Duration startDayTime, Duration endDayTime); event TimeBeforeTimestampChecked(Timestamp timestamp); event TimeAfterTimestampChecked(Timestamp timestamp); // --- // Errors // --- error DayTimeOverflow(); error DayTimeOutOfRange(Duration currentDayTime, Duration startDayTime, Duration endDayTime); error TimestampNotPassed(Timestamp timestamp); error TimestampPassed(Timestamp timestamp); // --- // Constants // --- /// @notice Total number of seconds in a day (24 hours). Duration public immutable DAY_DURATION = Durations.from(24 hours); // --- // Time Constraints Checks // --- /// @notice Checks that the current day time satisfies specific time range during the day. /// @dev Supports two types of time ranges: /// 1. Regular range: startDayTime <= endDayTime (e.g. [12:00, 18:00]) /// 2. Overnight range: startDayTime > endDayTime (e.g. [18:00, 12:00], where the end time is on the next day) /// @param startDayTime The start time of the allowed range (inclusive) in seconds since midnight (UTC). /// @param endDayTime The end time of the allowed range (inclusive) in seconds since midnight (UTC). function checkTimeWithinDayTime(Duration startDayTime, Duration endDayTime) public view { _validateDayTime(startDayTime); _validateDayTime(endDayTime); Duration currentDayTime = getCurrentDayTime(); bool isCurrentDayTimeOutOfRange = startDayTime <= endDayTime // Handle regular range within the same day: // 00:00:00 06:00:00 12:00:00 23:59:59 // │○○○○○○○○○○○○○○○○○│●●●●●●●●●●●●●●│○○○○○○○○○○○○○○○○○│ // startDayTime endDayTime ? currentDayTime < startDayTime || currentDayTime > endDayTime // Handle overnight range: // 00:00:00 06:00:00 12:00:00 23:59:59 // │●●●●●●●●●●●●●●●●●│○○○○○○○○○○○○○○│●●●●●●●●●●●●●●●●●│ // endDayTime startDayTime : currentDayTime < startDayTime && currentDayTime > endDayTime; if (isCurrentDayTimeOutOfRange) { revert DayTimeOutOfRange(currentDayTime, startDayTime, endDayTime); } } /// @notice Checks that the current network day time satisfies specific time range during the day and emits an event. /// @dev Supports two types of time ranges: /// 1. Regular range: startDayTime <= endDayTime (e.g. [12:00, 18:00]) /// 2. Overnight range: startDayTime > endDayTime (e.g. [18:00, 12:00], where the end time is on the next day) /// @param startDayTime The start time of the allowed range (inclusive) in seconds since midnight (UTC). /// @param endDayTime The end time of the allowed range (inclusive) in seconds since midnight (UTC). function checkTimeWithinDayTimeAndEmit(Duration startDayTime, Duration endDayTime) external { checkTimeWithinDayTime(startDayTime, endDayTime); emit TimeWithinDayTimeChecked(startDayTime, endDayTime); } /// @notice Checks that the current network timestamp is after the given specific timestamp. /// @param timestamp The Unix timestamp after which the check is successful. function checkTimeAfterTimestamp(Timestamp timestamp) public view { if (Timestamps.now() <= timestamp) { revert TimestampNotPassed(timestamp); } } /// @notice Checks that the current network timestamp is after the given specific timestamp and emits an event. /// @param timestamp The Unix timestamp after which the check is successful. function checkTimeAfterTimestampAndEmit(Timestamp timestamp) external { checkTimeAfterTimestamp(timestamp); emit TimeAfterTimestampChecked(timestamp); } /// @notice Checks that the current network timestamp is before the given specific timestamp. /// @param timestamp The Unix timestamp before which the check is successful. function checkTimeBeforeTimestamp(Timestamp timestamp) public view { if (Timestamps.now() >= timestamp) { revert TimestampPassed(timestamp); } } /// @notice Checks that the current network timestamp is before the given specific timestamp and emits an event. /// @param timestamp The Unix timestamp before which the check is successful. function checkTimeBeforeTimestampAndEmit(Timestamp timestamp) external { checkTimeBeforeTimestamp(timestamp); emit TimeBeforeTimestampChecked(timestamp); } // --- // Getters // --- /// @notice Gets the current time in seconds since midnight (UTC). /// @return Current time of day in seconds since midnight (UTC). function getCurrentDayTime() public view returns (Duration) { return Durations.from(block.timestamp % DAY_DURATION.toSeconds()); } // --- // Internal Methods // --- /// @notice Validates that a provided day time value is within the [0:00:00, 23:59:59] range. /// @param dayTime The day time value in seconds to validate. /// @dev Reverts with `DayTimeOverflow` if the value exceeds the number of seconds in a day. function _validateDayTime(Duration dayTime) internal view { if (dayTime >= DAY_DURATION) { revert DayTimeOverflow(); } } }
// SPDX-FileCopyrightText: 2024 Lido <[email protected]> // SPDX-License-Identifier: MIT pragma solidity 0.8.26; import {Timestamp, Timestamps} from "./Timestamp.sol"; // --- // Type Definition // --- type Duration is uint32; // --- // Assign Global Operations // --- using {lt as <, lte as <=, eq as ==, neq as !=, gte as >=, gt as >} for Duration global; using {addTo, plusSeconds, minusSeconds, multipliedBy, dividedBy, toSeconds} for Duration global; using {plus as +, minus as -} for Duration global; // --- // Errors // --- error DivisionByZero(); error DurationOverflow(); error DurationUnderflow(); // --- // Constants // --- /// @dev The maximum possible duration is approximately 136 years (assuming 365 days per year). uint32 constant MAX_DURATION_VALUE = type(uint32).max; // --- // Comparison Operations // --- function lt(Duration d1, Duration d2) pure returns (bool) { return Duration.unwrap(d1) < Duration.unwrap(d2); } function lte(Duration d1, Duration d2) pure returns (bool) { return Duration.unwrap(d1) <= Duration.unwrap(d2); } function eq(Duration d1, Duration d2) pure returns (bool) { return Duration.unwrap(d1) == Duration.unwrap(d2); } function neq(Duration d1, Duration d2) pure returns (bool) { return Duration.unwrap(d1) != Duration.unwrap(d2); } function gte(Duration d1, Duration d2) pure returns (bool) { return Duration.unwrap(d1) >= Duration.unwrap(d2); } function gt(Duration d1, Duration d2) pure returns (bool) { return Duration.unwrap(d1) > Duration.unwrap(d2); } // --- // Conversion Operations // --- function toSeconds(Duration d) pure returns (uint256) { return Duration.unwrap(d); } // --- // Arithmetic Operations // --- function plus(Duration d1, Duration d2) pure returns (Duration) { unchecked { /// @dev Both `d1.toSeconds()` and `d2.toSeconds()` are <= type(uint32).max. Therefore, their /// sum is <= type(uint256).max. return Durations.from(d1.toSeconds() + d2.toSeconds()); } } function minus(Duration d1, Duration d2) pure returns (Duration) { uint256 d1Seconds = d1.toSeconds(); uint256 d2Seconds = d2.toSeconds(); if (d1Seconds < d2Seconds) { revert DurationUnderflow(); } unchecked { /// @dev Subtraction is safe because `d1Seconds` >= `d2Seconds`. /// Both `d1Seconds` and `d2Seconds` <= `type(uint32).max`, so the difference fits within `uint32`. return Duration.wrap(uint32(d1Seconds - d2Seconds)); } } // --- // Custom Operations // --- function plusSeconds(Duration d, uint256 secondsToAdd) pure returns (Duration) { return Durations.from(d.toSeconds() + secondsToAdd); } function minusSeconds(Duration d, uint256 secondsToSubtract) pure returns (Duration) { uint256 durationSeconds = d.toSeconds(); if (durationSeconds < secondsToSubtract) { revert DurationUnderflow(); } unchecked { /// @dev Subtraction is safe because `durationSeconds` >= `secondsToSubtract`. /// Both `durationSeconds` and `secondsToSubtract` <= `type(uint32).max`, /// so the difference fits within `uint32`. return Duration.wrap(uint32(durationSeconds - secondsToSubtract)); } } function dividedBy(Duration d, uint256 divisor) pure returns (Duration) { if (divisor == 0) { revert DivisionByZero(); } return Duration.wrap(uint32(d.toSeconds() / divisor)); } function multipliedBy(Duration d, uint256 multiplicand) pure returns (Duration) { return Durations.from(multiplicand * d.toSeconds()); } function addTo(Duration d, Timestamp t) pure returns (Timestamp) { unchecked { /// @dev Both `t.toSeconds()` <= `type(uint40).max` and `d.toSeconds()` <= `type(uint32).max`, so their /// sum fits within `uint256`. return Timestamps.from(t.toSeconds() + d.toSeconds()); } } // --- // Namespaced Helper Methods // --- library Durations { Duration internal constant ZERO = Duration.wrap(0); function from(uint256 durationInSeconds) internal pure returns (Duration res) { if (durationInSeconds > MAX_DURATION_VALUE) { revert DurationOverflow(); } /// @dev Casting `durationInSeconds` to `uint32` is safe as the check ensures it is less than or equal /// to `MAX_DURATION_VALUE`, which fits within the `uint32`. res = Duration.wrap(uint32(durationInSeconds)); } }
// SPDX-FileCopyrightText: 2024 Lido <[email protected]> // SPDX-License-Identifier: MIT pragma solidity 0.8.26; // --- // Type Definition // --- type Timestamp is uint40; // --- // Assign Global Operations // --- using {lt as <, lte as <=, eq as ==, neq as !=, gte as >=, gt as >} for Timestamp global; using {isZero, isNotZero, toSeconds} for Timestamp global; // --- // Errors // --- error TimestampOverflow(); // --- // Constants // --- /// @dev The maximum value for a `Timestamp`, corresponding to approximately the year 36812. uint40 constant MAX_TIMESTAMP_VALUE = type(uint40).max; // --- // Comparison Operations // --- function lt(Timestamp t1, Timestamp t2) pure returns (bool) { return Timestamp.unwrap(t1) < Timestamp.unwrap(t2); } function lte(Timestamp t1, Timestamp t2) pure returns (bool) { return Timestamp.unwrap(t1) <= Timestamp.unwrap(t2); } function eq(Timestamp t1, Timestamp t2) pure returns (bool) { return Timestamp.unwrap(t1) == Timestamp.unwrap(t2); } function neq(Timestamp t1, Timestamp t2) pure returns (bool) { return Timestamp.unwrap(t1) != Timestamp.unwrap(t2); } function gte(Timestamp t1, Timestamp t2) pure returns (bool) { return Timestamp.unwrap(t1) >= Timestamp.unwrap(t2); } function gt(Timestamp t1, Timestamp t2) pure returns (bool) { return Timestamp.unwrap(t1) > Timestamp.unwrap(t2); } // --- // Conversion Operations // --- function toSeconds(Timestamp t) pure returns (uint256) { return Timestamp.unwrap(t); } // --- // Custom Operations // --- function isZero(Timestamp t) pure returns (bool) { return Timestamp.unwrap(t) == 0; } function isNotZero(Timestamp t) pure returns (bool) { return Timestamp.unwrap(t) > 0; } // --- // Namespaced Helper Methods // --- library Timestamps { Timestamp internal constant ZERO = Timestamp.wrap(0); function from(uint256 timestampInSeconds) internal pure returns (Timestamp res) { if (timestampInSeconds > MAX_TIMESTAMP_VALUE) { revert TimestampOverflow(); } /// @dev Casting `timestampInSeconds` to `uint40` is safe as the check ensures it is less than or equal /// to `MAX_TIMESTAMP_VALUE`, which fits within the `uint40`. return Timestamp.wrap(uint40(timestampInSeconds)); } function now() internal view returns (Timestamp res) { /// @dev Skipping the check that `block.timestamp` <= `MAX_TIMESTAMP_VALUE` for gas efficiency. /// Overflow is possible only after approximately 34,000 years from the Unix epoch. res = Timestamp.wrap(uint40(block.timestamp)); } function max(Timestamp t1, Timestamp t2) internal pure returns (Timestamp) { return t1 > t2 ? t1 : t2; } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.26; import {Duration} from "contracts/types/Duration.sol"; import {Timestamp} from "contracts/types/Timestamp.sol"; interface ITimeConstraints { function checkTimeWithinDayTime(Duration startDayTime, Duration endDayTime) external view; function checkTimeAfterTimestamp(Timestamp timestamp) external view; function checkTimeBeforeTimestamp(Timestamp timestamp) external view; function checkTimeWithinDayTimeAndEmit(Duration startDayTime, Duration endDayTime) external; function checkTimeAfterTimestampAndEmit(Timestamp timestamp) external; function checkTimeBeforeTimestampAndEmit(Timestamp timestamp) external; function getCurrentDayTime() external view returns (Duration); }
{ "remappings": [ "@openzeppelin/=lib/openzeppelin-contracts/", "ds-test/=lib/openzeppelin-contracts/lib/forge-std/lib/ds-test/src/", "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/", "eth-gas-reporter/=node_modules/eth-gas-reporter/", "forge-std/=lib/forge-std/src/", "hardhat/=node_modules/hardhat/", "kontrol-cheatcodes/=lib/kontrol-cheatcodes/src/", "openzeppelin-contracts/=lib/openzeppelin-contracts/" ], "optimizer": { "enabled": true, "runs": 200 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "cancun", "viaIR": false, "libraries": {} }
Contract ABI
API[{"inputs":[{"internalType":"Duration","name":"currentDayTime","type":"uint32"},{"internalType":"Duration","name":"startDayTime","type":"uint32"},{"internalType":"Duration","name":"endDayTime","type":"uint32"}],"name":"DayTimeOutOfRange","type":"error"},{"inputs":[],"name":"DayTimeOverflow","type":"error"},{"inputs":[],"name":"DurationOverflow","type":"error"},{"inputs":[{"internalType":"Timestamp","name":"timestamp","type":"uint40"}],"name":"TimestampNotPassed","type":"error"},{"inputs":[{"internalType":"Timestamp","name":"timestamp","type":"uint40"}],"name":"TimestampPassed","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"Timestamp","name":"timestamp","type":"uint40"}],"name":"TimeAfterTimestampChecked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"Timestamp","name":"timestamp","type":"uint40"}],"name":"TimeBeforeTimestampChecked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"Duration","name":"startDayTime","type":"uint32"},{"indexed":false,"internalType":"Duration","name":"endDayTime","type":"uint32"}],"name":"TimeWithinDayTimeChecked","type":"event"},{"inputs":[],"name":"DAY_DURATION","outputs":[{"internalType":"Duration","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"Timestamp","name":"timestamp","type":"uint40"}],"name":"checkTimeAfterTimestamp","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"Timestamp","name":"timestamp","type":"uint40"}],"name":"checkTimeAfterTimestampAndEmit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"Timestamp","name":"timestamp","type":"uint40"}],"name":"checkTimeBeforeTimestamp","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"Timestamp","name":"timestamp","type":"uint40"}],"name":"checkTimeBeforeTimestampAndEmit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"Duration","name":"startDayTime","type":"uint32"},{"internalType":"Duration","name":"endDayTime","type":"uint32"}],"name":"checkTimeWithinDayTime","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"Duration","name":"startDayTime","type":"uint32"},{"internalType":"Duration","name":"endDayTime","type":"uint32"}],"name":"checkTimeWithinDayTimeAndEmit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getCurrentDayTime","outputs":[{"internalType":"Duration","name":"","type":"uint32"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
60a0604052600e620151806026565b63ffffffff166080523480156021575f80fd5b50604f565b5f63ffffffff821115604b576040516368c2e67360e11b815260040160405180910390fd5b5090565b6080516104c86100755f395f8181610123015281816102a101526103bd01526104c85ff3fe608060405234801561000f575f80fd5b5060043610610085575f3560e01c80637a574578116100585780637a574578146100d75780638163b86f146100ea578063a532d6271461010b578063be93b8db1461011e575f80fd5b806313420c321461008957806314f5640f1461009e57806325272509146100b15780632d8b5033146100c4575b5f80fd5b61009c6100973660046103ff565b610145565b005b61009c6100ac3660046103ff565b610188565b61009c6100bf3660046103ff565b6101c3565b61009c6100d23660046103ff565b61020a565b61009c6100e5366004610442565b61024a565b6100f2610298565b60405163ffffffff909116815260200160405180910390f35b61009c610119366004610442565b6102d6565b6100f27f000000000000000000000000000000000000000000000000000000000000000081565b6101594264ffffffffff8084169116111590565b156101855760405163b8fcd36760e01b815264ffffffffff821660048201526024015b60405180910390fd5b50565b61019c4264ffffffffff8084169116101590565b156101855760405163529fe12d60e01b815264ffffffffff8216600482015260240161017c565b6101cc81610188565b60405164ffffffffff821681527f680d56203f239260ebedd5fa8a0a2f8b52068aad9b637cdf9cf675443c80ae26906020015b60405180910390a150565b61021381610145565b60405164ffffffffff821681527f51a89917aefcfff58f2404a99d83c9e19bc609c679aeac8bce038feef01e6341906020016101ff565b61025482826102d6565b6040805163ffffffff8085168252831660208201527fdcbcbd79e1d16a48f31541450b5248c46debf4fa5a2b05d7291c55eac9f5bd33910160405180910390a15050565b5f6102d16102cc7f000000000000000000000000000000000000000000000000000000000000000063ffffffff1642610473565b61038c565b905090565b6102df826103b6565b6102e8816103b6565b5f6102f1610298565b90505f63ffffffff808416908516111561032e5763ffffffff808516908316108015610329575063ffffffff8084169083161161034d565b61034d565b63ffffffff808516908316108061034d575063ffffffff808416908316115b90508015610386576040516309b31a1f60e41b815263ffffffff808416600483015280861660248301528416604482015260640161017c565b50505050565b5f63ffffffff8211156103b2576040516368c2e67360e11b815260040160405180910390fd5b5090565b63ffffffff7f0000000000000000000000000000000000000000000000000000000000000000811690821610610185576040516306ab415b60e11b815260040160405180910390fd5b5f6020828403121561040f575f80fd5b813564ffffffffff81168114610423575f80fd5b9392505050565b803563ffffffff8116811461043d575f80fd5b919050565b5f8060408385031215610453575f80fd5b61045c8361042a565b915061046a6020840161042a565b90509250929050565b5f8261048d57634e487b7160e01b5f52601260045260245ffd5b50069056fea2646970667358221220c69a3cc40a7f570c4062a2274e7c828ba3233fe70dc3cbad57389b294096301864736f6c634300081a0033
Deployed Bytecode
0x608060405234801561000f575f80fd5b5060043610610085575f3560e01c80637a574578116100585780637a574578146100d75780638163b86f146100ea578063a532d6271461010b578063be93b8db1461011e575f80fd5b806313420c321461008957806314f5640f1461009e57806325272509146100b15780632d8b5033146100c4575b5f80fd5b61009c6100973660046103ff565b610145565b005b61009c6100ac3660046103ff565b610188565b61009c6100bf3660046103ff565b6101c3565b61009c6100d23660046103ff565b61020a565b61009c6100e5366004610442565b61024a565b6100f2610298565b60405163ffffffff909116815260200160405180910390f35b61009c610119366004610442565b6102d6565b6100f27f000000000000000000000000000000000000000000000000000000000001518081565b6101594264ffffffffff8084169116111590565b156101855760405163b8fcd36760e01b815264ffffffffff821660048201526024015b60405180910390fd5b50565b61019c4264ffffffffff8084169116101590565b156101855760405163529fe12d60e01b815264ffffffffff8216600482015260240161017c565b6101cc81610188565b60405164ffffffffff821681527f680d56203f239260ebedd5fa8a0a2f8b52068aad9b637cdf9cf675443c80ae26906020015b60405180910390a150565b61021381610145565b60405164ffffffffff821681527f51a89917aefcfff58f2404a99d83c9e19bc609c679aeac8bce038feef01e6341906020016101ff565b61025482826102d6565b6040805163ffffffff8085168252831660208201527fdcbcbd79e1d16a48f31541450b5248c46debf4fa5a2b05d7291c55eac9f5bd33910160405180910390a15050565b5f6102d16102cc7f000000000000000000000000000000000000000000000000000000000001518063ffffffff1642610473565b61038c565b905090565b6102df826103b6565b6102e8816103b6565b5f6102f1610298565b90505f63ffffffff808416908516111561032e5763ffffffff808516908316108015610329575063ffffffff8084169083161161034d565b61034d565b63ffffffff808516908316108061034d575063ffffffff808416908316115b90508015610386576040516309b31a1f60e41b815263ffffffff808416600483015280861660248301528416604482015260640161017c565b50505050565b5f63ffffffff8211156103b2576040516368c2e67360e11b815260040160405180910390fd5b5090565b63ffffffff7f0000000000000000000000000000000000000000000000000000000000015180811690821610610185576040516306ab415b60e11b815260040160405180910390fd5b5f6020828403121561040f575f80fd5b813564ffffffffff81168114610423575f80fd5b9392505050565b803563ffffffff8116811461043d575f80fd5b919050565b5f8060408385031215610453575f80fd5b61045c8361042a565b915061046a6020840161042a565b90509250929050565b5f8261048d57634e487b7160e01b5f52601260045260245ffd5b50069056fea2646970667358221220c69a3cc40a7f570c4062a2274e7c828ba3233fe70dc3cbad57389b294096301864736f6c634300081a0033
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.