区块时间戳和区块编号

本文介绍了在Solidity中使用block.timestampblock.number来跟踪时间和区块的编程方法,并提供了相关代码示例和最佳实践。

到目前为止,我们已经能够做一些很酷的事情,但我们还未能跟踪时间的流逝。

你可以使用 block.timestamp 获取区块的 Unix 时间戳。让我们一起试试。


contract WhatTimeIsIt {

    function timestamp()
        public
        view
        returns (uint256) {
            return block.timestamp;
    }
}

在 Remix 中试试。

返回的数字是自 1970 年 1 月 1 日 UTC 以来的秒数,这是传统的 Unix 时间。记住,这是,而不是毫秒,即你的 Linux 桌面或其他编程语言可能会返回的类型。

以太坊通过区块不断推进,你获取的时间戳是验证者在生产区块时放入的时间戳。由于每 12 秒生产一个区块,因此 block.timestamp 大致会以这个数值递增。你不应信任以秒为单位的 block.timestamp,存在太多的偏差。但经过几分钟的时间,它就开始非常可靠了。

如果你想确保某人每天不会多次调用一个函数,可以使用下面这个结构


contract ExampleContract {

    uint256 public lastCall;

    function hasCooldown()
        public {
            uint256 day = 60 * 60 * 24;
            require(
                block.timestamp > lastCall + day,
                "隔天才能调用"
            );
            lastCall = block.timestamp;
    }
}

Solidity 有一种更简洁的方式来表示时间,而不需要那样乘以秒数。


contract ExampleContract {

    uint256 public lastCall;

    function hasCooldown()
        public {
            require(
                block.timestamp > lastCall + 1 days,
                "隔天才能调用"
            );
            lastCall = block.timestamp; // 更新最后一次调用函数的时间
    }
}

事实上,秒、分钟、小时、天和星期都是有效的时间单位,这些单位都是你所需秒数的便捷缩写。如果你想知道,seconds(秒)并不能改变数值,但如果你打算用秒作为度量的时间,它增加了代码的可读性。

block.number

你也可以通过变量了解自己目前在哪个区块。希望它的作用一目了然。有人错误地通过平均区块时间乘以 block.number 来度量的时间。不要这样做。

不要用 block.number(区块号)跟踪时间,只用于强制交易顺序。

何时需要强制交易顺序?并不常见。因此如果不确定,去用 block.timestamp。

Etherscan 显示当前的区块号,如果你想目前的区块号有多大,可以在 Etherscan 上查询。

https://static.wixstatic.com/media/61a666_a8d6fe27dfa944d696b31610c4b138b4~mv2.png/v1/fill/w_939,h_1250,al_c,q_95,enc_auto/block_timestamp_number.png


contract ExampleContract {

    function whatBlockIsIt()
        external
        view
        returns (uint256) {
            return block.number;
    }
}

上述的代码将告诉你当前交易发生在哪个区块。在本例中,它将动态更新。

如果你想强制某个函数在另一个函数之后(在更晚的区块中)被调用,你可以使用以下构造。


contract ExampleContract {

    // 默认值为零
    uint256 private calledAt;

    function callMeFirst()
        external {
            calledAt = block.number;
    }

    function callMeSecond()
        external {
            require(
                calledAt != 0 && block.number > calledAt,
                "必须先调用callMeFirst()"
            );
    }
}

练习题目

OneWeekLockup

IdiotBetting

TimeLockEscrow

ReducingPayout

BlockNumber

学习更多知识

Solidity 训练营中学习更多关于智能合约开发和代币标准的知识。

  • 原文链接: rareskills.io/learn-soli...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
RareSkills
RareSkills
https://www.rareskills.io/