Merge pull request #8843 from ethereum/deprecate-now

[BREAKING] Deprecate keyword now
This commit is contained in:
chriseth 2020-05-11 16:09:21 +02:00 committed by GitHub
commit 5566cd9f74
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
34 changed files with 157 additions and 107 deletions

View File

@ -3,6 +3,7 @@
Breaking changes: Breaking changes:
* Type Checker: Disallow virtual for library functions. * Type Checker: Disallow virtual for library functions.
* Deprecated dot syntax for `value` and `gas`. * Deprecated dot syntax for `value` and `gas`.
* Deprecated the identifier `now`.
Language Features: Language Features:

View File

@ -15,3 +15,4 @@ This section gives detailed instructions on how to update prior code for every b
* Change ``f.value(...)()`` to ``f{value: ...}()``. Similarly ``(new C).value(...)()`` to * Change ``f.value(...)()`` to ``f{value: ...}()``. Similarly ``(new C).value(...)()`` to
``(new C){value: ...}()`` and ``f.gas(...)()`` to ``f{gas: ...}()``. ``(new C){value: ...}()`` and ``f.gas(...)()`` to ``f{gas: ...}()``.
* Change ``now`` to ``block.timestamp``.

View File

@ -67,7 +67,7 @@ The following is the order of precedence for operators, listed in order of evalu
| *15* | Comma operator | ``,`` | | *15* | Comma operator | ``,`` |
+------------+-------------------------------------+--------------------------------------------+ +------------+-------------------------------------+--------------------------------------------+
.. index:: assert, block, coinbase, difficulty, number, block;number, timestamp, block;timestamp, msg, data, gas, sender, value, now, gas price, origin, revert, require, keccak256, ripemd160, sha256, ecrecover, addmod, mulmod, cryptography, this, super, selfdestruct, balance, send .. index:: assert, block, coinbase, difficulty, number, block;number, timestamp, block;timestamp, msg, data, gas, sender, value, gas price, origin, revert, require, keccak256, ripemd160, sha256, ecrecover, addmod, mulmod, cryptography, this, super, selfdestruct, balance, send
Global Variables Global Variables
================ ================
@ -91,7 +91,6 @@ Global Variables
- ``msg.data`` (``bytes``): complete calldata - ``msg.data`` (``bytes``): complete calldata
- ``msg.sender`` (``address payable``): sender of the message (current call) - ``msg.sender`` (``address payable``): sender of the message (current call)
- ``msg.value`` (``uint``): number of wei sent with the message - ``msg.value`` (``uint``): number of wei sent with the message
- ``now`` (``uint``): current block timestamp (alias for ``block.timestamp``)
- ``tx.gasprice`` (``uint``): gas price of the transaction - ``tx.gasprice`` (``uint``): gas price of the transaction
- ``tx.origin`` (``address payable``): sender of the transaction (full call chain) - ``tx.origin`` (``address payable``): sender of the transaction (full call chain)
- ``assert(bool condition)``: abort execution and revert state changes if condition is ``false`` (use for internal error) - ``assert(bool condition)``: abort execution and revert state changes if condition is ``false`` (use for internal error)
@ -124,7 +123,7 @@ Global Variables
- ``type(I).interfaceId`` (``bytes4``): value containing the EIP-165 interface identifier of the given interface, see :ref:`Type Information<meta-type>`. - ``type(I).interfaceId`` (``bytes4``): value containing the EIP-165 interface identifier of the given interface, see :ref:`Type Information<meta-type>`.
.. note:: .. note::
Do not rely on ``block.timestamp``, ``now`` and ``blockhash`` as a source of randomness, Do not rely on ``block.timestamp`` or ``blockhash`` as a source of randomness,
unless you know what you are doing. unless you know what you are doing.
Both the timestamp and the block hash can be influenced by miners to some degree. Both the timestamp and the block hash can be influenced by miners to some degree.
@ -144,6 +143,8 @@ Global Variables
In version 0.5.0, the following aliases were removed: ``suicide`` as alias for ``selfdestruct``, In version 0.5.0, the following aliases were removed: ``suicide`` as alias for ``selfdestruct``,
``msg.gas`` as alias for ``gasleft``, ``block.blockhash`` as alias for ``blockhash`` and ``msg.gas`` as alias for ``gasleft``, ``block.blockhash`` as alias for ``blockhash`` and
``sha3`` as alias for ``keccak256``. ``sha3`` as alias for ``keccak256``.
.. note::
In version 0.7.0, the alias ``now`` (for ``block.timestamp``) was removed.
.. index:: visibility, public, private, external, internal .. index:: visibility, public, private, external, internal

View File

