code-423n4 / 2022-05-opensea-seaport-findings

1 stars 0 forks source link

QA Report #93

Closed code423n4 closed 2 years ago

code423n4 commented 2 years ago

Use of Block.timestamp

Block timestamps have historically been used for a variety of applications, such as entropy for random numbers (see the Entropy Illusion for further details), locking funds for periods of time, and various state-changing conditional statements that are time-dependent. Miners have the ability to adjust timestamps slightly, which can prove to be dangerous if block timestamps are used incorrectly in smart contracts.

Instances:

reference/lib/ReferenceVerifiers.sol:48: if (startTime > block.timestamp || endTime <= block.timestamp) { reference/lib/ReferenceOrderFulfiller.sol:166: (block.timestamp - orderParameters.startTime), reference/lib/ReferenceOrderFulfiller.sol:168: (block.timestamp - orderParameters.startTime)) reference/lib/ReferenceOrderCombiner.sol:244: uint256 elapsed = block.timestamp - startTime; contracts/lib/OrderFulfiller.sol:164: uint256 elapsed = block.timestamp - orderParameters.startTime; contracts/lib/Verifiers.sol:43: if (startTime > block.timestamp || endTime <= block.timestamp) { contracts/lib/OrderCombiner.sol:238: uint256 elapsed = block.timestamp - startTime; test/foundry/FulfillBasicOrderTest.sol:216: basicOrderParameters.startTime = block.timestamp; test/foundry/FulfillBasicOrderTest.sol:217: basicOrderParameters.endTime = block.timestamp + 100; test/foundry/FulfillBasicOrderTest.sol:241: basicOrderParameters.startTime = block.timestamp; test/foundry/FulfillBasicOrderTest.sol:242: basicOrderParameters.endTime = block.timestamp + 100; test/foundry/FulfillBasicOrderTest.sol:282: orderComponents.startTime = block.timestamp; test/foundry/FulfillBasicOrderTest.sol:283: orderComponents.endTime = block.timestamp + 100; test/foundry/NonReentrant.t.sol:249: block.timestamp, test/foundry/NonReentrant.t.sol:250: block.timestamp + 1, test/foundry/NonReentrant.t.sol:292: orderComponents.startTime = block.timestamp; test/foundry/NonReentrant.t.sol:293: orderComponents.endTime = block.timestamp + 1; test/foundry/NonReentrant.t.sol:553: orderComponents.startTime = block.timestamp; test/foundry/NonReentrant.t.sol:554: orderComponents.endTime = block.timestamp + 1; test/foundry/NonReentrant.t.sol:571: orderParameters.startTime = block.timestamp; test/foundry/NonReentrant.t.sol:572: orderParameters.endTime = block.timestamp + 1; test/foundry/NonReentrant.t.sol:593: orderComponents.startTime = block.timestamp; test/foundry/NonReentrant.t.sol:594: orderComponents.endTime = block.timestamp + 1; test/foundry/NonReentrant.t.sol:613: orderParameters.startTime = block.timestamp; test/foundry/NonReentrant.t.sol:614: orderParameters.endTime = block.timestamp + 1;

Recommended Mitigation Steps

Block timestamps should not be used for entropy or generating random numbers—i.e., they should not be the deciding factor (either directly or through some derivation) for winning a game or changing an important state.

Time-sensitive logic is sometimes required; e.g., for unlocking contracts (time-locking), completing an ICO after a few weeks, or enforcing expiry dates. It is sometimes recommended to use block.number and an average block time to estimate times; with a 10 second block time, 1 week equates to approximately, 60480 blocks. Thus, specifying a block number at which to change a contract state can be more secure, as miners are unable to easily manipulate the block number.

MrToph commented 2 years ago

this warden submitted multiple QA reports, same submitter as #91