Units and Global Variables in Solidity

·

When developing smart contracts in Solidity, understanding the built-in units and globally available variables is essential for writing secure, efficient, and readable code. These features allow developers to work with real-world values—like ether amounts and time intervals—while interacting seamlessly with blockchain data such as block timestamps, transaction origins, and cryptographic functions.

This guide dives into the core concepts of ether units, time units, and global variables and functions available in Solidity 0.8.20, helping you leverage them effectively in your decentralized applications (dApps).


Ether Units in Solidity

Solidity provides native support for representing ether values using specific suffixes. These make it easier to express amounts in human-readable formats without manually calculating powers of 10.

The supported ether units are:

By default, any numeric literal without a suffix is interpreted as wei.

👉 Learn how to handle cryptocurrency values securely in your dApp

Here’s how these units work in practice:

assert(1 wei == 1);
assert(1 gwei == 1e9);
assert(1 ether == 1e18);

These suffixes are purely syntactic sugar—they multiply the number by the corresponding power of ten during compilation.

Note: As of Solidity 0.7.0, the finney and szabo units were removed from the language to reduce confusion and promote clarity in value representation.

Time Units for Readable Time Logic

Solidity includes built-in time units to simplify time-based calculations in smart contracts. These units help express durations clearly when working with timestamps, delays, or scheduling logic.

Available time units include:

Example usage:

function checkDeadline(uint start, uint daysAfter) public {
    if (block.timestamp >= start + daysAfter * 1 days) {
        // Deadline has passed
    }
}
Important: These suffixes can only be applied to literal constants, not variables. To use dynamic time calculations, multiply the variable by a unit like 1 days.

Calendar Accuracy and Leap Seconds

While convenient, time units assume fixed lengths for days and years. In reality, leap seconds can cause variations in actual day length. Since leap seconds are unpredictable and not accounted for on-chain, precise calendar calculations require external oracles to adjust for real-world timing discrepancies.

Note: The years unit was removed in Solidity 0.5.0 due to this imprecision and the complexity of handling leap years and leap seconds reliably.

Special Variables and Functions

Solidity exposes several global variables and functions that provide access to blockchain data and utility operations. These are grouped into categories based on their functionality.

Block and Transaction Properties

These variables offer insights into the current execution context:

Security Tip: Avoid using block.timestamp or blockhash as sources of randomness. Miners can manipulate these values slightly, which could be exploited in gambling or reward-distribution contracts.

👉 Explore secure contract patterns using blockchain metadata


ABI Encoding and Decoding Functions

Application Binary Interface (ABI) functions help serialize and deserialize data for external calls or storage.

Key functions include:

These are useful for crafting low-level calls or computing hashes of structured data.

Tip: Use keccak256(abi.encodePacked(a, b)) carefully—different input types may produce hash collisions due to encoding ambiguities.

String and Bytes Concatenation

Solidity supports concatenating dynamic data types via built-in methods:

These replace older manual concatenation techniques and improve readability.


Error Handling Functions

Proper error handling ensures your contract fails safely when preconditions aren't met.

Common functions:

Use require for user input validation and assert for invariant checks.


Cryptographic and Mathematical Functions

Solidity includes powerful built-in functions for math and cryptography:

Warning: On private blockchains, calling sha256, ripemd160, or ecrecover may result in an out-of-gas error unless the precompiled contracts are "touched" first by sending a minimal transaction to their addresses.

Contract-Level Operations

Special keywords let you interact with contract structure and lifecycle:

Deprecation Notice: Starting from Solidity 0.8.18, selfdestruct emits a deprecation warning because the EVM's SELFDESTRUCT opcode is expected to change behavior under EIP-6049.

Previously named suicide, this function was renamed in version 0.5.0 for clearer semantics.


Type Information with type()

You can query metadata about types at compile time using the type(T) expression.

For contract types:

For interfaces:

For integer types:

This feature enables advanced patterns like bytecode verification and safe upgrades.


Reserved Keywords

The following identifiers are reserved in Solidity and cannot be used as variable or function names, even though they are not currently part of the syntax:

after, alias, apply, auto, byte, case, copyof, default,
define, final, implements, in, inline, let, macro, match,
mutable, null, of, partial, promise, reference, relocatable,
sealed, sizeof, static, supports, switch, typedef, typeof, var

They may become active keywords in future versions.


Frequently Asked Questions

Can I use time units like 'years' in Solidity?

No. The years unit was removed in Solidity 0.5.0 due to inconsistencies caused by leap years and leap seconds. Use fixed calculations like 365 days only if approximate timing is acceptable.

Why was 'now' replaced with 'block.timestamp'?

The keyword now was deprecated in Solidity 0.7.0 and removed later. It was an alias for block.timestamp. Using the more explicit name improves code clarity and reduces ambiguity.

Is it safe to use blockhash for randomness?

No. Block hashes can be influenced by miners and should not be used as a randomness source in high-stakes applications like lotteries or NFT minting.

What replaced 'msg.gas'?

The variable msg.gas was deprecated in favor of gasleft() starting in Solidity 0.4.21. Always use gasleft() to check remaining gas.

How do I convert between address types?

You can cast a regular address to a payable one using:

address payable recipient = payable(msg.sender);

This is required before sending ether via .transfer() or .send().

Can I rely on block.timestamp for accurate timekeeping?

Block.timestamp is accurate within Ethereum consensus rules but should not be trusted for sub-minute precision. It must be strictly greater than the previous block's timestamp but can be slightly manipulated by miners.

👉 Build robust smart contracts with precise control over global variables


Core Keywords: Solidity global variables, ether units, time units, block.timestamp, msg.sender, abi.encode, keccak256, selfdestruct