Summary
Dangerous usage of block.timestamp
. block.timestamp
can be manipulated by miners.
Vulnerability Details
File: contracts/libraries/Oracle/LibChainlinkOracle.sol
LibChainlinkOracle.checkForInvalidTimestampOrAnswer(uint256,int256,uint256) (contracts/libraries/Oracle/LibChainlinkOracle.sol#138-149) uses timestamp for comparisons.
Dangerous comparisons:
- timestamp == 0 || timestamp > currentTimestamp (contracts/libraries/Oracle/LibChainlinkOracle.sol#144)
- currentTimestamp.sub(timestamp) > CHAINLINK_TIMEOUT (contracts/libraries/Oracle/LibChainlinkOracle.sol#146)
L#144, L#146,
138: function checkForInvalidTimestampOrAnswer(
139: uint256 timestamp,
140: int256 answer,
141: uint256 currentTimestamp
142: ) private pure returns (bool) {
143:
144: if (timestamp == 0 || timestamp > currentTimestamp) return true;
145:
146: if (currentTimestamp.sub(timestamp) > CHAINLINK_TIMEOUT) return true;
147:
148: if (answer <= 0) return true;
149: }
GitHub : 138-149
File: contracts/beanstalk/sun/SeasonFacet/SeasonFacet.sol
SeasonFacet.seasonTime() (contracts/beanstalk/sun/SeasonFacet/SeasonFacet.sol#63-67) uses timestamp for comparisons.
Dangerous comparisons:
- block.timestamp < s.season.start (contracts/beanstalk/sun/SeasonFacet/SeasonFacet.sol#64)
L#64,
63: function seasonTime() public view virtual returns (uint32) {
64: if (block.timestamp < s.season.start) return 0;
65: if (s.season.period == 0) return type(uint32).max;
66: return uint32((block.timestamp - s.season.start) / s.season.period);
67: }
GitHub : 63-67
File: contracts/libraries/Oracle/LibChainlinkOracle.sol
LibChainlinkOracle.getEthUsdTwap(uint256) (contracts/libraries/Oracle/LibChainlinkOracle.sol#70-136) uses timestamp for comparisons.
Dangerous comparisons:
- timestamp <= endTimestamp (contracts/libraries/Oracle/LibChainlinkOracle.sol#97)
- timestamp > endTimestamp (contracts/libraries/Oracle/LibChainlinkOracle.sol#104)
L#97, L#104,
97: if (timestamp <= endTimestamp) {
104: while (timestamp > endTimestamp) {
GitHub : 70-136
File: contracts/beanstalk/sun/SeasonFacet/SeasonFacet.sol
SeasonFacet.gm(address,LibTransfer.To) (contracts/beanstalk/sun/SeasonFacet/SeasonFacet.sol#44-57) uses timestamp for comparisons.
Dangerous comparisons:
- require(bool,string)(seasonTime() > s.season.current,Season: Still current Season.) (contracts/beanstalk/sun/SeasonFacet/SeasonFacet.sol#48)
L#48,
44: function gm(address account, LibTransfer.To mode) public payable returns (uint256) {
45: uint256 initialGasLeft = gasleft();
46:
47: require(!s.paused, "Season: Paused.");
48: require(seasonTime() > s.season.current, "Season: Still current Season.");
49: uint32 season = stepSeason();
50: int256 deltaB = stepOracle();
51: uint256 caseId = calcCaseIdandUpdate(deltaB);
52: LibGerminate.endTotalGermination(season, LibWhitelistedTokens.getWhitelistedTokens());
53: LibGauge.stepGauge();
54: stepSun(deltaB, caseId);
55:
56: return incentivize(account, initialGasLeft, mode);
57: }
GitHub : 44-57
Impact
block.timestamp
can be manipulated by miners so its use in comparison statements or computations will provide extra advantage to miners and attackers.
Tools Used
Manual Review
Recommendations
Avoid relying on block.timestamp
.