🔋Solidity Features
This is a list to explain and demonstrate new Solidity features as soon as they are completed.
Special Type Treatment for Integer Literals
PT Expressions only involving integer literals are now essentially treated as "big integers" (i.e. they do not overflow) until they are actually used with a non-literal. The type of the expression is only determined at that point as the smallest integer type that can contain the resulting value. Example:
Contracts Inherit all Members from Address
PT Contract types are implicitly convertible to address
and explicitly convertible to and from all integer types. Furthermore, a contract type contains all members of the address type with the semantics applying to the contract's address, unless overwritten by the contract.
ABI requires arguments to be padded to 32 bytes
PT The latest version of the ABI specification requires arguments to be padded to multiples of 32 bytes. This is not a language feature that can be demonstrated as code examples. Please see the automated tests SolidityEndToEndTests::packing_unpacking_types
and SolidityEndToEndTests::packing_signed_types
.
Specify value and gas for function calls
PT External functions have member functions "gas" and "value" that allow to change the default amount of gas (all) and wei (0) sent to the called contract. "new expressions" also have the value member.
delete for structs
PT delete
clears all members of a struct.
Note that, unfortunately, this only works directly on structs for now, so I would propose to not announce "delete" as a feature yet.
Contract Inheritance
PT1 PT2 Contracts can inherit from each other.
Function Modifiers
PT Modifiers can be used to easily change the behaviour of functions, for example to automatically check a condition prior to executing the function. They are inheritable properties of contracts and may be overridden by derived contracts.
Multiple modifiers can be applied to a function by specifying them in a whitespace-separated list and will be evaluated in order. Explicit returns from a modifier or function body immediately leave the whole function, while control flow reaching the end of a function or modifier body continues after the "_" in the previous modifier. Arbitrary expressions are allowed for modifier arguments and in this context, all symbols visible from the function are visible in the modifier. Symbols introduced in the modifier are not visible in the function (as they might change by overriding).
Conversion between String and Hash types
PT The explicit conversion between string
and hash
types of equal size is now allowed. Example:
Access to super
PT In the following contract, the function kill
is overridden by sibling classes. Due to the fact that the sibling classes do not know of each other, they can only call mortal.kill()
with the effect that one of the overrides is completely bypassed. A reasonable implementation would call the kill functions in all classes in the inheritance hierarchy.
The super
keyword solves this. Its type is the type of the current contract if it were empty, i.e. it contains all members of the current class' bases. Access to a member of super invokes the usual virtual member lookup, but it ends just above the current class. Using this keyword, the following works as expected:
State Variable Accessors
PT Public state variables now have accessors created for them. Basically any public
state variable can be accessed by calling a function with the same name as the variable.
For example in the above contract if you tried to call test's data()
method then you would obtain the result 42.
On the other hand on the above contract there is no accessor generated since the state variable is private.
Events
PT Events allow the convenient usage of the EVM logging facilities. Events are inheritable members of contracts. When they are called, they cause the arguments to be stored in the transaction's log. Up to three parameters can receive the attribute indexed
which will cause the respective arguments to be treated as log topics instead of data. The hash of the signature of the event is always one of the topics. All non-indexed arguments will be stored in the data part of the log. Example:
Here, the call to Deposit
will behave identical to log3(msg.value, 0x50cb9fe53daa9737b786ab3646f04d0150dc50ef4e75f59509d83667ad5adb20, sha3(msg.sender), _id);
. Note that the large hex number is equal to the sha3-hash of "Deposit(address,hash256,uint256)", the event's signature.
Fallback Functions
PT A contract can have exactly one unnamed function. This function cannot have arguments and is executed on a call to the contract if none of the other functions matches the given function identifier (or if no data was supplied at all).
Events in Exported Interfaces
PT Events are exported to the JSON and Solidity interfaces generated by the compiler. The contract
generates the JSON interface
and the Solidity interface contract c{event ev(uint256 indexed a,uint256 b);}
.
Visibility Specifiers
PT Functions and storage variables can be specified as being public
, protected
or private
, where the default for functions is public
protected
for storage variables. Public functions are part of the external interface and can be called externally, while for storage variables, an automatic accessor function is generated. Non-public functions are only visible inside a contract and its derived contracts (there is no distinction between protected
and private
for now).
External functions can call c.data()
to retrieve the value of data
in storage, but are not able to call f
.
Numeric Literals with Ether Subdenominations
PT Numeric literals can also be followed by the common ether subdenominations and the value of the assigned to variable will be multiplied by the proper amount.
SHA3 with arbitrary arguments
PT. sha3()
can now take an arbitrary number and type of arguments.
Optional Parameter Names
PT. The names for function parameters and return parameters are now optional.
Generic call Method
PT Address types (and contracts by inheritance) have a method call
that can receive an arbitrary number of arguments of arbitrary types (which can be serialized in memory) and will invoke a message call on that address while the arguments are ABI-serialized. If the first type has a memory-length of exactly four bytes, it is not padded to 32 bytes, so it is possible to specify a function signature.
Byte arrays
PT Basic support for variable-length byte arrays. This includes
bytes
type for storage variablesmsg.data
is ofbytes
type and contains the calldatafunctions taking arbitrary parameters (
call
,sha3
, ...) can be called withbytes
arguments.copying between
msg.data
andbytes
storage variables
What is not possible yet:
function parameters of
bytes
typelocal variables of
bytes
typeindex or slice access
Enums
PT Solidity now supports enums. Enums are explicitly convertible to all integer types but implicit conversion is not allowed.
Visibility Specifiers
PT The visibility of a function can be specified by giving at most one of the specifiers external
, public
, inheritable
or private
, where public
is the default. "External" functions can only be called via message-calls, i.e. from other contracts or from the same contract using this.function()
(note that this also prevents calls to overwritten functions in base classes). Furthermore, parameters of "external" functions are immutable. "Public" functions can be called from other contracts and from the same contract using stack-based calls. "Inheritable" and "private" functions can only be called via stack-based calls, while "inheritable" functions are only visible in the contract itself and its derived contracts and "private" functions are not even visible in derived contracts.
Import Statement
PT We can now import other contracts and/or standard library contracts using the import
keyword.
Inline members initialization
PT Inline members can be initialized at declaration time.
The arguments of the constructor of base contract
PT It is possible to pass arguments to the base contracts constructor. The arguments for the base constructor in the header will be optional later.
Detect failed CALLs
PT If a CALL fails, do not just silently continue. Currently, this issues a STOP but it will throw an exception once we have exceptions.
willFail
will always return an empty byte array (unless someone finds the correct private key...).
Basic features for arrays
PT Byte arrays and generic arrays of fixed and dynamic size are supported in calldata and storage with the following features: Index access, copying (from calldata to storage, inside storage, both including implicit type conversion), enlarging and shrinking and deleting. Not supported are memory-based arrays (i.e. usage in non-external functions or local variables), array accessors and features like slicing. Access to an array beyond its length will cause the execution to STOP (exceptions are planned for the future).
Now Variable
PT The global scope contains an immutable variable called now
which is an alias to block.timestamp
, i.e. it contains the timestamp of the current block.
HashXX and StringXX to bytesXX
[Link to PT] (https://www.pivotaltracker.com/story/show/88146508)
We replace
hash(XX*8)
andstringXX
bybytesXX
.bytesXX
behaves ashash(XX*8)
in terms of convertability and operators and asstringXX
in terms of layout in memory (alignment, etc).byte
is an alias forbytes1
.string
is reserved for future use.
msg.sig
returns the function's signature hash
msg.sig
returns the function's signature hash[Link to PT] (https://www.pivotaltracker.com/story/show/86896308) New magic type msg.sig
that will provide the hash of the current function signature as bytes4
type.
Calling that function will return 2FBEBD38
which is the hash of the signature of foo(uint256)
.
Constant variables
PT Added constant
specifier for uint, mapping and bytesXX types. Variables declared with constant
specifier should be initialized at declaration time and can not be changed later. For now local variables can not be constant. Constant variables are not stored in Storage.
Anonymous Events
PT Added anonymous
specifier for Event. For the event declared as anonymous the hash of the signature of the event will not be added as a first topic. The format is
Anonymous property is also visible for ABI document.
Tightly packed storage
PT Items in storage are packed tighly as far as possible according to the following rules:
The first item in a storage slot is stored lower-order aligned.
Elementary types use only that many bytes that are necessary to store them.
If an elementary type does not fit the remaining part of a storage slot, it is moved to the next storage slot.
Structs and array data always start a new slot and occupy whole slots (but items inside a struct or array are packed tightly according to these rules).
Examples:
Common Subexpression Elimination Excluding Memory and Storage
PT The optimizer splits code into blocks (at all operations that have non-local side effects like JUMP, CALL, CREATE and for also all instructions that access or modify memory or storage), analyses these blocks by creating an expression graph and establishes equivalences in a bottom-up way, simplifying expressions that e.g. involve constants. In the following code-generation phase, it re-creates the set of instructions that transform a given initial stack configuration into a given target stack configuration utilizing the simplest representatives of these equivalence classes. In conjunction with the already present jump-optimization, the two code snippets given below should be compiled into the same sequence of instructions:
Common Subexpression Elimination for Memory and Storage
PT This adds support for memory and storage operations to the common subexpression eliminator. This makes it possible to e.g. stretch the equality inference engine across SSTORE, MSTORE and even SHA3 computations (which go via memory). Without optimizer (because of packed storage), there are 4 SLOAD, 3 SSTORE and 4 SHA3 operations. The optimizer reduces those to a single SLOAD, SHA3 and SSTORE each.
External Types
PT All functions with visibility more than internal should have external types (ABI types) otherwise raise an error. For Contract type external type is address type.
the ABI interface for Poo is Poo(address) when the Solidity interface is still Poo(Foo).
Accessor for Arrays
PT For Arrays the accessor is generated which accepts the index as parameter and returns an array element
In the above contract if you tried to call the data(1) method of the test you would obtain the result 1.
Overloading Functions
PT Contracts can have multiple functions of the same name as long as the parameters differ in number or type. If such an overloaded function is referenced, it has to be called immediately to resolve the ambiguity using the types of the arguments. It is an error if not exactly one of the possible functions can be called with the given arguments.
Of course overloading a function does not need inheritance, i.e. f(uint a)
could as well have been defined directly in Derived
.
Overloaded functions are also present in the external interface. It is an error if two externally visible functions differ by their Solidity types but not by their external types, e.g. f(Derived _d)
and f(address _a)
both end up accepting an address
type for the ABI although they are considered different inside Solidity.
Merging of Basic Blocks
PT Blocks of assembly instructions that do not contain jumps, stops or returns are moved and modified according to the following rules:
if the control never simply flows into a block, but it is jumped to unconditionally, the block is moved, eliminating the jump
blocks that are never jumped to are removed
These optimizations might sound not very powerful, but together with "Common Subexpression Elimination" (which is does much more than its name might suggest), the following contract is optimized to store 8
in the mapping and return the value without any jump.
Interface contracts
PT Contracts can be marked as "not fully implemented" by containing at least one abstract function. A function is abstract if it does not have a body defined.
For example in the above, foo is an abstract function and as such the base contract is an interface contract. All non-interface contracts that derive from it must implement its abstract functions.
Last updated