Sparkn

CodeFox Inc.
DeFiFoundryProxy
15,000 USDC
View results
Submission Details
Severity: medium

Block.timestamp Manipulation

Summary

If one depends on block.timestamp in the setConstest() on ProxyFactory.sol#1 theclosetTime can be manipulated by the miners on the blockchain leading to incorrect functions or unexpected outcome.

Vulnerability Details

The vulnerability lies in the heavy reliance on the block.timestamp for critical decisions, such as checking the closeTime of the contest. This can expose the contract to risks associated with miner manipulation, time drift, or chain reorganizations, potentially leading to incorrect outcomes or malicious attacks.

Impact

1 Miner Manipulation: Miners have some control over the value of block.timestamp within certain limits. Malicious miners can manipulate the timestamp to influence contract behavior in their favor, possibly leading to unauthorized access, cheating, or other undesirable outcomes.

2 Time Drift and Chain Reorganizations: The blockchain's timestamp is based on the time provided by miners, which may not be entirely accurate. Additionally, chain reorganizations can alter the order of blocks, affecting timestamps and potentially leading to inconsistent or unexpected contract behavior.

Tools Used

Manual Review

Recommendations

1 Use Block Numbers: Instead of relying solely on block.timestamp, consider using block numbers in combination with other mechanisms to determine time-related decisions. Block numbers are less susceptible to manipulation or time drift.

2 Oracles and External Time Sources: If accurate timing is crucial, consider using external time sources or decentralized oracles to fetch reliable timestamp information.

Example:
`pragma solidity ^0.8.0;

// Import an external contract that provides reliable time information
`interface TimeOracle {
function getCurrentTime() external view returns (uint256);
}

contract Contest {
address public owner;
uint256 public closeBlock;
TimeOracle public timeOracle;

constructor(address _timeOracle) {
    owner = msg.sender;
    timeOracle = TimeOracle(_timeOracle);
}

modifier onlyOwner() {
    require(msg.sender == owner, "Only owner can call this function");
    _;
}

function setCloseTime(uint256 _secondsFromNow) public onlyOwner {
    uint256 currentBlock = block.number;
    uint256 currentTimestamp = timeOracle.getCurrentTime();
    closeBlock = currentBlock + (_secondsFromNow / 15); // Assuming ~15 seconds per block
    require(closeBlock > currentBlock, "Invalid close time");
}

function hasContestEnded() public view returns (bool) {
    return block.number >= closeBlock;
}

}

In this example, we've introduced an external time oracle that provides a reliable timestamp (getCurrentTime) as opposed to using block.timestamp. The contract calculates the close block based on the number of blocks required to achieve the desired time from the current block.

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.