- 1 Solidity Units And Global Variables Main Tips
- 2 Solidity Units And Global Variables Ether Units
- 3 Solidity Units And Global Variables Time Units
- 4 Solidity Units And Global Variables Special Variables and Functions
Solidity Units And Global Variables Main Tips
- Solidity provides two types of units – Ether units and time units.
- You can also use a variety of global special variables and functions for streamlining the creation of contracts.
Solidity Units And Global Variables Ether Units
A numeric literal may take a suffix of szabo, finney, wei or ether for converting between the Ether’s sub-denominations, where Ether currency numbers that are missing a postfix would be assumed to be Wei, for example 2 ethers equal 2000 finney, evaluating to true.
Solidity Units And Global Variables Time Units
Suffixes such as seconds, minutes, hours, days, weeks and years after literal numbers may be used for converting units of time from one to another, with seconds being the base unit, with units being considered more or less like this:
- 1 equals 1 seconds
- 1 minutes equals 60 seconds
- 1 hours equals 60 minutes
- 1 days equals 24 hours
- 1 weeks equals 7 days
- 1 years equals 365 days
Be careful in case you perform calendar calculations with these units, since not every year will equal 365 days with not even every day having 24 hours due to leap seconds. Because of the fact that leap seconds are unpredictable, a precise calendar library must be updated using an external oracle.
These suffixes might not be aplicable to variables. If interpreting some input variable in, say, days is what you want, it can be done like this:
Solidity Units And Global Variables Special Variables and Functions
Solidity provides functions and special variables that always exist inside the global namespace, are mainly used for providing information about the blockchain itself.
Block and Transaction Properties
- block.blockhash(uint numberOfBlock) returns (bytes32): hash which belongs to the given block – will only work for 256 of the most recent blocks, not including current
- block.difficulty (uint): difficulty of the current block
- block.coinbase (address): miner’s address of the current block
- block.number (uint): number of the current block
- block.gaslimit (uint): gaslimit of the current block
- block.timestamp (uint): timestamp of the current block as seconds passed since the unix epoch
- msg.gas (uint): gas that remains
- msg.data (bytes): complete calldata
- msg.value (uint): amount of wei which was sent along with the message
- msg.sender (address): message sender (current call)
- msg.sig (bytes4): calldata’s first four bytes (i.e. function identifier)
- now (uint): timestamp of the current block (alias for block.timestamp)
- tx.origin (address): sender of the transaction (whole call chain)
The timestamp and the block hash both are possible to influence by miners to a certain degree. Bad actors inside the mining community may, for example, run a casino payout function on a chosen hash, then just re-try another hash in case they have not received any money.
The timestamp of the current block has to be strictly larger than the last block’s timestamp, however, the only guarantee is that it is going to be somewhere in between the timestamps of a pair of consecutive blocks inside the canonical chain.
Note: The values of each member of msg, which includes msg.value and msg.sender may change for each external function call. That would include calls to library functions too.
Note: It is not recommended to rely on block.timestamp, now and block.blockhash for randomization, unless you are completely certain about what you are doing.
Note: The block hashes are not usable for every block for reasons concerning scalability. You may only access the hashes of the 256 blocks that were the most recent, while all other values are going to be zero.
- require(bool condition): will throw when the condition has been met – used for external components or errors in inputs
- assert(bool condition): will throw when the condition has been met – used for internal errors.
- revert(): used aborting execution and to revert state changes
Mathematical and Cryptographic Functions
- addmod(uint a, uint b, uint c) returns (uint): used for computing (a + b) % k in case when the addition is performed with arbitrary precision and does not wrap around at 2**256.
- keccak256(…) returns (bytes32): used for computing the Ethereum-SHA-3 (Keccak-256) hash of the (tightly packed) arguments
- ecrecover(uint8 v, bytes32 r, bytes32 hash, bytes32 s) returns (address): used for recovering the address associated along with the public key from an elliptic curve signature or, on error, to return zero
- ripemd160(…) returns (bytes20): used for computing RIPEMD-160 hash of arguments that are tightly packed
- mulmod(uint a, uint b, uint c) returns (uint): used for computing (a * b) % k in which the multiplying is done with arbitrary precision without wrapping around at 2**256.
- sha3(…) returns (bytes32): used as an alias to keccak256
- sha256(…) returns (bytes32): used for computing the SHA-256 hash of the (tightly packed) arguments
In the functions descriptions above, the term “tightly packed” means the arguments get concatenated without padding, meaning the following are all identical:
keccak256(97, 98, 99)
In case padding is necessary, explicit type conversions may be used: keccak256(“\x00\x12”) would be the same as keccak256(uint16(0x12)).
Notice how the constants are packed using the minimum amount of bytes that is needed to store them, meaning that, say, keccak256(0) would equal keccak256(uint8(0)), as well as keccak256(0x12345678) equals keccak256(uint32(0x12345678)).
You might come across an Out-of-Gas error for ripemd160, ecrecover or sha256 on a private blockchain. This is because those are implemented as “precompiled” contracts and those contracts only actually exist after they receive the first message (however, the code of their contract is hardcoded). Messages sent to non-existing contracts are more costly, thus the execution will run into an Out-of-Gas error. This problem can worked around by first sending e.g. 1 Wei to every single one of the contracts before using them in your actual contracts. That is not an issue on the official or test net.
- <address>.transfer(uint256 amount): used for sending specified number of Wei to an Address, will throw on failure
- <address>.callcode(…) returns (bool): used for issuing CALLCODE (low-level), will return false on failure
- <address>.balance (uint256): address’ balance in Wei
- <address>.delegatecall(…) returns (bool): used for issuing low-level DELEGATECALL, will return false on failure
- <address>.call(…) returns (bool): used for issuing low-level CALL, will return false on failure
- <address>.send(uint256 amount) will return (bool): used for sending specified amount of Wei to an Address, will return false on failure
The tutorial about Addresses expands on this topic.
Warning: using send is not always risk-free: The transfer will fail if the depth of the call stack is at 1024 (this is always possible force by the caller). Additionally, it also fails when the recipient runs out of gas. So, to make safe Ether transfers, You have to always check the return value of send, use transfer instead or even better: utilize a pattern where the recipient would withdraw the money.
Note: Using of callcode is not recommended , since it is planned for removal in the future.
- this (current contract’s type): the current contract, explicitly convertible to Address
- suicide(address recipient): used as an alias to selfdestruct
- selfdestruct(address recipient): used for destroying the current contract, sending its funds to a specified Address
Moreover, every function of the current contract is callable directly including the current function.