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:
wei— the smallest unit (1 wei = 1)gwei— 1 gwei = 10^9 weiether— 1 ether = 10^18 wei
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, thefinneyandszabounits 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:
seconds— base unit (1 == 1 seconds)minutes— 1 minute = 60 secondshours— 1 hour = 60 minutesdays— 1 day = 24 hoursweeks— 1 week = 7 days
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:
blockhash(uint blockNumber)— returns the hash of a given block (only for the most recent 256 blocks; otherwise returns zero)block.basefee— current block's base fee (post-EIP-1559)block.chainid— ID of the current chainblock.coinbase— address of the miner who produced the blockblock.difficulty— current block difficulty (or alias forprevrandaoafter The Merge)block.gaslimit— gas limit of the current blockblock.number— current block numberblock.timestamp— Unix timestamp of the current blockgasleft()— returns remaining gas available in the current transactionmsg.sender— address that initiated the current callmsg.value— amount of wei sent with the messagetx.origin— original sender of the transaction (entire call stack)
Security Tip: Avoid usingblock.timestamporblockhashas 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:
abi.encode(...)— ABI-encodes given argumentsabi.decode(data, (types))— decodes ABI-encoded data into specified typesabi.encodePacked(...)— performs tight packing (use cautiously—can lead to ambiguity)abi.encodeWithSelector(selector, ...)— encodes data with a function selector prefixabi.encodeWithSignature(signature, ...)— encodes using a function signature stringabi.encodeCall(funcPointer, (...))— type-safe encoding of function calls with full compile-time checking
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:
bytes.concat(...)— combines byte arrays and fixed-size bytes valuesstring.concat(...)— joins multiple strings into one
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:
assert(bool condition)— use for internal errors; consumes all remaining gas if falserequire(bool condition)— validate inputs or external conditions; reverts with unused gas returnedrequire(bool condition, string memory message)— same as above, but includes a custom error messagerevert()orrevert(string memory reason)— explicitly revert execution with optional explanation
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:
addmod(x, y, k)— computes(x + y) % kwith arbitrary precisionmulmod(x, y, k)— computes(x * y) % ksafelykeccak256(bytes memory)— computes Keccak-256 hash (formerly known assha3)sha256(bytes memory)— SHA-256 hash functionripemd160(bytes memory)— RIPEMD-160 hash outputecrecover(hash, v, r, s)— recovers Ethereum address from ECDSA signature components
Warning: On private blockchains, callingsha256,ripemd160, orecrecovermay 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:
this— refers to the current contract instance (can be cast to address)super— accesses functions from parent contracts in inheritance hierarchiesselfdestruct(address payable recipient)— terminates contract and sends funds to recipient
Deprecation Notice: Starting from Solidity 0.8.18,selfdestructemits a deprecation warning because the EVM'sSELFDESTRUCTopcode 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:
type(C).name— contract nametype(C).creationCode— creation bytecode (not accessible within the contract itself)type(C).runtimeCode— deployed runtime bytecode
For interfaces:
type(I).interfaceId— EIP-165 interface identifier (XOR of all function selectors)
For integer types:
type(T).min— minimum value representabletype(T).max— maximum value representable
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