Contents
What is Pragma in Solidity
In Solidity the pragma keyword is used to configure compiler features and checks. The pragma directive is always local to the current file and is not global. Hence to make it applicable in your entire project of Solidity you have to include pragma directive in every file to work.
In Solidity, there are the following types of Pragma –
- Version Pragma
- ABI Coder Pragma
- Experimental Pragma
1. Version Pragma
The version pragma directive of Solidity instructs the compiler to ensure that the code complies only for the given version or version range of the Solidity. Otherwise, the compilation should be rejected. As a matter of practice, one should always use the version Pragma in Solidity code to make sure that the non-supported functionality of the code does not break when compiled with future Solidity releases.
It should however be noted that using the version pragma has no effect on the compiler’s version. It does not even enable or disable compiler features. It simply tells the compiler to compare its version to the one specified by the pragma. The compiler throws an error if it doesn’t match.
Let us see how to use Version Pragmain Solidity.
Example 1
In the below example the pragma directive instructs the compiler to compile code for Solidity version greater than equal to 0.6.0 till up to but not including 0.8.0
// SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.6.0 <0.8.0; contract DemoContract { uint sampleData; function set(uint a) public { sampleData = a; } function getData() public view returns (uint) { return sampleData; } }
Example 2
In the below example the compiler will not compile code for versions before 0.6.1 and also for versions starting from 0.7.0 and above. However, it will compile from 0.6.1 to 0.7.0 (exclusive), this is because it is not expected that any functionality will break before the 0.7.0 version. This condition is taken care off by ^
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.6.1; contract DemoContract { uint sampleData; function set(uint a) public { sampleData = a; } function getData() public view returns (uint) { return sampleData; } }
2. ABI Coder Pragma
This pragma lets you choose between the v1 and v2 implementation of the ABI encoder and decoder. The v2 ABI coder supports nested array and struct types that were not available in v1.
It should be noted that v2 is default from solidity 0.8.0 hence pragma abicoder v1 has to be used to work with the old version of ABI coder.
Example 1 – Working with ABI Coder v2 Pragma
In the below example, we are creating contract with struct types which is not supported by default in the solidity version 0.7.0 hence it throws a compilation error.
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.7.0; contract Test { struct S { uint a; uint[] b; T[] c; } struct T { uint x; uint y; } function f(S memory, T memory, uint) public pure {} function g() public pure returns (S memory, T memory, uint) {} }
Compilation error –
contracts/Sample.sol:10:12: TypeError: This type is only supported in ABI coder v2. Use "pragma abicoder v2;" to enable the feature. function f(S memory, T memory, uint) public pure {} ^------^
To avoid this issue there are two options. First, we can use pragma abicoder v2; directive to make the code compatible with ABI Coder v2 that supports struct. We can see below that there is no compilation error this time.
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.7.0; pragma abicoder v2; contract Test { struct S { uint a; uint[] b; T[] c; } struct T { uint x; uint y; } function f(S memory, T memory, uint) public pure {} function g() public pure returns (S memory, T memory, uint) {} }
Another approach is to use Solidity 0.8.0 as it uses v2 ABI coder by default as shown below.
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.0; contract Test { struct S { uint a; uint[] b; T[] c; } struct T { uint x; uint y; } function f(S memory, T memory, uint) public pure {} function g() public pure returns (S memory, T memory, uint) {} }
Example 2 – Working with ABI Coder v1 Pragma
Since in 0.8.0 the v2 ABI Coder is used by default, and if you wish to use v1 then you can do it with pragma abicoder v1 as shown below.
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.0; pragma abicoder v1; contract DemoContract { uint sampleData; function set(uint a) public { sampleData = a; } function getData() public view returns (uint) { return sampleData; } }
3. Experimental Pragma
Experimental Pragma in Solidity is used to enable experimental features of Solidity that are not enabled by default.
Example
We discussed ABI coder above, however, it was just an experimental feature until 0.6.0 which is why the below code with struct types will throw a compilation error.
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.6.0; contract Test { struct S { uint a; uint[] b; T[] c; } struct T { uint x; uint y; } function f(S memory, T memory, uint) public pure {} function g() public pure returns (S memory, T memory, uint) {} }
Compilation Error
contracts/Sample.sol:12:12: TypeError: This type is only supported in ABIEncoderV2. Use "pragma experimental ABIEncoderV2;" to enable the feature. function f(S memory, T memory, uint) public pure {} ^------^
To overcome this, the pragma experimental ABIEncoderV2 can be used as below that compiles the code without any issues.
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.6.0; pragma experimental ABIEncoderV2; contract Test { struct S { uint a; uint[] b; T[] c; } struct T { uint x; uint y; } function f(S memory, T memory, uint) public pure {} function g() public pure returns (S memory, T memory, uint) {} }