@ -128,7 +128,7 @@ restrictions highly readable.
// phase, where `msg.sender` is the account // phase, where `msg.sender` is the account
// creating this contract. // creating this contract.
address public owner = msg.sender; address public owner = msg.sender;
uint public creationTime = now; uint public creationTime = block.timestamp;
// Modifiers can be used to change // Modifiers can be used to change
// the body of a function. // the body of a function.
@ -159,7 +159,7 @@ restrictions highly readable.
modifier onlyAfter(uint _time) { modifier onlyAfter(uint _time) {
require( require(
now >= _time, block.timestamp >= _time,
"Function called too early." "Function called too early."
); );
_; _;
@ -287,7 +287,7 @@ function finishes.
// This is the current stage. // This is the current stage.
Stages public stage = Stages.AcceptingBlindedBids; Stages public stage = Stages.AcceptingBlindedBids;
uint public creationTime = now; uint public creationTime = block.timestamp;
modifier atStage(Stages _stage) { modifier atStage(Stages _stage) {
require( require(
@ -306,10 +306,10 @@ function finishes.
// will not take the new stage into account. // will not take the new stage into account.
modifier timedTransitions() { modifier timedTransitions() {
if (stage == Stages.AcceptingBlindedBids && if (stage == Stages.AcceptingBlindedBids &&
now >= creationTime + 10 days) block.timestamp >= creationTime + 10 days)
nextStage(); nextStage();
if (stage == Stages.RevealBids && if (stage == Stages.RevealBids &&
now >= creationTime + 12 days) block.timestamp >= creationTime + 12 days)
nextStage(); nextStage();
// The other stages transition by transaction // The other stages transition by transaction
_; _;

View File

@ -44,7 +44,7 @@ Constant
For ``constant`` variables, the value has to be a constant at compile time and it has to be For ``constant`` variables, the value has to be a constant at compile time and it has to be
assigned where the variable is declared. Any expression assigned where the variable is declared. Any expression
that accesses storage, blockchain data (e.g. ``now``, ``address(this).balance`` or that accesses storage, blockchain data (e.g. ``block.timestamp``, ``address(this).balance`` or
``block.number``) or ``block.number``) or
execution data (``msg.value`` or ``gasleft()``) or makes calls to external contracts is disallowed. Expressions execution data (``msg.value`` or ``gasleft()``) or makes calls to external contracts is disallowed. Expressions
that might have a side-effect on memory allocation are allowed, but those that that might have a side-effect on memory allocation are allowed, but those that

View File

@ -146,7 +146,7 @@ The following statements are considered modifying the state:
contract C { contract C {
function f(uint a, uint b) public view returns (uint) { function f(uint a, uint b) public view returns (uint) {
return a * (b + 42) + now; return a * (b + 42) + block.timestamp;
} }
} }

View File

@ -61,7 +61,7 @@ to receive their money - contracts cannot activate themselves.
address payable _beneficiary address payable _beneficiary
) public { ) public {
beneficiary = _beneficiary; beneficiary = _beneficiary;
auctionEndTime = now + _biddingTime; auctionEndTime = block.timestamp + _biddingTime;
} }
/// Bid on the auction with the value sent /// Bid on the auction with the value sent
@ -78,7 +78,7 @@ to receive their money - contracts cannot activate themselves.
// Revert the call if the bidding // Revert the call if the bidding
// period is over. // period is over.
require( require(
now <= auctionEndTime, block.timestamp <= auctionEndTime,
"Auction already ended." "Auction already ended."
); );
@ -140,7 +140,7 @@ to receive their money - contracts cannot activate themselves.
// external contracts. // external contracts.
// 1. Conditions // 1. Conditions
require(now >= auctionEndTime, "Auction not yet ended."); require(block.timestamp >= auctionEndTime, "Auction not yet ended.");
require(!ended, "auctionEnd has already been called."); require(!ended, "auctionEnd has already been called.");
// 2. Effects // 2. Effects
@ -211,8 +211,8 @@ invalid bids.
/// functions. `onlyBefore` is applied to `bid` below: /// functions. `onlyBefore` is applied to `bid` below:
/// The new function body is the modifier's body where /// The new function body is the modifier's body where
/// `_` is replaced by the old function body. /// `_` is replaced by the old function body.
modifier onlyBefore(uint _time) { require(now < _time); _; } modifier onlyBefore(uint _time) { require(block.timestamp < _time); _; }
modifier onlyAfter(uint _time) { require(now > _time); _; } modifier onlyAfter(uint _time) { require(block.timestamp > _time); _; }
constructor( constructor(
uint _biddingTime, uint _biddingTime,
@ -220,7 +220,7 @@ invalid bids.
address payable _beneficiary address payable _beneficiary
) public { ) public {
beneficiary = _beneficiary; beneficiary = _beneficiary;
biddingEnd = now + _biddingTime; biddingEnd = block.timestamp + _biddingTime;
revealEnd = biddingEnd + _revealTime; revealEnd = biddingEnd + _revealTime;
} }
@ -326,4 +326,4 @@ invalid bids.
highestBidder = bidder; highestBidder = bidder;
return true; return true;
} }
} }

View File

@ -351,7 +351,7 @@ The full contract
{ {
sender = msg.sender; sender = msg.sender;
recipient = _recipient; recipient = _recipient;
expiration = now + duration; expiration = block.timestamp + duration;
} }
/// the recipient can close the channel at any time by presenting a /// the recipient can close the channel at any time by presenting a
@ -376,7 +376,7 @@ The full contract
/// if the timeout is reached without the recipient closing the channel, /// if the timeout is reached without the recipient closing the channel,
/// then the Ether is released back to the sender. /// then the Ether is released back to the sender.
function claimTimeout() public { function claimTimeout() public {
require(now >= expiration); require(block.timestamp >= expiration);
selfdestruct(sender); selfdestruct(sender);
} }

View File

@ -47,7 +47,7 @@ These suffixes cannot be applied to variables. For example, if you want to
interpret a function parameter in days, you can in the following way:: interpret a function parameter in days, you can in the following way::
function f(uint start, uint daysAfter) public { function f(uint start, uint daysAfter) public {
if (now >= start + daysAfter * 1 days) { if (block.timestamp >= start + daysAfter * 1 days) {
// ... // ...
} }
} }
@ -61,7 +61,7 @@ There are special variables and functions which always exist in the global
namespace and are mainly used to provide information about the blockchain namespace and are mainly used to provide information about the blockchain
or are general-use utility functions. or are general-use utility functions.
.. index:: abi, block, coinbase, difficulty, encode, number, block;number, timestamp, block;timestamp, msg, data, gas, sender, value, now, gas price, origin .. index:: abi, block, coinbase, difficulty, encode, number, block;number, timestamp, block;timestamp, msg, data, gas, sender, value, gas price, origin
Block and Transaction Properties Block and Transaction Properties
@ -78,7 +78,6 @@ Block and Transaction Properties
- ``msg.sender`` (``address payable``): sender of the message (current call) - ``msg.sender`` (``address payable``): sender of the message (current call)
- ``msg.sig`` (``bytes4``): first four bytes of the calldata (i.e. function identifier) - ``msg.sig`` (``bytes4``): first four bytes of the calldata (i.e. function identifier)
- ``msg.value`` (``uint``): number of wei sent with the message - ``msg.value`` (``uint``): number of wei sent with the message
- ``now`` (``uint``): current block timestamp (alias for ``block.timestamp``)
- ``tx.gasprice`` (``uint``): gas price of the transaction - ``tx.gasprice`` (``uint``): gas price of the transaction
- ``tx.origin`` (``address payable``): sender of the transaction (full call chain) - ``tx.origin`` (``address payable``): sender of the transaction (full call chain)
@ -88,7 +87,7 @@ Block and Transaction Properties
This includes calls to library functions. This includes calls to library functions.
.. note:: .. note::
Do not rely on ``block.timestamp``, ``now`` and ``blockhash`` as a source of randomness, Do not rely on ``block.timestamp`` or ``blockhash`` as a source of randomness,
unless you know what you are doing. unless you know what you are doing.
Both the timestamp and the block hash can be influenced by miners to some degree. Both the timestamp and the block hash can be influenced by miners to some degree.
@ -112,6 +111,9 @@ Block and Transaction Properties
The function ``gasleft`` was previously known as ``msg.gas``, which was deprecated in The function ``gasleft`` was previously known as ``msg.gas``, which was deprecated in
version 0.4.21 and removed in version 0.5.0. version 0.4.21 and removed in version 0.5.0.
.. note::
In version 0.7.0, the alias ``now`` (for ``block.timestamp``) was removed.
.. index:: abi, encoding, packed .. index:: abi, encoding, packed
ABI Encoding and Decoding Functions ABI Encoding and Decoding Functions
@ -327,4 +329,3 @@ for an interface type ``I``:
A ``bytes4`` value containing the `EIP-165 <https://eips.ethereum.org/EIPS/eip-165>`_ A ``bytes4`` value containing the `EIP-165 <https://eips.ethereum.org/EIPS/eip-165>`_
interface identifier of the given interface ``I``. This identifier is defined as the ``XOR`` of all interface identifier of the given interface ``I``. This identifier is defined as the ``XOR`` of all
function selectors defined within the interface itself - excluding all inherited functions. function selectors defined within the interface itself - excluding all inherited functions.

View File

@ -580,6 +580,9 @@ Available upgrade modules
| | | ``f{gas: ..., value: ...}()`` and | | | | ``f{gas: ..., value: ...}()`` and |
| | | ``(new C){value: ...}()``. | | | | ``(new C){value: ...}()``. |
+-----------------+---------+--------------------------------------------------+ +-----------------+---------+--------------------------------------------------+
| ``now`` | 0.7.0 | The ``now`` keyword is deprecated. Use |
| | | ``block.timestamp`` instead. |
+-----------------+---------+--------------------------------------------------+
Please read :doc:`0.5.0 release notes <050-breaking-changes>`, Please read :doc:`0.5.0 release notes <050-breaking-changes>`,
:doc:`0.6.0 release notes <060-breaking-changes>` and :doc:`0.6.0 release notes <060-breaking-changes>` and

View File

@ -2908,6 +2908,20 @@ bool TypeChecker::visit(Identifier const& _identifier)
); );
} }
if (
MagicVariableDeclaration const* magicVar =
dynamic_cast<MagicVariableDeclaration const*>(annotation.referencedDeclaration)
)
if (magicVar->type()->category() == Type::Category::Integer)
{
solAssert(_identifier.name() == "now", "");
m_errorReporter
.typeError(
_identifier.location(),
"\"now\" has been deprecated. Use \"block.timestamp\" instead."
);
}
return false; return false;
} }

