From ea4cdd4fec6871677c54bb48fa6f086f9d0279be Mon Sep 17 00:00:00 2001 From: allformless <213398294+allformless@users.noreply.github.com> Date: Mon, 10 Aug 2026 15:23:21 +0800 Subject: [PATCH] BEP-706: Millisecond-Precision Block Timestamp Precompile --- BEPs/BEP-706.md | 112 ++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 1 + 2 files changed, 113 insertions(+) create mode 100644 BEPs/BEP-706.md diff --git a/BEPs/BEP-706.md b/BEPs/BEP-706.md new file mode 100644 index 00000000..c0ebc096 --- /dev/null +++ b/BEPs/BEP-706.md @@ -0,0 +1,112 @@ +
+  BEP: 706
+  Title: Millisecond-Precision Block Timestamp Precompile
+  Status: Draft
+  Type: Standards
+  Created: 2026-08-10
+  Description: Add a precompile that exposes the block header's millisecond-precision timestamp to smart contracts.
+
+ +# BEP-706: Millisecond-Precision Block Timestamp Precompile + +- [BEP-706: Millisecond-Precision Block Timestamp Precompile](#bep-706-millisecond-precision-block-timestamp-precompile) + - [1. Summary](#1-summary) + - [2. Abstract](#2-abstract) + - [3. Motivation](#3-motivation) + - [4. Specification](#4-specification) + - [4.1 Precompiled Contract](#41-precompiled-contract) + - [4.2 Input](#42-input) + - [4.3 Output](#43-output) + - [4.4 Gas Cost](#44-gas-cost) + - [4.5 Solidity Usage](#45-solidity-usage) + - [5. Rationale](#5-rationale) + - [6. Backward Compatibility](#6-backward-compatibility) + - [7. Security Considerations](#7-security-considerations) + - [8. License](#8-license) + +## 1. Summary + +This BEP introduces a new precompiled contract that returns the current block's timestamp in **milliseconds** since the Unix epoch, giving smart contracts access to the sub-second precision that already exists in the block header but is currently unreachable from the EVM. + +## 2. Abstract + +Since [BEP-520](./BEP-520.md), BSC block headers carry a millisecond-precision timestamp: `Header.Time` (seconds) is unchanged for backward compatibility, and the sub-second remainder is stored in the last two bytes of `Header.MixDigest`. Full nodes compute this value via `Header.MilliTimestamp()`. This value is validated as part of consensus, but it is only accessible in client code — the EVM's `TIMESTAMP` (`0x42`) opcode still returns only `Header.Time`, truncated to whole seconds. + +This BEP adds a precompiled contract that returns `Header.MilliTimestamp()` of the currently executing block, so contracts can read block time at the same precision the protocol already commits to, without any change to the semantics of `block.timestamp`. + +## 3. Motivation + +BSC's block interval has been shortened multiple times ([BEP-520](./BEP-520.md) and subsequent reductions), to the point where `block.timestamp`'s one-second resolution is now coarser than the block interval itself — multiple blocks can share the same second-level timestamp. On-chain logic that needs sub-second real-world time has no reliable way to get it today. + +A concrete example is market maker / RFQ signature validity windows: an off-chain quote is signed with a short expiry (e.g. a few hundred milliseconds) to bound the maker's price risk, and a settlement contract must reject the quote once it has expired. With only second-level `block.timestamp`, the contract can only round the expiry up or down to the nearest second, forcing makers to widen the effective validity window and quote worse prices to offset the added risk. + +Other cases with the same shape include auction/order cutoffs, price-feed staleness checks, and any settlement logic keyed to a sub-second deadline. Exposing the header's existing millisecond timestamp via a precompile solves this directly, using data nodes already agree on, with no new trust assumptions. + +## 4. Specification + +### 4.1 Precompiled Contract + +As of `FORK_TIMESTAMP`, a new precompiled contract is added at address `MILLI_TIMESTAMP_PRECOMPILE_ADDRESS`. The exact address is `0x70`. + +The precompile returns the millisecond timestamp of the block currently being executed, equivalent to calling `Header.MilliTimestamp()` on the executing block's header: + +```go +// existing, introduced by BEP-520 +func (h *Header) MilliTimestamp() uint64 { + milliseconds := uint64(0) + if h.MixDigest != (common.Hash{}) { + milliseconds = uint256.NewInt(0).SetBytes32(h.MixDigest[:]).Uint64() + } + return h.Time*1000 + milliseconds +} +``` + +```go +// new precompile +func (c *milliTimestamp) Run(evm *EVM, input []byte) ([]byte, error) { + ts := evm.Context.Header.MilliTimestamp() // or evm.Context.Time equivalent, in milliseconds + return common.LeftPadBytes(new(big.Int).SetUint64(ts).Bytes(), 32), nil +} +``` + +Since the value is derived solely from the executing block's own header fields (both already validated by consensus), the precompile is a pure, deterministic function of the execution context and is safe to call from `STATICCALL`. + +### 4.2 Input + +The precompile takes no arguments. Calldata is ignored — the call succeeds regardless of calldata length or content. This mirrors context-only reads such as the `TIMESTAMP` opcode, and keeps the interface trivial to call from both Solidity and raw bytecode. + +### 4.3 Output + +A single 32-byte big-endian unsigned integer: the current block's timestamp in milliseconds since the Unix epoch, i.e. `Header.MilliTimestamp()`. + +### 4.4 Gas Cost + +This is a read-only call whose computational cost is comparable to that of the `0x4` (`identity`/`dataCopy`) precompile, whose base cost is 15 gas. Accordingly, this precompile's gas cost is set at 20 gas. + +### 4.5 Solidity Usage + +```solidity +function milliTimestamp() internal view returns (uint64) { + (bool ok, bytes memory data) = MILLI_TIMESTAMP_PRECOMPILE_ADDRESS.staticcall(""); + require(ok, "milliTimestamp: call failed"); + return uint64(uint256(bytes32(data))); +} +``` + +## 5. Rationale + +- **Precompile, not an opcode change.** Changing `TIMESTAMP` itself to return milliseconds was considered and rejected: `block.timestamp` is deeply embedded in deployed contracts and tooling that assume second units (e.g. `+ 1 days` arithmetic), so silently changing its unit would be a severe, silent breaking change. A new precompile is strictly additive and opt-in. +- **Precompile, not a new EVM opcode.** A precompile needs no changes to the opcode table or gas schedule that EVM tooling (disassemblers, static analyzers, gas estimators) special-cases, and matches BSC's existing convention of adding chain-specific functionality via precompiles rather than extending core EVM opcodes. + +## 6. Backward Compatibility + +This is a purely additive change. Before `FORK_TIMESTAMP`, the target address has no code, matching standard EVM behavior for calls to empty accounts. After activation, existing contracts are unaffected unless they explicitly call the new address. `block.timestamp` / the `TIMESTAMP` opcode's semantics are unchanged. + +## 7. Security Considerations + +- **No new trust assumptions.** The returned value is derived entirely from the executing block's own header fields (`Header.Time` and the millisecond component in `Header.MixDigest`), both of which are already validated as part of block consensus since [BEP-520](./BEP-520.md). The precompile does not introduce any data that isn't already agreed upon by validators. +- **Same timing trust model as `block.timestamp`.** The millisecond timestamp is validator-supplied and bounded by the same consensus-level constraints (e.g. monotonicity, permitted drift) that already apply to `Header.Time`, just at finer granularity. It offers no stronger guarantee than `block.timestamp` does today — a validator still has some latitude within protocol bounds, so timing-sensitive logic (e.g. auctions) carries the same caveats as before, just at millisecond rather than second resolution. + +## 8. License + +The content is licensed under [CC0](https://creativecommons.org/publicdomain/zero/1.0/). diff --git a/README.md b/README.md index a7c3b346..b1522db2 100644 --- a/README.md +++ b/README.md @@ -108,6 +108,7 @@ Here is the list of subjects of BEPs: | [BEP-677](./BEPs/BEP-677.md) | Implement EIP-8056 Scaled UI Amount | Standards | Draft | | [BEP-682](./BEPs/BEP-682.md) | Reject Duplicate Validators in CometBFT Light Block Validation | Standards | Draft | | [BEP-695](./BEPs/BEP-695.md) | Staking and Governance Security Hardening | Standards | Draft | +| [BEP-706](./BEPs/BEP-706.md) | Millisecond-Precision Block Timestamp Precompile | Standards | Draft | # BAPs BAP (BNB Application Proposal) defines standards for application layer interactions on BNB Chain. Unlike BEPs which govern core protocol changes, BAPs focus on establishing conventions and interfaces for how applications communicate and interact with each other within the BNB Chain ecosystem.