Solidity Style Guide
In this article, we will explore some of the essential elements of a Solidity style guide and provide tips for writing clean, readable, and efficient Solidity code.
This Solidity Style Guide provides best practices and recommendations for writing Solidity code.
Maintaining a style guide helps maintain consistency in the layout of code and makes it easier to read. In order to write contracts with Solidity, the following best practices should be followed.
Solidity Code Layout
Well-organized code helps you and other developers understand the structure of your contracts and makes it easier to find specific sections of code.
The Solidity Style Guide recommends organizing your code into sections for imports, interfaces, contracts, and libraries, with each section separated by a single blank line.
1. Indentation
Consistent indentation and spacing make your code easier to read and understand.
The Solidity Style Guide recommends using two spaces for indentation, and adding a space after commas and around operators.
// SPDX-License-Identifier: 3.0
pragma solidity ^0.8.0;contract SolidityTest{// Here we declare all the functions,variables used in the code using 4 indentation spacesfunction get_Bio() public pure returns(string memory){return "We are learning about Indentation within a contract";
}// Similar pattern of indentation should be used with variable names
uint number=4;function get_Number() public view returns(uint){return number;}
}
<div class="spinner-border" role="status"><span class="sr-only">Loading...</span></div>
// SPDX-License-Identifier: 3.0
pragma solidity ^0.8.0;contract SolidityTest{function age_check(uint user_age) public pure returns(string memory){
if(user_age >= 18){ // As per style guide rule, we leave 4 spaces while declaring areturn "Congratulations !! You are Eligible to cast you vote";
}else{
return "Sorry !! We do not find you eligible to cast your vote !!";
}}}
<div class="spinner-border" role="status"><span class="sr-only">Loading...</span></div>
2. Two Blank Lines Rule
It is considered to be a good practice to leave two blank spaces between two contract definitions.
// SPDX-License-Identifier: 3.0
pragma solidity ^0.8.0;contract SolidityTest1{function get_String() public pure returns(string memory){return "Hey User !! Please make sure that you leave two lines between two contracts";
}}
// It is advisable to leave two lines after one contract definition closing bracketscontract SolidityTest2{uint mrx=52;
function get_number() public view returns(uint){return mrx;
}
}
<div class="spinner-border" role="status"><span class="sr-only">Loading...</span></div>
Here, we have created 2 different contracts and have arranged them on the basis of solidity style guide. For better understanding follow the example below:
// SPDX-License-Identifier: 3.0
pragma solidity ^0.8.0;contract SolidityTest1{function Product_Of_Numbers(uint mrx,uint ample) public pure returns(uint){return mrx*ample;}}// Here we left 2 lines spaces as per solidity style guide //contract SolidityTest2{
function Devide_Numbers(uint mrx,uint ample) public pure returns(uint){
return mrx/ample;
}
}contract Mr_Example_Final_Contract is SolidityTest1,SolidityTest2{SolidityTest1 obj1=new SolidityTest1();
SolidityTest2 obj2=new SolidityTest2();
function call_Contract() public view returns(uint,uint){uint result1=obj1.Product_Of_Numbers(4,7);
uint result2=obj2.Devide_Numbers(15,3);return(result1,result2);}
}
<div class="spinner-border" role="status"><span class="sr-only">Loading...</span></div>
3. One Blank Lines Rule
It is recommended to use one line space between two functions. If the function is just declared then there is no need to do this. For better understanding, consider the example below:
// SPDX-License-Identifier: 3.0
pragma solidity ^0.8.0;contract SolidityTest1{function get_String() public pure returns(string memory){return "Hey User !! Please make sure that you leave one lines space between two functions";
}
// This line is used as one line space between two functions with body
function get_bio() public pure returns(string memory){return "If function has no body then it is not must to leave one line space";
}}abstract contract SolidityTest2 {function balance() public virtual pure;
function account() public virtual pure;}
<div class="spinner-border" role="status"><span class="sr-only">Loading...</span></div>
// SPDX-License-Identifier: 3.0
pragma solidity ^0.8.0;contract SolidityTest{function Style_Guide() public pure returns(string memory){return "In Solidity Style Guide, We need one line spacing while declaring a function after function";}
// This is one line space left between two functions //
function Style_Guide2() public pure returns(string memory){return "As a perspective of style guide, Leaving one line space between to functions makes it readable and easier to understand the code";}}
<div class="spinner-border" role="status"><span class="sr-only">Loading...</span></div>
4. Maximum Line Length
Readers should be able to parse code easily if lines do not exceed 79 characters.
// SPDX-License-Identifier: 3.0
pragma solidity ^0.8.0;contract SolidityTest{function A_Big_Named_Function(
uint mrx1,
uint mrx2,
uint mrx3,
uint mrx4,
uint mrx5,
uint mrx6,
uint mrx7
) public pure returns(uint,uint,uint,uint,uint,uint,uint)
{return(mrx1,mrx2,mrx3,mrx4,mrx5,mrx6,mrx7);}
}
<div class="spinner-border" role="status"><span class="sr-only">Loading...</span></div>
5. Wrapping rules
It is recommended that the first argument be placed on a new line without opening parenthesis. You should use one indent per argument. The last element should be associated with a terminating element.
// SPDX-License-Identifier: 3.0
pragma solidity ^0.8.0;contract SolidityTest{function A_Big_Named_Function(
string memory mrx1,
string memory mrx2,
string memory mrx3,
string memory mrx4,
string memory mrx5,
string memory mrx6,
string memory mrx7
) public pure returns(string memory,string memory,string memory,string memory,string memory,string memory,string memory)
{return(mrx1,mrx2,mrx3,mrx4,mrx5,mrx6,mrx7);}
}
<div class="spinner-border" role="status"><span class="sr-only">Loading...</span></div>
6. Source Code Encoding
It is recommended to use UTF-8 or ASCII encodings.
7. Imports
These should be placed just after the pragma declaration at the top of the file.
8. Order of Functions
Functions should be grouped according to their visibility.
// SPDX-License-Identifier: 3.0
pragma solidity ^0.8.0;
contract Mr_Examples {
constructor() public {
// Write the block of code here
}
Function external_Function() external {
// Write the block of code here
}
// External functions
// Write the block of code here
// External view functions
// Write the block of code here
// External pure functions
// Write the block of code here
// Public functions
// Write the block of code here
// Internal functions
// Write the block of code here
// Private functions
// Write the block of code here
}
It is advisable to avoid extra spaces that are immediately inside parenthesis, brackets, or braces.
10. Control structures
It is recommended to open the brackets at the same time as the declaration. Ensure that they are closed on their own line in order to maintain the same indentation as before. Make use of space with an opening brace.
// SPDX-License-Identifier: 3.0
pragma solidity ^0.8.0;contract SolidityTest{struct My_Site{uint site_Id;
address site_address;
bool site_is_good;
}
My_Site[] public data;function add_Data(uint site_Id,address site_address,bool site_is_good) public {
My_Site memory Data = My_Site(site_Id,site_address,site_is_good);
data.push(Data);
}
}
<div class="spinner-border" role="status"><span class="sr-only">Loading...</span></div>
11. Error Handling
Handling errors in your smart contracts is important to ensure they function correctly and securely.
The Solidity Style Guide recommends using require() statements to check for valid input and assert() statements to check for internal errors.
Function Declaration
Braces should be used according to the above rule. It is always a wise idea to add a visibility label. It is necessary to place the visibility label first before adding any custom modifiers.
function Built() public Build_House {
selfdestruct(house);
}
Mappings
Make sure that you avoid whitespace while defining the mapping variables.
- mapping(uint => int) uint_to_int_)mapping;
- mapping(address => bool) confirmation_Address;
- mapping(uint => mapping(uint => string)) public info;
- mapping(uint => mapping(uint => address)) data_Address;
Variable declaration
Don’t use whitespace when declaring array variables.
uint[] x; is correct whereas unit [] x is considered as a wrong practice;
String Declaration
Double quotes should be used instead of single quotes to declare a string.
str = “Mr.Examples”; should be used instead of str = ‘Mr.Examples’;
Order of Layout
It is recommended to layout elements in the following order:
- Pragma statements
- Import statements
- Interfaces
- Libraries
- Contracts
It is recommended to order interfaces, libraries, or contracts as follows:
- Type declarations
- State variables
- Events
- Functions
- Naming conventions
It is recommended to name the contract and library according to CapWords style. For example:
MyContract, Contract_Main etc.
The names of the contracts and libraries should be the same as the names of the files.
If there are multiple contracts/libraries in a file, use the name of the core contract/library.
// SPDX-License-Identifier: 3.0// This shows the license version there is no need to modify this// The pragma version should always be in lower case as initialized belowpragma solidity ^0.8.0;contract SolidityTest1{ // As per naming conventions the CapWord style should be used for contract namesstruct My_Struct{ // The structures should also be initialized with the CapWord styleuint _id; // It is advisable to use mixedCase style while naming variables
string mrx_Name; // It is advisable to use mixedCase style while naming variables
bool is_Solidity_Fun; // It is advisable to use mixedCase style while naming variables
}My_Struct public ample; // The variable of the struct is initialized here to fetch details to the structfunction fetch_Data() public { // The function name should be in mixedCaseample=My_Struct(1,"Mr.Examples",true);
}function get_Id() public view returns(uint){ // The function name should be in mixedCasereturn ample._id;}
function get_Name() public view returns(string memory){ // The function name should be in mixedCasereturn ample.mrx_Name;}
function get_Bool() public view returns(bool){ // The function name should be in mixedCasereturn ample.is_Solidity_Fun;}
}contract SolidityTest2{ // As per naming conventions the CapWord style should be used for contract namesuint constant age=19; // It is advisable to use mixedCase style while naming variablesfunction change_Age() public pure returns(uint){ // The function name should be in mixedCaseuint new_Age=13; // It is advisable to use mixedCase style while naming variables// This returns an error because the value of the constant variable is not changeable
// age=new_Age;
return age;}
}
<div class="spinner-border" role="status"><span class="sr-only">Loading...</span></div>
In addition, the following naming conventions should be kept in mind while naming variables,structs and functions in solidity.
Naming Conventions | Overview |
Struct Names | You can use the CapWords style like My_Struct. |
Event Names | Make use of CapWords Styles like Pay_Money and Transfer_Amount. |
Function Names | Implementing a mixed case like my_Function is a smart idea. |
Local and state variables | It is recommended to use a mixed case style, such as sender_Address and supply. |
Constants | Separate words with all capital letters and underscores, such as MRX_AMPLE. |
Modifier Names | It is best to use a mixCase style like onlyData. |
Enum Names | It is recommended to use CapWords style just like My_Enum. |
Conclusion
To conclude, it comes as no surprise that following a Solidity style guide is one of the most important aspects of writing maintainable and high-quality code.
It is important to maintain a consistent coding style in order to make sure that the codebase is easier to read and understand.
This will make it easier for you and other developers to comprehend, manage, and enhance smart contracts.