SCWE-020: Absence of Time-Locked Functions
Stable Version v1.0
This content is in the version-(v1.0) and still under active development, so it is subject to change any time (e.g. structure, IDs, content, URLs, etc.).
Relationships¶
- CWE-840: Business Logic Errors https://cwe.mitre.org/data/definitions/840.html
Description¶
Absence of time-locked functions occurs when smart contracts do not implement mechanisms to delay certain critical functions or actions based on time conditions. This can result in the contract allowing actions that should be restricted or postponed for a certain period, such as emergency fund withdrawals or sensitive administrative actions. Without time-locking mechanisms, malicious actors or faulty logic could trigger these actions at the wrong time, leading to undesired outcomes.
Time-locking is commonly used in scenarios like: - Delaying admin or owner functions to prevent immediate misuse. - Ensuring withdrawal or fund transfer happens only after a predefined delay. - Enabling emergency actions only after a certain time or under specific conditions.
Remediation¶
- Implement time-locked functions: Ensure that critical functions, especially those related to fund transfers or administrative actions, are protected by a time lock, delaying their execution until an appropriate time has passed.
- Use block timestamps: Leverage block timestamps or block numbers to control the execution of functions.
- Limit emergency access: If implementing emergency mechanisms, ensure that there are time delays before they can be invoked, to reduce the chance of misuse.
- Review time-based logic regularly: Verify the correctness of time-based logic to ensure that the system behaves as intended.
Examples¶
Absence of Time-Locked Function¶
pragma solidity ^0.8.0;
contract NoTimeLock {
address public owner;
uint public funds;
constructor() {
owner = msg.sender;
funds = 1000;
}
// Critical function without time-lock
function withdrawFunds(uint amount) public {
require(msg.sender == owner, "Not the owner");
funds -= amount;
}
}
Time-Locked Function Implementation¶
pragma solidity ^0.8.0;
contract TimeLockExample {
address public owner;
uint public funds;
uint public lastWithdrawalTime;
uint public withdrawalDelay = 1 weeks;
constructor() {
owner = msg.sender;
funds = 1000;
lastWithdrawalTime = block.timestamp;
}
// Critical function with time-lock
function withdrawFunds(uint amount) public {
require(msg.sender == owner, "Not the owner");
require(block.timestamp >= lastWithdrawalTime + withdrawalDelay, "Time lock not expired");
lastWithdrawalTime = block.timestamp;
funds -= amount;
}
}