An open API service indexing awesome lists of open source software.

https://github.com/0xcert/solidity-style-guide

Solidity style guide
https://github.com/0xcert/solidity-style-guide

ethereum smart-contract solidity styleguide

Last synced: about 1 year ago
JSON representation

Solidity style guide

Awesome Lists containing this project

README

          

# 0xcert Solidity Style Guide

## Introduction

This guide is based on the Solidity style guide that can be found here:
https://github.com/ethereum/solidity/blob/v0.5.1/docs/style-guide.rst. It mostly follows the guide
line but with slight changes and more specific restrictions.

This guide is intended to provide coding conventions for writing solidity code.
This guide should be thought of as an evolving document that will change over
time as useful conventions are found and old conventions are rendered obsolete.

## Code Layout

### Indentation

Use 2 spaces per indentation level.

### Tabs or Spaces

Spaces are the preferred indentation method.

Mixing tabs and spaces must be avoided.

### Multiple contracts in the same file

Each smart contract should be in its own file.

### Maximum Line Length

Maximum line length is 100 characters.

### Function Calls

Yes

thisFunctionCallIsReallyLong(
longArgument1,
longArgument2,
longArgument3
);

shortFunctionCall(arg1);

No

thisFunctionCallIsReallyLong(longArgument1,
longArgument2,
longArgument3
);

thisFunctionCallIsReallyLong(longArgument1,
longArgument2,
longArgument3
);

thisFunctionCallIsReallyLong(
longArgument1, longArgument2,
longArgument3
);

thisFunctionCallIsReallyLong(
longArgument1,
longArgument2,
longArgument3
);

thisFunctionCallIsReallyLong(
longArgument1,
longArgument2,
longArgument3);

#### Assignment Statements

Yes

thisIsALongNestedMapping[being][set][to_some_value] = someFunction(
argument1,
argument2,
argument3,
argument4
);

No

thisIsALongNestedMapping[being][set][to_some_value] = someFunction(argument1,
argument2,
argument3,
argument4);

#### Event Definitions and Event Emitters

Yes

event ShortOneArg(
address _sender
);

event LongAndLotsOfArgs(
address _sender,
address _recipient,
uint256 _publicKey,
uint256 _amount,
bytes32[] _options
);

emit LongAndLotsOfArgs(
sender,
recipient,
publicKey,
amount,
options
);

emit ShortOneArg(sender);

No

event ShortOneArg(address _sender);

event LongAndLotsOfArgs(address _sender,
address _recipient,
uint256 _publicKey,
uint256 _amount,
bytes32[] _options);

emit LongAndLotsOfArgs(sender,
recipient,
publicKey,
amount,
options);

### Source File Encoding

UTF-8 or ASCII encoding is preferred.

### Imports

Import statements must always be placed at the top of the file.

### Code Ordering

Functions and declarations must be grouped according to their visibility and ordered:

- constructor
- fallback function (if exists)
- external
- public
- internal
- private

Within a grouping, place the `view` and `pure` functions last.

Yes

pragma solidity >=0.4.0 <0.6.0;

contract A
{
using SafeMath for uint256;

uint256 someVariable;

event SomeEvent(
uint256 _arg1
);

modifier SomeModifier(
uint256 _arg1
)
{
// some check
_;
}

constructor()
public
{
// ...
}

function()
external
{
// ...
}

// External functions
// ...

// External functions that are view
// ...

// External functions that are pure
// ...

// Public functions
// ...

// Internal functions
// ...

// Private functions
// ...
}

No

pragma solidity >=0.4.0 <0.6.0;

contract A
{

// External functions
// ...

function()
external
{
// ...
}

// Private functions
// ...

// Public functions
// ...

constructor()
public
{
// ...
}

// Internal functions
// ...
}

### Whitespace in Expressions

Avoid extraneous whitespace in the following situations:

Yes

spam(ham[1], Coin({ name: "ham" }));

No

spam( ham[ 1 ], Coin( { name: "ham" } ) );

More than one space around an assignment or other operator to align with
another:

Yes

x = 1;
y = 2;
long_variable = 3;

No

x = 1;
y = 2;
long_variable = 3;

Control Structures

Yes

pragma solidity >=0.4.0 <0.6.0;

contract Coin
{
struct Bank
{
address owner;
uint balance;
}
}

No

pragma solidity >=0.4.0 <0.6.0;

contract Coin {
struct Bank {
address owner;
uint balance;
}
}

The same recommendations apply to the control structures `if`, `else`, `while`,
and `for`.

Additionally there must be a single space between the control structures
`if`, `while`, and `for` and the parenthetic block representing the
conditional, as well as a single space between the conditional parenthetic
block and the opening brace.

Yes

if (...)
{
...
}

No

if (...) {
...
}

while(...){
}

for (...) {
...;}

For control structures whose body contains a single statement, omitting the
braces is NOT ok in any condition.

Yes

if (x < 10)
{
x += 1;
}

No

if (x < 10)
x += 1;

if (x < 10)
someArray.push(Coin({
name: 'spam',
value: 42
}));

