aboutsummaryrefslogtreecommitdiffstats
path: root/docs/style-guide.rst
diff options
context:
space:
mode:
Diffstat (limited to 'docs/style-guide.rst')
-rw-r--r--docs/style-guide.rst540
1 files changed, 540 insertions, 0 deletions
diff --git a/docs/style-guide.rst b/docs/style-guide.rst
new file mode 100644
index 00000000..0d7e900f
--- /dev/null
+++ b/docs/style-guide.rst
@@ -0,0 +1,540 @@
+.. index:: style, coding style
+
+#############
+Style Guide
+#############
+
+************
+Introduction
+************
+
+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.
+
+Many projects will implement their own style guides. In the event of
+conflicts, project specific style guides take precedence.
+
+The structure and many of the recommendations within this style guide were
+taken from python's
+`pep8 style guide <https://www.python.org/dev/peps/pep-0008/>`_.
+
+The goal of this guide is *not* to be the right way or the best way to write
+solidity code. The goal of this guide is *consistency*. A quote from python's
+`pep8 <https://www.python.org/dev/peps/pep-0008/#a-foolish-consistency-is-the-hobgoblin-of-little-minds>`_
+captures this concept well.
+
+ A style guide is about consistency. Consistency with this style guide is important. Consistency within a project is more important. Consistency within one module or function is most important.
+ But most importantly: know when to be inconsistent -- sometimes the style guide just doesn't apply. When in doubt, use your best judgment. Look at other examples and decide what looks best. And don't hesitate to ask!
+
+
+***********
+Code Layout
+***********
+
+
+Indentation
+===========
+
+Use 4 spaces per indentation level.
+
+Tabs or Spaces
+==============
+
+Spaces are the preferred indentation method.
+
+Mixing tabs and spaces should be avoided.
+
+Blank Lines
+===========
+
+Surround top level declarations in solidity source with two blank lines.
+
+Yes::
+
+ contract A {
+ ...
+ }
+
+
+ contract B {
+ ...
+ }
+
+
+ contract C {
+ ...
+ }
+
+No::
+
+ contract A {
+ ...
+ }
+ contract B {
+ ...
+ }
+
+ contract C {
+ ...
+ }
+
+Within a contract surround function declarations with a single blank line.
+
+Blank lines may be omitted between groups of related one-liners (such as stub functions for an abstract contract)
+
+Yes::
+
+ contract A {
+ function spam();
+ function ham();
+ }
+
+
+ contract B is A {
+ function spam() {
+ ...
+ }
+
+ function ham() {
+ ...
+ }
+ }
+
+No::
+
+ contract A {
+ function spam() {
+ ...
+ }
+ function ham() {
+ ...
+ }
+ }
+
+Source File Encoding
+====================
+
+UTF-8 or ASCII encoding is preferred.
+
+Imports
+==========
+
+Import statements should always be placed at the top of the file.
+
+Yes::
+
+ import "owned";
+
+
+ contract A {
+ ...
+ }
+
+
+ contract B is owned {
+ ...
+ }
+
+No::
+
+ contract A {
+ ...
+ }
+
+
+ import "owned";
+
+
+ contract B is owned {
+ ...
+ }
+
+Whitespace in Expressions
+=========================
+
+Avoid extraneous whitespace in the following situations:
+
+* Immediately inside parenthesis, brackets or braces.
+
+Yes: `spam(ham[1], Coin({name: "ham"}));`
+
+No: `spam( ham[ 1 ], Coin( { name: "ham" } ) );`
+
+* Immediately before a comma, semicolon:
+
+Yes: `function spam(uint i, Coin coin);`
+
+No: `function spam(uint i , Coin coin) ;`
+
+* 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
+==================
+
+The braces denoting the body of a contract, library, functions and structs
+should:
+
+* open on the same line as the declaration
+* close on their own line at the same indentation level as the beginning of the
+ declaration.
+* The opening brace should be proceeded by a single space.
+
+Yes::
+
+ contract Coin {
+ struct Bank {
+ address owner;
+ uint balance;
+ }
+ }
+
+No::
+
+ contract Coin
+ {
+ struct Bank {
+ address owner;
+ uint balance;
+ }
+ }
+
+The same recommendations apply to the control structures `if`, `else`, `while`,
+and `for`.
+
+Additionally there should 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 (...) {
+ ...
+ }
+
+ for (...) {
+ ...
+ }
+
+No::
+
+ if (...)
+ {
+ ...
+ }
+
+ while(...){
+ }
+
+ for (...) {
+ ...;}
+
+For control structures who's body contains a single statement, omitting the
+braces is ok *if* the statement is contained on a single line.
+
+Yes::
+
+ if (x < 10)
+ x += 1;
+
+No::
+
+ if (x < 10)
+ someArray.push(Coin({
+ name: 'spam',
+ value: 42
+ }));
+
+For `if` blocks which have an `else` or `else if` clause, the `else` should be
+placed on it's own line following the previous closing parenthesis. The
+parenthesis for the else block should follow the same rules as the other
+conditional control structures.
+
+Yes::
+
+ if (x < 3) {
+ x += 1;
+ }
+ else {
+ x -= 1;
+ }
+
+
+ if (x < 3)
+ x += 1;
+ else
+ x -= 1;
+
+No::
+
+ if (x < 3) {
+ x += 1;
+ } else {
+ x -= 1;
+ }
+
+Function Declaration
+====================
+
+For short function declarations, it is recommended for the opening brace of the
+function body to be kept on the same line as the function declaration.
+
+The closing brace should be at the same indentation level as the function
+declaration.
+
+The opening brace should be preceeded by a single space.
+
+Yes::
+
+ function increment(uint x) returns (uint) {
+ return x + 1;
+ }
+
+ function increment(uint x) public onlyowner returns (uint) {
+ return x + 1;
+ }
+
+No::
+
+ function increment(uint x) returns (uint)
+ {
+ return x + 1;
+ }
+
+ function increment(uint x) returns (uint){
+ return x + 1;
+ }
+
+ function increment(uint x) returns (uint) {
+ return x + 1;
+ }
+
+ function increment(uint x) returns (uint) {
+ return x + 1;}
+
+The visibility modifiers for a function should come before any custom
+modifiers.
+
+Yes::
+
+ function kill() public onlyowner {
+ selfdestruct(owner);
+ }
+
+No::
+
+ function kill() onlyowner public {
+ selfdestruct(owner);
+ }
+
+For long function declarations, it is recommended to drop each arguent onto
+it's own line at the same indentation level as the function body. The closing
+parenthesis and opening bracket should be placed on their own line as well at
+the same indentation level as the function declaration.
+
+Yes::
+
+ function thisFunctionHasLotsOfArguments(
+ address a,
+ address b,
+ address c,
+ address d,
+ address e,
+ address f,
+ ) {
+ do_something;
+ }
+
+No::
+
+ function thisFunctionHasLotsOfArguments(address a, address b, address c,
+ address d, address e, address f) {
+ do_something;
+ }
+
+ function thisFunctionHasLotsOfArguments(address a,
+ address b,
+ address c,
+ address d,
+ address e,
+ address f) {
+ do_something;
+ }
+
+ function thisFunctionHasLotsOfArguments(
+ address a,
+ address b,
+ address c,
+ address d,
+ address e,
+ address f) {
+ do_something;
+ }
+
+If a long function declaration has modifiers, then each modifier should be
+dropped to it's own line.
+
+Yes::
+
+ function thisFunctionNameIsReallyLong(address x, address y, address z)
+ public
+ onlyowner
+ priced
+ returns (address)
+ {
+ do_something;
+ }
+
+ function thisFunctionNameIsReallyLong(
+ address x,
+ address y,
+ address z,
+ )
+ public
+ onlyowner
+ priced
+ returns (address)
+ {
+ do_something;
+ }
+
+No::
+
+ function thisFunctionNameIsReallyLong(address x, address y, address z)
+ public
+ onlyowner
+ priced
+ returns (address) {
+ do_something;
+ }
+
+ function thisFunctionNameIsReallyLong(address x, address y, address z)
+ public onlyowner priced returns (address)
+ {
+ do_something;
+ }
+
+ function thisFunctionNameIsReallyLong(address x, address y, address z)
+ public
+ onlyowner
+ priced
+ returns (address) {
+ do_something;
+ }
+
+For constructor functions on inherited contracts who's bases require arguments,
+it is recommended to drop the base constructors onto new lines in the same
+manner as modifiers if the function declaration is long or hard to read.
+
+Yes::
+
+ contract A is B, C, D {
+ function A(uint param1, uint param2, uint param3, uint param4, uint param5)
+ B(param1)
+ C(param2, param3)
+ D(param4)
+ {
+ // do something with param5
+ }
+ }
+
+No::
+
+ contract A is B, C, D {
+ function A(uint param1, uint param2, uint param3, uint param4, uint param5)
+ B(param1)
+ C(param2, param3)
+ D(param4)
+ {
+ // do something with param5
+ }
+ }
+
+ contract A is B, C, D {
+ function A(uint param1, uint param2, uint param3, uint param4, uint param5)
+ B(param1)
+ C(param2, param3)
+ D(param4) {
+ // do something with param5
+ }
+ }
+
+
+These guidelines for function declarations are intended to improve readability.
+Authors should use their best judgement as this guide does not try to cover all
+possible permutations for function declarations.
+
+Mappings
+========
+
+TODO
+
+Variable Declarations
+=====================
+
+Declarations of array variables should not have a space between the type and
+the brackets.
+
+Yes: `uint[] x;`
+No: `uint [] x;`
+
+Other Recommendations
+=====================
+
+* 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 precidence. 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;
+
+Naming Conventions
+==================
+
+TODO
+
+General Recommendations
+=======================
+
+TODO