Solidity Coding Specification for Smart Contract Best Practices

Each language has its corresponding coding standards, and Solidity does the same. The following officially recommended standards and my summary are for your reference, hoping to help you write better and more standardized smart contracts.

Naming conventions

avoid using

Lowercase l, uppercase I, and uppercase O should be avoided in naming alone, as confusion can easily arise.

Contract, library, event, enumeration and structure naming

The names of contracts, libraries, events and structures should use the capitalization of the first letter of the word. This method is also called: Pascal notation or camel case notation, such as: SimpleToken, SmartBank, CertificateHashRepository, Player.

Functions, Parameters, Variables, and Decorators

Functions, parameters, variables and modifiers should use the first word lowercase followed by uppercase. This method is also known as: (small) camel case, which is a mixed case method, such as:

  • The function name should be like: getBalance, transfer, verifyOwner, addMember.
  • Parameters and variables should be like: initialSupply, senderAddress, account, isPreSale.
  • The decorator should be like: onlyAfter, onlyOwner.

Code format related

indentation

Use spaces instead of Tab, indent should be 4 spaces

Blank line

There should be blank lines between contracts, for example:

contract A {
    ...
}
    
    
contract B {
    ...
}
    
    
contract C {
    ...
}

instead of using:

contract A {
    ...
}
contract B {
    ...
}
    
contract C {
    ...
}
  • There should be blank lines between functions, for example:
contract A {
    function spam() public {
        ...
    }
    
    function ham() public {
        ...
    }
}

If not implemented, blank lines can be omitted, such as:

contract A {
    function spam() public;
    function ham() public;
}

instead of:

contract A {
    function spam() public {
        ...
    }
    function ham() public {
        ...
    }
}

The opening parenthesis should follow the definition on the same line

Definitions include contract definitions, function definitions, library definitions, structure definitions, etc. For example, it is recommended to use:

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

instead of:

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

The left parenthesis should be on the same line as the conditional control

When using if, else, while, for, the recommended way of writing is:

if (...) {
    ...
}

for (...) {
    ...
}

instead of:

if (...)
{
    ...
}

while(...){
}

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

If there is only one line in the control statement, the parentheses can be omitted, for example:

if (x < 10)
    x += 1;

But a statement like the following cannot be omitted if it has multiple parties, such as:

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

spaces within expressions

  • In a single-line expression, unnecessary spaces should be avoided between parentheses, square brackets, and curly brackets. For example, it is recommended to use:

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

    instead of:

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

    With one exception, the closing parenthesis following the closing semicolon should be followed by a space, as is also recommended:

    function singleLine() public { spam(); }
  • Semicolon; there should be no space before it, for example it is recommended to use:

    function spam(uint i, Coin coin) public;

    instead of:

    function spam(uint i , Coin coin) public ;
  • Don't add unnecessary spaces to the alignment, for example it is recommended to use:

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

    instead of:

    x             = 1;
    y             = 2;
    long_variable = 3;
  • The fallback function should not have spaces, for example it is recommended to use:

    function() public {
        ...
    }

    instead of:

    function () public {
        ...
    }

control the length of each line

Each line should not be too long, preferably within 79 (or 99) characters. The parameters of the function should be separate lines with only one indent. For example, the recommended way is:

thisFunctionCallIsReallyLong(
    longArgument1,
    longArgument2,
    longArgument3
);

instead of:

thisFunctionCallIsReallyLong(longArgument1,
                              longArgument2,
                              longArgument3
);

thisFunctionCallIsReallyLong(longArgument1,
    longArgument2,
    longArgument3
);

thisFunctionCallIsReallyLong(
    longArgument1, longArgument2,
    longArgument3
);

thisFunctionCallIsReallyLong(
longArgument1,
longArgument2,
longArgument3
);

thisFunctionCallIsReallyLong(
    longArgument1,
    longArgument2,
    longArgument3);

The corresponding assignment statement should be written like this:

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

instead of:

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

Event definitions should follow the same principles, for example they should use:

event LongAndLotsOfArgs(
    adress sender,
    adress recipient,
    uint256 publicKey,
    uint256 amount,
    bytes32[] options
);

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

instead of:

event LongAndLotsOfArgs(adress sender,
                        adress recipient,
                        uint256 publicKey,
                        uint256 amount,
                        bytes32[] options);

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

file encoding format

It is recommended to use utf-8 and ASCII encoding

The import file should be at the top

It is recommended to use:

import "owned";


contract A {
    ...
}


contract B is owned {
    ...
}

instead of:

contract A {
    ...
}


import "owned";


contract B is owned {
    ...
}

Function writing specification

order of functions

When writing functions, it should be easy for everyone to find constructors and fallback functions. The officially recommended function order is:

  1. Constructor
  2. Fallback function (if any)
  3. External function (external)
  4. public function
  5. Internal function (internal)
  6. private function

When the same type of function is used, the constant function is placed at the back. For example, the recommended method is:

 contract A {
    // 构造函数
    function A() public {
        ...
    }

    // 回退函数
    function() public {
        ...
    }

    // 外部函数
    // ...

    // 带有constant 外部函数 
    // ...

    // 公有函数
    // ...

    // 内部函数
    // ...

    // 私有函数
    // ...
}

instead of the following function order:

 contract A {


    // 外部函数
    // ...

    // 公有函数
    // ...

    // 内部函数
    // ...
    
    function A() public {
        ...
    }

    function() public {
        ...
    }

    // 私有函数
    // ...
}

explicit function visibility

All functions (including constructors) should have explicit function visibility when they are defined. For example, they should use:

function explicitlyPublic(uint val) public {
    doSomething();
}

instead of

function implicitlyPublic(uint val) {
    doSomething();
}

Visibility should come before modifiers

The visibility of the function should be written before the custom function modifier, for example:

function kill() public onlyowner {
    selfdestruct(owner);
}

instead of

function kill() onlyowner public {
    selfdestruct(owner);
}

Distinguish between functions and events

To prevent confusion between functions and events, declare an event in uppercase and add a prefix (you can use LOG). Always start with a lowercase letter for functions, except constructors.

// 不建议
event Transfer() {}
function transfer() {}

// 建议
event LogTransfer() {}
function transfer() external {}

constant

Constants should use all uppercase and underscore to separate big words, such as: MAX_BLOCKS, TOKEN_NAME, CONTRACT_VERSION.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325344407&siteId=291194637