For `if` blocks which have an `else` or `else if` clause, the `else` must be
placed on the same line as the `if`'s closing brace. This is an exception compared
to the rules of other block-like structures.

Yes

if (x < 3)
{
x += 1;
}
else if (x > 7)
{
x -= 1;
}
else
{
x = 5;
}

if (x < 3)
{
x += 1;
}
else
{
x -= 1;
}

No

if (x < 3) {
x += 1;
} else {
x -= 1;
}

if (x < 3)
x += 1;
else
x -= 1;

### Function Declaration

For every function declarations, it is recommended to drop each argument onto
it's own line at the same indentation level as the function body. The closing
parenthesis and opening bracket must be placed on their own line as well at
the same indentation level as the function declaration.

Yes

function thisFunctionHasNoArguments()
public
{
doSomething();
}

function thisFunctionHasAnArgument(
address _a
)
public
{
doSomething();
}

function thisFunctionHasLotsOfArguments(
address _a,
address _b,
address _c,
address _d,
address _e,
address _f
)
public
{
doSomething();
}

No

function thisFunctionHasNoArguments() public
{
doSomething();
}

function thisFunctionHasAnArgument(address _a) public {
doSomething();
}

function thisFunctionHasLotsOfArguments(address _a, address _b, address _c,
address _d, address _e, address _f) public {
doSomething();
}

function thisFunctionHasLotsOfArguments(address _a,
address _b,
address _c,
address _d,
address _e,
address _f) public {
doSomething();
}

function thisFunctionHasLotsOfArguments(
address _a,
address _b,
address _c,
address _d,
address _e,
address _f) public {
doSomething();
}

If a function declaration has modifiers, then each modifier must be
dropped to its own line.

Yes

function thisFunctionNameIsReallyLong(
address _x,
address _y,
address _z
)
public
onlyowner
priced
returns (address)
{
doSomething();
}

function thisFunctionNameIsReallyLong(
address _x,
address _y,
address _z,
)
public
onlyowner
priced
returns (address)
{
doSomething();
}

No

function thisFunctionNameIsReallyLong(address _x, address _y, address _z)
public
onlyowner
priced
returns (address) {
doSomething();
}

function thisFunctionNameIsReallyLong(address _x, address _y, address _z)
public onlyowner priced returns (address)
{
doSomething();
}

function thisFunctionNameIsReallyLong(address _x, address _y, address _z)
public
onlyowner
priced
returns (address) {
doSomething();
}

Multiline output parameters and return statements must follow the same style.

Yes

function thisFunctionNameIsReallyLong(
address _a,
address _b,
address _c
)
public
returns (
address someAddressName,
uint256 LongArgument,
uint256 Argument
)
{
doSomething()

return (
veryLongReturnArg1,
veryLongReturnArg2,
veryLongReturnArg3
);
}

No

function thisFunctionNameIsReallyLong(
address _a,
address _b,
address _c
)
public
returns (address someAddressName,
uint256 LongArgument,
uint256 Argument)
{
doSomething()

return (veryLongReturnArg1,
veryLongReturnArg1,
veryLongReturnArg1);
}

For constructor functions on inherited contracts whose bases require arguments,
it is recommended to drop the base constructors onto new lines in the same
manner as modifiers.

Yes

pragma solidity >=0.4.0 <0.6.0;

// Base contracts just to make this compile
contract B {

constructor(
uint
)
public
{
}

}

contract C {

constructor(
uint,
uint
)
public
{
}

}

contract D {

constructor(
uint
)
public
{
}

}

contract A is
B,
C,
D
{
uint x;

constructor(
uint _param1,
uint _param2,
uint _param3,
uint _param4,
uint _param5
)
B(_param1)
C(_param2, _param3)
D(_param4)
public
{
// do something with param5
x = _param5;
}
}

No

pragma solidity >=0.4.0 <0.6.0;

// Base contracts just to make this compile
contract B {
constructor(uint) public {
}
}
contract C {
constructor(uint, uint) public {
}
}
contract D {
constructor(uint) public {
}
}

contract A is B, C, D {
uint x;

constructor(uint _param1, uint _param2, uint _param3, uint _param4, uint _param5)
B(_param1)
C(_param2, _param3)
D(_param4)
public
{
x = _param5;
}
}