View File

@ -69,8 +69,8 @@ contract MultiSigWalletWithDailyLimit is MultiSigWallet {
internal internal
returns (bool) returns (bool)
{ {
if (now > lastDay + 24 hours) { if (block.timestamp > lastDay + 24 hours) {
lastDay = now; lastDay = block.timestamp;
spentToday = 0; spentToday = 0;
} }
if (spentToday + amount > dailyLimit || spentToday + amount < spentToday) if (spentToday + amount > dailyLimit || spentToday + amount < spentToday)
@ -88,7 +88,7 @@ contract MultiSigWalletWithDailyLimit is MultiSigWallet {
view view
returns (uint) returns (uint)
{ {
if (now > lastDay + 24 hours) if (block.timestamp > lastDay + 24 hours)
return dailyLimit; return dailyLimit;
if (dailyLimit < spentToday) if (dailyLimit < spentToday)
return 0; return 0;

View File

@ -256,7 +256,7 @@ contract provider is module, safeMath, announcementTypes {
providers[msg.sender].data[currHeight].country = country; providers[msg.sender].data[currHeight].country = country;
providers[msg.sender].data[currHeight].info = info; providers[msg.sender].data[currHeight].info = info;
providers[msg.sender].data[currHeight].currentRate = rate; providers[msg.sender].data[currHeight].currentRate = rate;
providers[msg.sender].data[currHeight].create = now; providers[msg.sender].data[currHeight].create = block.timestamp;
providers[msg.sender].data[currHeight].lastPaidRate = rate; providers[msg.sender].data[currHeight].lastPaidRate = rate;
providers[msg.sender].data[currHeight].priv = priv; providers[msg.sender].data[currHeight].priv = priv;
providers[msg.sender].data[currHeight].lastSupplyID = currentSchellingRound; providers[msg.sender].data[currHeight].lastSupplyID = currentSchellingRound;
@ -436,7 +436,7 @@ contract provider is module, safeMath, announcementTypes {
clients[msg.sender].lastSupplyID = currentSchellingRound; clients[msg.sender].lastSupplyID = currentSchellingRound;
clients[msg.sender].paidUpTo = currentSchellingRound; clients[msg.sender].paidUpTo = currentSchellingRound;
clients[msg.sender].lastRate = providers[provider].data[currHeight].currentRate; clients[msg.sender].lastRate = providers[provider].data[currHeight].currentRate;
clients[msg.sender].providerConnected = now; clients[msg.sender].providerConnected = block.timestamp;
emit ENewClient(msg.sender, provider, currHeight, bal); emit ENewClient(msg.sender, provider, currHeight, bal);
} }
function partProvider() isReady external { function partProvider() isReady external {

View File

@ -55,7 +55,7 @@ contract Campaign {
} }
modifier timedTransitions() { modifier timedTransitions() {
if (stage == Stages.AuctionStarted && deadline < now) if (stage == Stages.AuctionStarted && deadline < block.timestamp)
stage = Stages.AuctionFailed; stage = Stages.AuctionFailed;
_; _;
} }
@ -86,7 +86,7 @@ contract Campaign {
&& address(_marketMaker) != address(0) && address(_marketMaker) != address(0)
&& _fee < FEE_RANGE && _fee < FEE_RANGE
&& _funding > 0 && _funding > 0
&& now < _deadline); && block.timestamp < _deadline);
eventContract = _eventContract; eventContract = _eventContract;
marketFactory = _marketFactory; marketFactory = _marketFactory;
marketMaker = _marketMaker; marketMaker = _marketMaker;

View File

@ -71,7 +71,7 @@ contract FutarchyOracle is Oracle {
public public
{ {
// Deadline is in the future // Deadline is in the future
require(_deadline > now); require(_deadline > block.timestamp);
// Create decision event // Create decision event
categoricalEvent = eventFactory.createCategoricalEvent(collateralToken, this, outcomeCount); categoricalEvent = eventFactory.createCategoricalEvent(collateralToken, this, outcomeCount);
// Create outcome events // Create outcome events
@ -131,7 +131,7 @@ contract FutarchyOracle is Oracle {
public public
{ {
// Outcome is not set yet and deadline has passed // Outcome is not set yet and deadline has passed
require(!isSet && deadline <= now); require(!isSet && deadline <= block.timestamp);
// Find market with highest marginal price for long outcome tokens // Find market with highest marginal price for long outcome tokens
uint highestMarginalPrice = markets[0].marketMaker().calcMarginalPrice(markets[0], LONG); uint highestMarginalPrice = markets[0].marketMaker().calcMarginalPrice(markets[0], LONG);
uint highestIndex = 0; uint highestIndex = 0;

View File

@ -80,7 +80,7 @@ contract UltimateOracle is Oracle {
&& forwardedOutcomeSetTimestamp == 0 && forwardedOutcomeSetTimestamp == 0
&& forwardedOracle.isOutcomeSet()); && forwardedOracle.isOutcomeSet());
forwardedOutcome = forwardedOracle.getOutcome(); forwardedOutcome = forwardedOracle.getOutcome();
forwardedOutcomeSetTimestamp = now; forwardedOutcomeSetTimestamp = block.timestamp;
emit ForwardedOracleOutcomeAssignment(forwardedOutcome); emit ForwardedOracleOutcomeAssignment(forwardedOutcome);
} }
@ -97,7 +97,7 @@ contract UltimateOracle is Oracle {
totalOutcomeAmounts[_outcome] = challengeAmount; totalOutcomeAmounts[_outcome] = challengeAmount;
totalAmount = challengeAmount; totalAmount = challengeAmount;
frontRunner = _outcome; frontRunner = _outcome;
frontRunnerSetTimestamp = now; frontRunnerSetTimestamp = block.timestamp;
emit OutcomeChallenge(msg.sender, _outcome); emit OutcomeChallenge(msg.sender, _outcome);
} }
@ -120,7 +120,7 @@ contract UltimateOracle is Oracle {
if (_outcome != frontRunner && totalOutcomeAmounts[_outcome] > totalOutcomeAmounts[frontRunner]) if (_outcome != frontRunner && totalOutcomeAmounts[_outcome] > totalOutcomeAmounts[frontRunner])
{ {
frontRunner = _outcome; frontRunner = _outcome;
frontRunnerSetTimestamp = now; frontRunnerSetTimestamp = block.timestamp;
} }
emit OutcomeVote(msg.sender, _outcome, amount); emit OutcomeVote(msg.sender, _outcome, amount);
} }
@ -147,7 +147,7 @@ contract UltimateOracle is Oracle {
view view
returns (bool) returns (bool)
{ {
return forwardedOutcomeSetTimestamp != 0 && now.sub(forwardedOutcomeSetTimestamp) > challengePeriod; return forwardedOutcomeSetTimestamp != 0 && (block.timestamp).sub(forwardedOutcomeSetTimestamp) > challengePeriod;
} }
/// @dev Checks if time to overbid the front runner is over /// @dev Checks if time to overbid the front runner is over
@ -157,7 +157,7 @@ contract UltimateOracle is Oracle {
view view
returns (bool) returns (bool)
{ {
return frontRunnerSetTimestamp != 0 && now.sub(frontRunnerSetTimestamp) > frontRunnerPeriod; return frontRunnerSetTimestamp != 0 && (block.timestamp).sub(frontRunnerSetTimestamp) > frontRunnerPeriod;
} }
/// @dev Checks if outcome was challenged /// @dev Checks if outcome was challenged

View File

@ -264,10 +264,10 @@ contract MilestoneTracker {
&&(msg.sender != recipient)) &&(msg.sender != recipient))
revert(); revert();
if (milestone.status != MilestoneStatus.AcceptedAndInProgress) revert(); if (milestone.status != MilestoneStatus.AcceptedAndInProgress) revert();
if (now < milestone.minCompletionDate) revert(); if (block.timestamp < milestone.minCompletionDate) revert();
if (now > milestone.maxCompletionDate) revert(); if (block.timestamp > milestone.maxCompletionDate) revert();
milestone.status = MilestoneStatus.Completed; milestone.status = MilestoneStatus.Completed;
milestone.doneTime = now; milestone.doneTime = block.timestamp;
emit ProposalStatusChanged(_idMilestone, milestone.status); emit ProposalStatusChanged(_idMilestone, milestone.status);
} }
@ -312,7 +312,7 @@ contract MilestoneTracker {
&&(msg.sender != recipient)) &&(msg.sender != recipient))
revert(); revert();
if ((milestone.status != MilestoneStatus.Completed) || if ((milestone.status != MilestoneStatus.Completed) ||
(now < milestone.doneTime + milestone.reviewTime)) (block.timestamp < milestone.doneTime + milestone.reviewTime))
revert(); revert();
authorizePayment(_idMilestone); authorizePayment(_idMilestone);

View File

@ -38,7 +38,6 @@ namespace solidity::frontend::test
namespace namespace
{ {
static char const* registrarCode = R"DELIMITER( static char const* registrarCode = R"DELIMITER(
pragma solidity >=0.4.0 <0.8.0; pragma solidity >=0.4.0 <0.8.0;
@ -68,7 +67,7 @@ abstract contract AuctionSystem {
function bid(string memory _name, address payable _bidder, uint _value) internal { function bid(string memory _name, address payable _bidder, uint _value) internal {
Auction storage auction = m_auctions[_name]; Auction storage auction = m_auctions[_name];
if (auction.endDate > 0 && now > auction.endDate) if (auction.endDate > 0 && block.timestamp > auction.endDate)
{ {
emit AuctionEnded(_name, auction.highestBidder); emit AuctionEnded(_name, auction.highestBidder);
onAuctionEnd(_name); onAuctionEnd(_name);
@ -82,7 +81,7 @@ abstract contract AuctionSystem {
auction.sumOfBids += _value; auction.sumOfBids += _value;
auction.highestBid = _value; auction.highestBid = _value;
auction.highestBidder = _bidder; auction.highestBidder = _bidder;
auction.endDate = now + c_biddingTime; auction.endDate = block.timestamp + c_biddingTime;
emit NewBid(_name, _bidder, _value); emit NewBid(_name, _bidder, _value);
} }
@ -120,7 +119,7 @@ contract GlobalRegistrar is Registrar, AuctionSystem {
Auction storage auction = m_auctions[_name]; Auction storage auction = m_auctions[_name];
Record storage record = m_toRecord[_name]; Record storage record = m_toRecord[_name];
address previousOwner = record.owner; address previousOwner = record.owner;
record.renewalDate = now + c_renewalInterval; record.renewalDate = block.timestamp + c_renewalInterval;
record.owner = auction.highestBidder; record.owner = auction.highestBidder;
emit Changed(_name); emit Changed(_name);
if (previousOwner != 0x0000000000000000000000000000000000000000) { if (previousOwner != 0x0000000000000000000000000000000000000000) {
@ -138,7 +137,7 @@ contract GlobalRegistrar is Registrar, AuctionSystem {
bool needAuction = requiresAuction(_name); bool needAuction = requiresAuction(_name);
if (needAuction) if (needAuction)
{ {
if (now < m_toRecord[_name].renewalDate) if (block.timestamp < m_toRecord[_name].renewalDate)
revert(); revert();
bid(_name, msg.sender, msg.value); bid(_name, msg.sender, msg.value);
} else { } else {

View File

@ -40,7 +40,6 @@ using namespace solidity::util;
namespace solidity::frontend::test namespace solidity::frontend::test
{ {
static char const* walletCode = R"DELIMITER( static char const* walletCode = R"DELIMITER(
//sol Wallet //sol Wallet
// Multi-sig, daily-limited account proxy/wallet. // Multi-sig, daily-limited account proxy/wallet.
@ -317,7 +316,7 @@ abstract contract daylimit is multiowned {
return false; return false;
} }
// determines today's index. // determines today's index.
function today() private view returns (uint) { return now / 1 days; } function today() private view returns (uint) { return block.timestamp / 1 days; }
// FIELDS // FIELDS

View File

@ -34,7 +34,7 @@ function colony_test
FORCE_ABIv2=false FORCE_ABIv2=false
CONFIG="truffle.js" CONFIG="truffle.js"
truffle_setup https://github.com/solidity-external-tests/colonyNetwork.git develop_060 truffle_setup https://github.com/solidity-external-tests/colonyNetwork.git develop_070
run_install install_fn run_install install_fn
cd lib cd lib

View File

@ -33,7 +33,7 @@ function gnosis_safe_test
OPTIMIZER_LEVEL=1 OPTIMIZER_LEVEL=1
CONFIG="truffle.js" CONFIG="truffle.js"
truffle_setup https://github.com/solidity-external-tests/safe-contracts.git development_060 truffle_setup https://github.com/solidity-external-tests/safe-contracts.git development_070
force_truffle_version force_truffle_version
sed -i 's|github:gnosis/mock-contract#sol_0_5_0|github:solidity-external-tests/mock-contract#master_070|g' package.json sed -i 's|github:gnosis/mock-contract#sol_0_5_0|github:solidity-external-tests/mock-contract#master_070|g' package.json

View File

@ -381,7 +381,7 @@ contract DAO is DAOInterface, Token, TokenCreation {
revert(); revert();
if (address(DAOrewardAccount) == 0x0000000000000000000000000000000000000000) if (address(DAOrewardAccount) == 0x0000000000000000000000000000000000000000)
revert(); revert();
lastTimeMinQuorumMet = now; lastTimeMinQuorumMet = block.timestamp;
minQuorumDivisor = 5; // sets the minimal quorum to 20% minQuorumDivisor = 5; // sets the minimal quorum to 20%
proposals.push(); // avoids a proposal with ID 0 because it is used proposals.push(); // avoids a proposal with ID 0 because it is used
@ -390,7 +390,7 @@ contract DAO is DAOInterface, Token, TokenCreation {
} }
receive() external payable override(DAOInterface, TokenCreation) { receive() external payable override(DAOInterface, TokenCreation) {
if (now < closingTime + creationGracePeriod && msg.sender != address(extraBalance)) if (block.timestamp < closingTime + creationGracePeriod && msg.sender != address(extraBalance))
createTokenProxy(msg.sender); createTokenProxy(msg.sender);
else else
receiveEther(); receiveEther();
@ -430,13 +430,13 @@ contract DAO is DAOInterface, Token, TokenCreation {
revert(); revert();
if (!isFueled if (!isFueled
|| now < closingTime || block.timestamp < closingTime
|| (msg.value < proposalDeposit && !_newCurator)) { || (msg.value < proposalDeposit && !_newCurator)) {
revert(); revert();
} }
if (now + _debatingPeriod < now) // prevents overflow if (block.timestamp + _debatingPeriod < block.timestamp) // prevents overflow
revert(); revert();
// to prevent a 51% attacker to convert the ether into deposit // to prevent a 51% attacker to convert the ether into deposit
@ -445,7 +445,7 @@ contract DAO is DAOInterface, Token, TokenCreation {
// to prevent curator from halving quorum before first proposal // to prevent curator from halving quorum before first proposal
if (proposals.length == 1) // initial length is 1 (see constructor) if (proposals.length == 1) // initial length is 1 (see constructor)
lastTimeMinQuorumMet = now; lastTimeMinQuorumMet = block.timestamp;
Proposal storage p = proposals.push(); Proposal storage p = proposals.push();
_proposalID = proposals.length - 1; _proposalID = proposals.length - 1;
@ -453,7 +453,7 @@ contract DAO is DAOInterface, Token, TokenCreation {
p.amount = _amount; p.amount = _amount;
p.description = _description; p.description = _description;
p.proposalHash = keccak256(abi.encodePacked(_recipient, _amount, _transactionData)); p.proposalHash = keccak256(abi.encodePacked(_recipient, _amount, _transactionData));
p.votingDeadline = now + _debatingPeriod; p.votingDeadline = block.timestamp + _debatingPeriod;
p.open = true; p.open = true;
//p.proposalPassed = False; // that's default //p.proposalPassed = False; // that's default
p.newCurator = _newCurator; p.newCurator = _newCurator;
@ -493,7 +493,7 @@ contract DAO is DAOInterface, Token, TokenCreation {
Proposal storage p = proposals[_proposalID]; Proposal storage p = proposals[_proposalID];
if (p.votedYes[msg.sender] if (p.votedYes[msg.sender]
|| p.votedNo[msg.sender] || p.votedNo[msg.sender]
|| now >= p.votingDeadline) { || block.timestamp >= p.votingDeadline) {
revert(); revert();
} }
@ -529,13 +529,13 @@ contract DAO is DAOInterface, Token, TokenCreation {
? splitExecutionPeriod ? splitExecutionPeriod
: executeProposalPeriod; : executeProposalPeriod;
// If we are over deadline and waiting period, assert proposal is closed // If we are over deadline and waiting period, assert proposal is closed
if (p.open && now > p.votingDeadline + waitPeriod) { if (p.open && block.timestamp > p.votingDeadline + waitPeriod) {
closeProposal(_proposalID); closeProposal(_proposalID);
return false; return false;
} }
// Check if the proposal can be executed // Check if the proposal can be executed
if (now < p.votingDeadline // has the voting deadline arrived? if (block.timestamp < p.votingDeadline // has the voting deadline arrived?
// Have the votes been counted? // Have the votes been counted?
|| !p.open || !p.open
|| p.proposalPassed // anyone trying to call us recursively? || p.proposalPassed // anyone trying to call us recursively?
@ -573,7 +573,7 @@ contract DAO is DAOInterface, Token, TokenCreation {
if (!p.creator.send(p.proposalDeposit)) if (!p.creator.send(p.proposalDeposit))
revert(); revert();
lastTimeMinQuorumMet = now; lastTimeMinQuorumMet = block.timestamp;
// set the minQuorum to 20% again, in the case it has been reached // set the minQuorum to 20% again, in the case it has been reached
if (quorum > totalSupply / 5) if (quorum > totalSupply / 5)
minQuorumDivisor = 5; minQuorumDivisor = 5;
@ -628,9 +628,9 @@ contract DAO is DAOInterface, Token, TokenCreation {
// Sanity check // Sanity check
if (now < p.votingDeadline // has the voting deadline arrived? if (block.timestamp < p.votingDeadline // has the voting deadline arrived?
//The request for a split expires XX days after the voting deadline //The request for a split expires XX days after the voting deadline
|| now > p.votingDeadline + splitExecutionPeriod || block.timestamp > p.votingDeadline + splitExecutionPeriod
// Does the new Curator address match? // Does the new Curator address match?
|| p.recipient != _newCurator || p.recipient != _newCurator
// Is it a new curator proposal? // Is it a new curator proposal?
@ -759,7 +759,7 @@ override returns (bool _success) {
function transfer(address _to, uint256 _value) public override returns (bool success) { function transfer(address _to, uint256 _value) public override returns (bool success) {
if (isFueled if (isFueled
&& now > closingTime && block.timestamp > closingTime
&& !isBlocked(msg.sender) && !isBlocked(msg.sender)
&& _to != address(this) && _to != address(this)
&& transferPaidOut(msg.sender, _to, _value) && transferPaidOut(msg.sender, _to, _value)
@ -782,7 +782,7 @@ override returns (bool _success) {
function transferFrom(address _from, address _to, uint256 _value) public function transferFrom(address _from, address _to, uint256 _value) public
override returns (bool success) { override returns (bool success) {
if (isFueled if (isFueled
&& now > closingTime && block.timestamp > closingTime
&& !isBlocked(_from) && !isBlocked(_from)
&& _to != address(this) && _to != address(this)
&& transferPaidOut(_from, _to, _value) && transferPaidOut(_from, _to, _value)
@ -869,11 +869,11 @@ override returns (bool _success) {
// this can only be called after `quorumHalvingPeriod` has passed or at anytime after // this can only be called after `quorumHalvingPeriod` has passed or at anytime after
// fueling by the curator with a delay of at least `minProposalDebatePeriod` // fueling by the curator with a delay of at least `minProposalDebatePeriod`
// between the calls // between the calls
if ((lastTimeMinQuorumMet < (now - quorumHalvingPeriod) || msg.sender == curator) if ((lastTimeMinQuorumMet < (block.timestamp - quorumHalvingPeriod) || msg.sender == curator)
&& lastTimeMinQuorumMet < (now - minProposalDebatePeriod) && lastTimeMinQuorumMet < (block.timestamp - minProposalDebatePeriod)
&& now >= closingTime && block.timestamp >= closingTime
&& proposals.length > 1) { && proposals.length > 1) {
lastTimeMinQuorumMet = now; lastTimeMinQuorumMet = block.timestamp;
minQuorumDivisor *= 2; minQuorumDivisor *= 2;
return true; return true;
} else { } else {
@ -887,7 +887,7 @@ override returns (bool _success) {
_newCurator, _newCurator,
0, 0,
0, 0,
now + splitExecutionPeriod, block.timestamp + splitExecutionPeriod,
name, name,
symbol, symbol,
decimals decimals
@ -907,7 +907,7 @@ override returns (bool _success) {
if (blocked[_account] == 0) if (blocked[_account] == 0)
return false; return false;
Proposal storage p = proposals[blocked[_account]]; Proposal storage p = proposals[blocked[_account]];
if (now > p.votingDeadline) { if (block.timestamp > p.votingDeadline) {
blocked[_account] = 0; blocked[_account] = 0;
return false; return false;
} else { } else {

View File

@ -102,7 +102,7 @@ contract TokenCreation is TokenCreationInterface, Token {
function createTokenProxy(address payable _tokenHolder) payable public function createTokenProxy(address payable _tokenHolder) payable public
override returns (bool success) { override returns (bool success) {
if (now < closingTime && msg.value > 0 if (block.timestamp < closingTime && msg.value > 0
&& (privateCreation == 0x0000000000000000000000000000000000000000 || privateCreation == msg.sender)) { && (privateCreation == 0x0000000000000000000000000000000000000000 || privateCreation == msg.sender)) {
uint token = (msg.value * 20) / divisor(); uint token = (msg.value * 20) / divisor();
@ -121,7 +121,7 @@ override returns (bool success) {
} }
function refund() public override { function refund() public override {
if (now > closingTime && !isFueled) { if (block.timestamp > closingTime && !isFueled) {
// Get extraBalance - will only succeed when called for the first time // Get extraBalance - will only succeed when called for the first time
if (address(extraBalance).balance >= extraBalance.accumulatedInput()) if (address(extraBalance).balance >= extraBalance.accumulatedInput())
extraBalance.payOut(address(this), extraBalance.accumulatedInput()); extraBalance.payOut(address(this), extraBalance.accumulatedInput());
@ -141,11 +141,11 @@ override returns (bool success) {
// The number of (base unit) tokens per wei is calculated // The number of (base unit) tokens per wei is calculated
// as `msg.value` * 20 / `divisor` // as `msg.value` * 20 / `divisor`
// The fueling period starts with a 1:1 ratio // The fueling period starts with a 1:1 ratio
if (closingTime - 2 weeks > now) { if (closingTime - 2 weeks > block.timestamp) {
return 20; return 20;
// Followed by 10 days with a daily creation rate increase of 5% // Followed by 10 days with a daily creation rate increase of 5%
} else if (closingTime - 4 days > now) { } else if (closingTime - 4 days > block.timestamp) {
return (20 + (now - (closingTime - 2 weeks)) / (1 days)); return (20 + (block.timestamp - (closingTime - 2 weeks)) / (1 days));
// The last 4 days there is a constant creation rate ratio of 1:1.5 // The last 4 days there is a constant creation rate ratio of 1:1.5
} else { } else {
return 30; return 30;

View File

@ -1025,29 +1025,6 @@ BOOST_AUTO_TEST_CASE(blockchain)
ABI_CHECK(callContractFunctionWithValue("someInfo()", 28), encodeArgs(28, u256("0x1212121212121212121212121212121212121212"), 7)); ABI_CHECK(callContractFunctionWithValue("someInfo()", 28), encodeArgs(28, u256("0x1212121212121212121212121212121212121212"), 7));
} }
BOOST_AUTO_TEST_CASE(now)
{
char const* sourceCode = R"(
contract test {
function someInfo() public returns (bool equal, uint val) {
equal = block.timestamp == now;
val = now;
}
}
)";
ALSO_VIA_YUL(
compileAndRun(sourceCode);
u256 startBlock = blockNumber();
size_t startTime = blockTimestamp(startBlock);
auto ret = callContractFunction("someInfo()");
u256 endBlock = blockNumber();
size_t endTime = blockTimestamp(endBlock);
BOOST_CHECK(startBlock != endBlock);
BOOST_CHECK(startTime != endTime);
ABI_CHECK(ret, encodeArgs(true, endTime));
)
}
BOOST_AUTO_TEST_CASE(send_ether) BOOST_AUTO_TEST_CASE(send_ether)
{ {
char const* sourceCode = R"( char const* sourceCode = R"(

View File

@ -346,9 +346,9 @@ BOOST_AUTO_TEST_CASE(incorrect_storage_access_bug)
mapping(uint => uint) data; mapping(uint => uint) data;
function f() public returns (uint) function f() public returns (uint)
{ {
if (data[now] == 0) if (data[block.timestamp] == 0)
data[uint(-7)] = 5; data[uint(-7)] = 5;
return data[now]; return data[block.timestamp];
} }
} }
)"; )";

View File

@ -10,7 +10,7 @@ contract C
assert(tx.origin == msg.sender); assert(tx.origin == msg.sender);
uint x = block.number; uint x = block.number;
assert(x + 2 > block.number); assert(x + 2 > block.number);
assert(now > 10); assert(block.timestamp > 10);
assert(gasleft() > 100); assert(gasleft() > 100);
} }
} }
@ -22,5 +22,5 @@ contract C
// Warning: (244-275): Assertion violation happens here // Warning: (244-275): Assertion violation happens here
// Warning: (311-316): Overflow (resulting value larger than 2**256 - 1) happens here // Warning: (311-316): Overflow (resulting value larger than 2**256 - 1) happens here
// Warning: (304-332): Assertion violation happens here // Warning: (304-332): Assertion violation happens here
// Warning: (336-352): Assertion violation happens here // Warning: (336-364): Assertion violation happens here
// Warning: (356-379): Assertion violation happens here // Warning: (368-391): Assertion violation happens here

View File

@ -0,0 +1,7 @@
contract C {
function f() public {
now;
}
}
// ----
// TypeError: (38-41): "now" has been deprecated. Use "block.timestamp" instead.

View File

@ -0,0 +1,8 @@
contract C {
function f() public view {
uint now = block.timestamp;
now;
}
}
// ----
// Warning: (43-51): This declaration shadows a builtin symbol.

View File

@ -1,7 +1,7 @@
contract C { contract C {
uint x; uint x;
function g() pure public {} function g() pure public {}
function f() view public returns (uint) { return now; } function f() view public returns (uint) { return block.timestamp; }
function h() public { x = 2; } function h() public { x = 2; }
function i() payable public { x = 2; } function i() payable public { x = 2; }
} }

View File

@ -267,6 +267,11 @@ public:
return ""; return "";
} }
static std::string nowUpdate(langutil::SourceLocation const& _location)
{
return regex_replace(_location.text(), std::regex{"now"}, "block.timestamp");
}
}; };
} }

View File

@ -196,6 +196,8 @@ Allowed options)",
m_suite.activateModule(Module::VirtualFunction); m_suite.activateModule(Module::VirtualFunction);
else if (module == "dotsyntax") else if (module == "dotsyntax")
m_suite.activateModule(Module::DotSyntax); m_suite.activateModule(Module::DotSyntax);
else if (module == "now")
m_suite.activateModule(Module::NowKeyword);
else else
{ {
error() << "Unknown upgrade module \"" + module + "\"" << endl; error() << "Unknown upgrade module \"" + module + "\"" << endl;

View File

@ -58,7 +58,8 @@ private:
AbstractContract, AbstractContract,
OverridingFunction, OverridingFunction,
VirtualFunction, VirtualFunction,
DotSyntax DotSyntax,
NowKeyword
}; };
/// Upgrade suite that hosts all available modules. /// Upgrade suite that hosts all available modules.
@ -84,6 +85,8 @@ private:
/// Solidity 0.7.0 /// Solidity 0.7.0
if (isActivated(Module::DotSyntax)) if (isActivated(Module::DotSyntax))
DotSyntax{m_changes}.analyze(_sourceUnit); DotSyntax{m_changes}.analyze(_sourceUnit);
if (isActivated(Module::NowKeyword))
NowKeyword{m_changes}.analyze(_sourceUnit);
} }
void activateModule(Module _module) { m_modules.insert(_module); } void activateModule(Module _module) { m_modules.insert(_module); }
@ -103,7 +106,8 @@ private:
Module::AbstractContract, Module::AbstractContract,
Module::OverridingFunction, Module::OverridingFunction,
Module::VirtualFunction, Module::VirtualFunction,
Module::DotSyntax Module::DotSyntax,
Module::NowKeyword
}; };
}; };

View File

@ -40,3 +40,22 @@ void DotSyntax::endVisit(FunctionCall const& _functionCall)
); );
} }
} }
void NowKeyword::endVisit(Identifier const& _identifier)
{
IdentifierAnnotation& annotation = _identifier.annotation();
if (
MagicVariableDeclaration const* magicVar =
dynamic_cast<MagicVariableDeclaration const*>(annotation.referencedDeclaration)
)
if (magicVar->type()->category() == Type::Category::Integer)
{
solAssert(_identifier.name() == "now", "");
m_changes.emplace_back(
UpgradeChange::Level::Safe,
_identifier.location(),
SourceTransform::nowUpdate(_identifier.location())
);
}
}

View File

@ -32,4 +32,13 @@ private:
void endVisit(frontend::FunctionCall const& _expression) override; void endVisit(frontend::FunctionCall const& _expression) override;
}; };
class NowKeyword: public AnalysisUpgrade
{
public:
using AnalysisUpgrade::AnalysisUpgrade;
void analyze(frontend::SourceUnit const& _sourceUnit) { _sourceUnit.accept(*this); }
private:
void endVisit(frontend::Identifier const& _expression) override;
};
} }