Solidity File Structure

What is a Solidity File?

As mentioned in Remix - A First Glance, all Solidity file have the file extension .sol . However, we have not yet covered what a Solidity file actually contains. In this section, we will go over the general structure of a Solidity file.

Most Solidity files contain the following components (in order):

  1. SPDX License Identifier

  2. Solidity Version

  3. File Imports

  4. Contracts

SPDX License Identifier

The Software Package Data Exchange (SPDX) License Identifier is commonly found at the top of most smart contracts. Although not required, many compiler (such as the Remix compiler) will give you warnings if your Solidity files do not include a SPDX license identifier.

Smart contract code, like all other digital content, are subject to copyright laws. Rather than having to go through the hassle of contacting the developer of a smart contract which you wish to use, the SPDX license identifier communicates to all potential users the manners if which one is allowed and is not allowed to use said smart contract code.

The MIT license identifier is one of the most commonly used SPDX license identifiers. Looking at the license itself, we can see that any contract with the MIT license has almost no limitations to its use:

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Not all smart contracts can be used freely, however. A famous case of this is with the Uniswap V3 contract code; being protected under the BSD-1.1 license, users were not able to utilize the code in a production/commericial setting (i.e. deploying Uniswap V3 on other blockchains) until April 1st, 2023.

Solidity Version

Due to there being multiple versions of Solidity, following the SPDX License Identifier, we must declare the version of Solidity which we wish to use to compile our file. The Solidity version declaration is as follows:

pragma solidity 0.8.0;

In the above code snippet, we are telling our compiler that we wish to use Solidity version 0.8.0. However, we are not restricted to using solely a single version. Consider the following:

pragma solidity ^0.8.0;

In contrast to the first code snippet, the second code snippet tells the compiler that we wish to compile using any version of Solidity greater or equal to version 0.8.0. An implicit restriction imposed by the caret symbol is that we wish to compile with versions of Solidity with the prefix 0.8. As an example, if we specify the compiler version of our Solidity contract to be ^0.7.0, we cannot compile with 0.6.* compiler, 0.8.* compiler, etc. This is because between different major versions (i.e. 0.x.*, 0.y.* where x != y), there exists incompatible differences.

Furthermore, we can also declare a range of versions for which we want our contract to compile to; an example of this is as follows:

pragma solidity >=0.7.6 < 0.8.17;

Here, we are telling the compiler that we wish to compile this contract with any version of Solidity greater than or equal to version 0.7.6 and less than 0.8.17.

Aren't We Combining Incompatible Solidity Versions?

The statement pragma solidity >=0.7.6 < 0.8.17; might seem to contradict the earlier statement about mixing major versions. However, it is implicitly assumed that our contract will be compiled with any version within the range that does not break its functionality.

File Imports

Like with most other programming languages, we can divide up our code into different files in order to avoid merging our code into a single file. Assume the directory we are working in is as follows:

> HelloWorld.sol
> HelloMoon.sol

If we are working with HelloWorld.sol, and we wish to import HelloMoon.sol, we can write the following in HelloWorld.sol :

import "./HelloMoon.sol";

In practice, we sometimes might prefer to inherit only certain objects (i.e. contracts, interfaces, libaries, etc.) from a file. Assume the following is the contents of HelloMoon.sol:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract A {}

contract B {}

If we wished to only import contract A, we would write the following in HelloWorld.sol:

import {A} from "./HelloMoon.sol";

Contracts

This section is self-explanatory; this is where your smart contracts will live.

Resources

SPDX Tutorial: https://github.com/david-a-wheeler/spdx-tutorial/blob/master/README.md#spdx-license-identifiers

MIT License: https://opensource.org/license/mit/

Uniswap V3 BSD-1.1 License: https://support.uniswap.org/hc/en-us/articles/14569783029645-Uniswap-v3-Licensing-

Solidity Docs: https://docs.soliditylang.org/en/latest/layout-of-source-files.html

Last updated