contract X is B, C, D {
uint x;

constructor(uint _param1, uint _param2, uint _param3, uint _param4, uint _param5)
B(_param1)
C(_param2, _param3)
D(_param4)
public {
x = _param5;
}

### Mappings

In variable declarations, do not separate the keyword `mapping` from its
type by a space. Do not separate any nested `mapping` keyword from its type by
whitespace.

Yes

mapping(uint => uint) map;
mapping(address => bool) registeredAddresses;
mapping(uint => mapping(bool => Data[])) public data;
mapping(uint => mapping(uint => s)) data;

No

mapping (uint => uint) map;
mapping( address => bool ) registeredAddresses;
mapping (uint => mapping (bool => Data[])) public data;
mapping(uint => mapping (uint => s)) data;

### Variable Declarations

Declarations of array variables must not have a space between the type and
the brackets.

Yes

uint[] x;

No

uint [] x;

### Other Recommendations

* Strings must be quoted with double-quotes instead of single-quotes.

Yes

str = "foo";
str = "Hamlet says, 'To be or not to be...'";

No

str = 'bar';
str = '"Be yourself; everyone else is already taken." -Oscar Wilde';

* Surround operators with a single space on either side.

Yes

x = 3;
x = 100 / 10;
x += 3 + 4;
x |= y && z;

No

x=3;
x = 100/10;
x += 3+4;
x |= y&&z;

* Operators with a higher priority than others can exclude surrounding
whitespace in order to denote precedence. This is meant to allow for
improved readability for complex statement. You should always use the same
amount of whitespace on either side of an operator:

Yes

x = 2**3 + 5;
x = 2*y + 3*z;
x = (a+b) * (a-b);

No

x = 2** 3 + 5;
x = y+z;
x +=1;

## Order of Layout

Layout contract elements in the following order:

1. Pragma statements
2. Import statements
3. Interfaces
4. Libraries
5. Contract

Inside each contract, library or interface, use the following order:

1. Library declarations (`using` statements)
2. Constant variables
3. Type declarations
4. State variables
5. Events
6. Modifiers
7. Functions

## Naming Styles

To avoid confusion, the following names will be used to refer to different
naming styles.

* `b` (single lowercase letter)
* `B` (single uppercase letter)
* `lowercase`
* `lower_case_with_underscores`
* `UPPERCASE`
* `UPPER_CASE_WITH_UNDERSCORES`
* `CapitalizedWords` (or CapWords)
* `mixedCase` (differs from CapitalizedWords by initial lowercase character!)
* `Capitalized_Words_With_Underscores`
* `_underscoreMixedCase`

When using initialisms in CapWords, capitalize all the letters of the initialisms. Thus HTTPServerError is better than HttpServerError. When using initialisms is mixedCase, capitalize all the letters of the initialisms, except keep the first one lower case if it is the beginning of the name. Thus xmlHTTPRequest is better than XMLHTTPRequest.

### Names to Avoid

* `l` - Lowercase letter el
* `O` - Uppercase letter oh
* `I` - Uppercase letter eye

Never use any of these for single letter variable names. They are often
indistinguishable from the numerals one and zero.

### Contract and Library Names

* Contracts and libraries must be named using the CapWords style. Examples: `SimpleToken`, `SmartBank`, `CertificateHashRepository`, `Player`, `Congress`, `Owned`.

As shown in the example below, if the contract name is `Congress` and the library name is `Owned`, then their associated filenames should be `congress.sol` and `owned.sol`.

Yes

pragma solidity >=0.4.0 <0.6.0;

// owned.sol
contract Owned
{
address public owner;

constructor()
public
{
owner = msg.sender;
}

modifier onlyOwner
{
require(msg.sender == owner);
_;
}

function transferOwnership(
address _newOwner
)
public
onlyOwner
{
owner = _newOwner;
}
}

// congress.sol
import "./Owned.sol";

contract Congress is
Owned,
TokenRecipient
{
//...
}

No

pragma solidity >=0.4.0 <0.6.0;

// owned.sol
contract owned
{
address public owner;

constructor()
public
{
owner = msg.sender;
}

modifier onlyOwner
{
require(msg.sender == owner);
_;
}

function transferOwnership(
address _newOwner
)
public
onlyOwner
{
owner = _newOwner;
}
}

// Congress.sol
import "./owned.sol";

contract Congress is
owned,
tokenRecipient
{
//...
}

### Struct Names

Structs must be named using the CapWords style. Examples: `MyCoin`, `Position`, `PositionXY`.

### Event Names

Events must be named using the CapWords style. Examples: `Deposit`, `Transfer`, `Approval`, `BeforeTransfer`, `AfterTransfer`.

### Function Names

Functions other than constructors must use mixedCase. Examples: `getBalance`, `transfer`, `verifyOwner`, `addMember`, `changeOwner`.
If a function is `private` or `internal` function should use _underscoreMixedCase. Examples: `_calculateBalance` , `_doTransfer`.

### Function Argument Names

Function arguments must use _underscoreMixedCase. Examples: `_initialSupply`, `_account`, `_recipientAddress`, `_senderAddress`, `_newOwner`.

When writing library functions that operate on a custom struct, the struct
should be the first argument and should always be named `self`.

### Local and State Variable Names

Use mixedCase. Examples: `totalSupply`, `remainingSupply`, `balancesOf`, `creatorAddress`, `isPreSale`, `tokenExchangeRate`.

### Constants

Constants must be named with all capital letters with underscores separating
words. Examples: `MAX_BLOCKS`, `TOKEN_NAME`, `TOKEN_TICKER`, `CONTRACT_VERSION`.

### Modifier Names

Use mixedCase. Examples: `onlyBy`, `onlyAfter`, `onlyDuringThePreSale`.

### Enums

Enums, in the style of simple type declarations, must be named using the CapWords style. Examples: `TokenGroup`, `Frame`, `HashStyle`, `CharacterLocation`.