2017-06-19 10:02:03 +00:00
***** ***** ***** ***** ***** ***** **
2015-12-07 20:16:25 +00:00
Layout of a Solidity Source File
***** ***** ***** ***** ***** ***** **
2018-09-13 16:29:14 +00:00
Source files can contain an arbitrary number of
:ref: `contract definitions<contract_structure>` , import_ directives
and :ref: `pragma directives<pragma>` .
.. index :: ! pragma
.. _pragma:
Pragmas
=======
2016-08-19 17:57:21 +00:00
2019-02-27 15:14:43 +00:00
The `` pragma `` keyword is used to enable certain compiler features
2018-09-25 18:03:53 +00:00
or checks. A pragma directive is always local to a source file, so
you have to add the pragma to all your files if you want enable it
in all of your project. If you :ref: `import<import>` another file, the pragma
2019-02-27 15:14:43 +00:00
from that file does not automatically apply to the importing file.
2018-09-25 18:03:53 +00:00
2016-08-19 17:57:21 +00:00
.. index :: ! pragma, version
2017-03-16 00:42:42 +00:00
.. _version_pragma:
2016-08-19 17:57:21 +00:00
Version Pragma
2018-09-13 16:29:14 +00:00
--------------
2016-08-19 17:57:21 +00:00
2019-02-27 15:14:43 +00:00
Source files can (and should) be annotated with a version pragma to reject
compilation with future compiler versions that might introduce incompatible
changes. We try to keep these to an absolute minimum and
introduce them in a way that changes in semantics also require changes
in the syntax, but this is not always possible. Because of this, it is always
2016-08-19 17:57:21 +00:00
a good idea to read through the changelog at least for releases that contain
2019-02-27 15:14:43 +00:00
breaking changes. These releases always have versions of the form
2016-08-19 17:57:21 +00:00
`` 0.x.0 `` or `` x.0.0 `` .
The version pragma is used as follows::
2019-01-07 21:29:36 +00:00
pragma solidity ^0.5.2;
2016-08-19 17:57:21 +00:00
2019-02-27 15:14:43 +00:00
A source file with the line above does not compile with a compiler earlier than version 0.5.2,
and it also does not work on a compiler starting from version 0.6.0 (this
second condition is added by using `` ^ `` ). This is because
there will be no breaking changes until version `` 0.6.0 `` , so you can always
be sure that your code compiles the way you intended. The exact version of the
compiler is not fixed, so that bugfix releases are still possible.
2016-08-19 17:57:21 +00:00
2019-02-27 15:14:43 +00:00
It is possible to specify more complex rules for the compiler version,
these follow the same syntax used by `npm <https://docs.npmjs.com/misc/semver> `_ .
2015-12-07 20:16:25 +00:00
2018-09-25 18:03:53 +00:00
.. note ::
2019-02-27 15:14:43 +00:00
Using the version pragma *does not* change the version of the compiler.
It also *does not* enable or disable features of the compiler. It just
instructs the compiler to check whether its version matches the one
required by the pragma. If it does not match, the compiler issues
2018-09-25 18:03:53 +00:00
an error.
2018-09-13 16:29:14 +00:00
.. index :: ! pragma, experimental
.. _experimental_pragma:
Experimental Pragma
-------------------
The second pragma is the experimental pragma. It can be used to enable
features of the compiler or language that are not yet enabled by default.
The following experimental pragmas are currently supported:
ABIEncoderV2
~~~~~~~~~~~~
The new ABI encoder is able to encode and decode arbitrarily nested
arrays and structs. It produces less optimal code (the optimizer
for this part of the code is still under development) and has not
received as much testing as the old encoder. You can activate it
using `` pragma experimental ABIEncoderV2; `` .
2018-09-27 12:55:05 +00:00
.. _smt_checker:
2018-09-13 16:29:14 +00:00
SMTChecker
~~~~~~~~~~
This component has to be enabled when the Solidity compiler is built
and therefore it is not available in all Solidity binaries.
The :ref: `build instructions<smt_solvers_build>` explain how to activate this option.
It is activated for the Ubuntu PPA releases in most versions,
but not for solc-js, the Docker images, Windows binaries or the
statically-built Linux binaries.
If you use
`` pragma experimental SMTChecker; `` , then you get additional
safety warnings which are obtained by querying an SMT solver.
The component does not yet support all features of the Solidity language
and likely outputs many warnings. In case it reports unsupported
features, the analysis may not be fully sound.
2019-02-25 17:01:25 +00:00
.. index :: source file, ! import, module
2015-12-07 20:16:25 +00:00
2016-06-07 17:44:32 +00:00
.. _import:
2015-12-07 20:16:25 +00:00
Importing other Source Files
============================
2016-01-11 21:33:36 +00:00
Syntax and Semantics
--------------------
2015-12-07 20:16:25 +00:00
2019-02-25 17:01:25 +00:00
Solidity supports import statements to help modularise your code that are similar to those available in JavaScript
(from ES6 on). However, Solidity does not support the concept of a `default export <https://developer.mozilla.org/en-US/docs/web/javascript/reference/statements/export#Description> `_ .
2015-12-07 20:16:25 +00:00
2016-01-11 21:33:36 +00:00
At a global level, you can use import statements of the following form:
2015-12-07 20:16:25 +00:00
2016-02-18 09:34:23 +00:00
::
2016-01-11 21:33:36 +00:00
2016-02-18 09:34:23 +00:00
import "filename";
2016-01-11 21:33:36 +00:00
2016-08-05 08:30:40 +00:00
This statement imports all global symbols from "filename" (and symbols imported there) into the
2016-02-18 09:34:23 +00:00
current global scope (different than in ES6 but backwards-compatible for Solidity).
2019-02-25 17:01:25 +00:00
This form is not recommended for use, because it unpredictably pollutes the namespace.
If you add new top-level items inside "filename", they automatically
2018-09-13 16:41:08 +00:00
appear in all files that import like this from "filename". It is better to import specific
symbols explicitly.
The following example creates a new global symbol `` symbolName `` whose members are all
2019-02-25 17:01:25 +00:00
the global symbols from `` "filename" `` :
2016-02-18 09:34:23 +00:00
::
import * as symbolName from "filename";
2019-02-25 17:01:25 +00:00
which results in all global symbols being available in the format `` symbolName.symbol `` .
2016-02-18 09:34:23 +00:00
2019-02-25 17:01:25 +00:00
A variant of this syntax that is not part of ES6, but possibly useful is:
2016-01-11 21:33:36 +00:00
2016-02-18 09:34:23 +00:00
::
import "filename" as symbolName;
2016-08-05 08:45:52 +00:00
which is equivalent to `` import * as symbolName from "filename"; `` .
2016-01-11 21:33:36 +00:00
2019-02-25 17:01:25 +00:00
If there is a naming collision, you can rename symbols while importing. For example,
the code below creates new global symbols `` alias `` and `` symbol2 `` which reference
`` symbol1 `` and `` symbol2 `` from inside `` "filename" `` , respectively.
::
import {symbol1 as alias, symbol2} from "filename";
2018-10-25 16:28:24 +00:00
2016-01-11 21:33:36 +00:00
Paths
-----
2016-05-24 17:57:36 +00:00
In the above, `` filename `` is always treated as a path with `` / `` as directory separator,
2019-02-25 17:01:25 +00:00
and `` . `` as the current and `` .. `` as the parent directory. When `` . `` or `` .. `` is followed by a character except `` / `` ,
2017-01-02 15:13:57 +00:00
it is not considered as the current or the parent directory.
All path names are treated as absolute paths unless they start with the current `` . `` or the parent directory `` .. `` .
2016-01-11 21:33:36 +00:00
2019-02-25 17:01:25 +00:00
To import a file `` filename `` from the same directory as the current file, use `` import "./filename" as symbolName; `` .
If you use `` import "filename" as symbolName; `` instead, a different file could be referenced
2016-01-11 21:33:36 +00:00
(in a global "include directory").
2019-02-25 17:01:25 +00:00
It depends on the compiler (see :ref: `import-compiler` ) how to actually resolve the paths.
2016-01-11 21:33:36 +00:00
In general, the directory hierarchy does not need to strictly map onto your local
2019-02-25 17:01:25 +00:00
filesystem, and the path can also map to resources such as ipfs, http or git.
2016-01-11 21:33:36 +00:00
2018-09-13 16:41:08 +00:00
.. note ::
Always use relative imports like `` import "./filename.sol"; `` and avoid
using `` .. `` in path specifiers. In the latter case, it is probably better to use
global paths and set up remappings as explained below.
2019-02-25 17:01:25 +00:00
.. _import-compiler:
2016-08-11 20:50:53 +00:00
Use in Actual Compilers
2016-01-11 21:33:36 +00:00
-----------------------
2018-08-17 10:51:32 +00:00
When invoking the compiler, you can specify how to discover the first element
of a path, and also path prefix remappings. For
example you can setup a remapping so that everything imported from the virtual
directory `` github.com/ethereum/dapp-bin/library `` would actually be read from
your local directory `` /usr/local/dapp-bin/library `` .
If multiple remappings apply, the one with the longest key is tried first.
An empty prefix is not allowed. The remappings can depend on a context,
which allows you to configure packages to import e.g., different versions of a
library of the same name.
2016-01-11 21:33:36 +00:00
2016-01-13 16:34:59 +00:00
**solc** :
2018-08-17 10:51:32 +00:00
For solc (the commandline compiler), you provide these path remappings as
2016-06-07 17:44:32 +00:00
`` context:prefix=target `` arguments, where both the `` context: `` and the
2018-08-17 10:51:32 +00:00
`` =target `` parts are optional (`` target `` defaults to `` prefix `` in this
2016-01-11 21:33:36 +00:00
case). All remapping values that are regular files are compiled (including
2018-08-17 10:51:32 +00:00
their dependencies).
2015-12-07 20:16:25 +00:00
2018-08-17 10:51:32 +00:00
This mechanism is backwards-compatible (as long
as no filename contains `` = `` or `` : `` ) and thus not a breaking change. All
files in or below the `` context `` directory that import a file that starts with
`` prefix `` are redirected by replacing `` prefix `` by `` target `` .
For example, if you clone `` github.com/ethereum/dapp-bin/ `` locally to
`` /usr/local/dapp-bin `` , you can use the following in your source file:
2016-01-13 16:34:59 +00:00
2016-02-18 10:00:33 +00:00
::
import "github.com/ethereum/dapp-bin/library/iterable_mapping.sol" as it_mapping;
2016-01-13 16:34:59 +00:00
2018-08-17 10:51:32 +00:00
Then run the compiler:
2016-01-13 16:34:59 +00:00
2016-05-18 19:37:38 +00:00
.. code-block :: bash
2016-02-18 10:00:33 +00:00
solc github.com/ethereum/dapp-bin/=/usr/local/dapp-bin/ source.sol
2016-01-13 16:34:59 +00:00
2018-08-17 10:51:32 +00:00
As a more complex example, suppose you rely on a module that uses an old
version of dapp-bin that you checked out to `` /usr/local/dapp-bin_old `` , then you can run:
2016-06-07 17:44:32 +00:00
.. code-block :: bash
solc module1:github.com/ethereum/dapp-bin/=/usr/local/dapp-bin/ \
module2:github.com/ethereum/dapp-bin/=/usr/local/dapp-bin_old/ \
source.sol
2018-08-17 10:51:32 +00:00
This means that all imports in `` module2 `` point to the old version but imports
in `` module1 `` point to the new version.
.. note ::
2016-06-07 17:44:32 +00:00
2018-08-17 10:51:32 +00:00
`` solc `` only allows you to include files from certain directories. They have
to be in the directory (or subdirectory) of one of the explicitly specified
source files or in the directory (or subdirectory) of a remapping target. If
you want to allow direct absolute includes, add the remapping `` /=/ `` .
2016-01-29 22:17:43 +00:00
If there are multiple remappings that lead to a valid file, the remapping
with the longest common prefix is chosen.
2017-03-15 22:58:14 +00:00
**Remix** :
2016-01-13 16:34:59 +00:00
2018-08-17 10:51:32 +00:00
`Remix <https://remix.ethereum.org/> `_ provides an automatic remapping for
GitHub and automatically retrieves the file over the network. You can import
the iterable mapping as above, e.g.
2016-01-13 16:34:59 +00:00
2018-08-17 10:51:32 +00:00
::
import "github.com/ethereum/dapp-bin/library/iterable_mapping.sol" as it_mapping;
2015-12-07 20:16:25 +00:00
2018-08-17 10:51:32 +00:00
Remix may add other source code providers in the future.
2015-12-07 20:16:25 +00:00
.. index :: ! comment, natspec
Comments
========
2016-05-24 17:57:36 +00:00
Single-line comments (`` // `` ) and multi-line comments (`` /*...*/ `` ) are possible.
2015-12-07 20:16:25 +00:00
2016-02-18 10:08:20 +00:00
::
// This is a single-line comment.
2016-05-18 15:35:00 +00:00
2016-02-18 10:08:20 +00:00
/*
2016-05-18 15:35:00 +00:00
This is a
2016-02-18 10:08:20 +00:00
multi-line comment.
*/
2016-05-18 15:35:00 +00:00
2018-09-13 16:41:08 +00:00
.. note ::
A single-line comment is terminated by any unicode line terminator
(LF, VF, FF, CR, NEL, LS or PS) in utf8 encoding. The terminator is still part of
the source code after the comment, so if it is not an ascii symbol
(these are NEL, LS and PS), it will lead to a parser error.
2016-02-18 10:08:20 +00:00
2016-04-20 11:53:36 +00:00
Additionally, there is another type of comment called a natspec comment,
2017-05-15 10:45:26 +00:00
which is detailed in the :ref: `style guide<natspec>` . They are written with a
2016-05-24 17:57:36 +00:00
triple slash (`` /// `` ) or a double asterisk block(`` /** ... */ `` ) and
2016-05-18 15:35:00 +00:00
they should be used directly above function declarations or statements.
2017-06-11 05:41:15 +00:00
You can use `Doxygen <https://en.wikipedia.org/wiki/Doxygen> `_ -style tags inside these comments to document
2016-05-18 15:35:00 +00:00
functions, annotate conditions for formal verification, and provide a
2016-04-20 11:53:36 +00:00
**confirmation text** which is shown to users when they attempt to invoke a
function.
2016-08-05 11:16:14 +00:00
In the following example we document the title of the contract, the explanation
2018-10-24 11:23:15 +00:00
for the two function parameters and two return variables.
2016-08-05 11:16:14 +00:00
::
2019-03-05 17:10:09 +00:00
pragma solidity >=0.4.0 <0.7.0;
2016-09-05 11:54:54 +00:00
2017-07-17 09:24:18 +00:00
/** @title Shape calculator. * /
2018-05-26 19:37:52 +00:00
contract ShapeCalculator {
2017-07-17 09:24:18 +00:00
/** @dev Calculates a rectangle's surface and perimeter.
* @param w Width of the rectangle.
* @param h Height of the rectangle.
* @return s The calculated surface.
* @return p The calculated perimeter.
*/
2018-08-09 13:36:00 +00:00
function rectangle(uint w, uint h) public pure returns (uint s, uint p) {
2017-07-17 09:24:18 +00:00
s = w * h;
p = 2 * (w + h);
}
}