当前位置: 首页 > 软件库 > Web3 > 区块链 >

solidity-cheatsheet

授权协议 MIT License
开发语言
所属分类 Web3、 区块链
软件类型 开源软件
地区 不详
投 递 者 单于煌
操作系统 跨平台
开源组织
适用人群 未知
 软件概览

Solidity Cheatsheet and Best practices

Motivation

This document is a cheatsheet for Solidity that you can use to write Smart Contracts for Ethereum based blockchain.

This guide is not intended to teach you Solidity from the ground up, but to help developers with basic knowledge who may struggle to get familiar with Smart Contracts and Blockchain because of the Solidity concepts used.

Note: If you have basic knowledge in JavaScript, it's easier to learn Solidity.

Table of contents

Version pragma

pragma solidity ^0.5.2; will compile with a compiler version >= 0.5.2 and < 0.6.0.

Import files

import "filename";

import * as symbolName from "filename"; or import "filename" as symbolName;

import {symbol1 as alias, symbol2} from "filename";

Types

Boolean

bool : true or false

Operators:

  • Logical : ! (logical negation), && (AND), || (OR)
  • Comparisons : == (equality), != (inequality)

Integer

Unsigned : uint8 | uint16 | uint32 | uint64 | uint128 | uint256(uint)

Signed : int8 | int16 | int32 | int64 | int128 | int256(int)

Operators:

  • Comparisons: <=, <, ==, !=, >= and >
  • Bit operators: &, |, ^ (bitwise exclusive or) and ~ (bitwise negation)
  • Arithmetic operators: +, -, unary -, unary +, *, /, %, ** (exponentiation), << (left shift) and >> (right shift)

Address

address: Holds an Ethereum address (20 byte value).address payable : Same as address, but includes additional methods transfer and send

Operators:

  • Comparisons: <=, <, ==, !=, >= and >

Methods:

balance

  • <address>.balance (uint256): balance of the Address in Wei

transfer and send

  • <address>.transfer(uint256 amount): send given amount of Wei to Address, throws on failure
  • <address>.send(uint256 amount) returns (bool): send given amount of Wei to Address, returns false on failure

call

  • <address>.call(...) returns (bool): issue low-level CALL, returns false on failure

delegatecall

  • <address>.delegatecall(...) returns (bool): issue low-level DELEGATECALL, returns false on failure

Delegatecall uses the code of the target address, taking all other aspects (storage, balance, ...) from the calling contract. The purpose of delegatecall is to use library code which is stored in another contract. The user has to ensure that the layout of storage in both contracts is suitable for delegatecall to be used.

contract A {
  uint value;
  address public sender;
  address a = address(0); // address of contract B
  function makeDelegateCall(uint _value) public {
    a.delegatecall(
        abi.encodePacked(bytes4(keccak256("setValue(uint)")), _value)
    ); // Value of A is modified
  }
}

contract B {
  uint value;
  address public sender;
  function setValue(uint _value) public {
    value = _value;
    sender = msg.sender; // msg.sender is preserved in delegatecall. It was not available in callcode.
  }
}

gas() option is available for call, callcode and delegatecall. value() option is not supported for delegatecall.

callcode

  • <address>.callcode(...) returns (bool): issue low-level CALLCODE, returns false on failure

Prior to homestead, only a limited variant called callcode was available that did not provide access to the original msg.sender and msg.value values.

Array

Arrays can be dynamic or have a fixed size.

uint[] dynamicSizeArray;

uint[7] fixedSizeArray;

Fixed byte arrays

bytes1(byte), bytes2, bytes3, ..., bytes32.

Operators:

Comparisons: <=, <, ==, !=, >=, > (evaluate to bool)Bit operators: &, |, ^ (bitwise exclusive or), ~ (bitwise negation), << (left shift), >> (right shift)Index access: If x is of type bytesI, then x[k] for 0 <= k < I returns the k th byte (read-only).

Members

  • .length : read-only

Dynamic byte arrays

bytes: Dynamically-sized byte array. It is similar to byte[], but it is packed tightly in calldata. Not a value-type!

string: Dynamically-sized UTF-8-encoded string. It is equal to bytes but does not allow length or index access. Not a value-type!

Enum

Enum works just like in every other language.

enum ActionChoices { 
  GoLeft, 
  GoRight, 
  GoStraight, 
  SitStill 
}

ActionChoices choice = ActionChoices.GoStraight;

Struct

New types can be declared using struct.

struct Funder {
    address addr;
    uint amount;
}

Funder funders;

Mapping

Declared as mapping(_KeyType => _ValueType)

Mappings can be seen as hash tables which are virtually initialized such that every possible key exists and is mapped to a value.

key can be almost any type except for a mapping, a dynamically sized array, a contract, an enum, or a struct. value can actually be any type, including mappings.

Control Structures

Most of the control structures from JavaScript are available in Solidity except for switch and goto.

  • if else
  • while
  • do
  • for
  • break
  • continue
  • return
  • ? :

Functions

Structure

function (<parameter types>) {internal|external|public|private} [pure|constant|view|payable] [returns (<return types>)]

Access modifiers

  • public - Accessible from this contract, inherited contracts and externally
  • private - Accessible only from this contract
  • internal - Accessible only from this contract and contracts inheriting from it
  • external - Cannot be accessed internally, only externally. Recommended to reduce gas. Access internally with this.f.

Parameters

Input parameters

Parameters are declared just like variables and are memory variables.

function f(uint _a, uint _b) {}

Output parameters

Output parameters are declared after the returns keyword

function f(uint _a, uint _b) returns (uint _sum) {
   _sum = _a + _b;
}

Output can also be specified using return statement. In that case, we can omit parameter name returns (uint).

Multiple return types are possible with return (v0, v1, ..., vn).

Constructor

Function that is executed during contract deployment. Defined using the constructor keyword.

contract C {
   address owner;
   uint status;
   constructor(uint _status) {
       owner = msg.sender;
       status = _status;
   }
}

Function Calls

Internal Function Calls

Functions of the current contract can be called directly (internally - via jumps) and also recursively

contract C {
    function funA() returns (uint) { 
       return 5; 
    }
    
    function FunB(uint _a) returns (uint ret) { 
       return funA() + _a; 
    }
}

External Function Calls

this.g(8); and c.g(2); (where c is a contract instance) are also valid function calls, but, the function will be called “externally”, via a message call.

.gas() and .value() can also be used with external function calls.

Named Calls

Function call arguments can also be given by name in any order as below.

function f(uint a, uint b) {  }

function g() {
    f({b: 1, a: 2});
}

Unnamed function parameters

Parameters will be present on the stack, but are not accessible.

function f(uint a, uint) returns (uint) {
    return a;
}

Function type

Pass function as a parameter to another function. Similar to callbacks and delegates

pragma solidity ^0.4.18;

contract Oracle {
  struct Request {
    bytes data;
    function(bytes memory) external callback;
  }
  Request[] requests;
  event NewRequest(uint);
  function query(bytes data, function(bytes memory) external callback) {
    requests.push(Request(data, callback));
    NewRequest(requests.length - 1);
  }
  function reply(uint requestID, bytes response) {
    // Here goes the check that the reply comes from a trusted source
    requests[requestID].callback(response);
  }
}

contract OracleUser {
  Oracle constant oracle = Oracle(0x1234567); // known contract
  function buySomething() {
    oracle.query("USD", this.oracleResponse);
  }
  function oracleResponse(bytes response) {
    require(msg.sender == address(oracle));
  }
}

Function Modifier

Modifiers can automatically check a condition prior to executing the function.

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

function close() onlyOwner {
    selfdestruct(owner);
}

View or Constant Functions

Functions can be declared view or constant in which case they promise not to modify the state, but can read from them.

function f(uint a) view returns (uint) {
    return a * b; // where b is a storage variable
}

The compiler does not enforce yet that a view method is not modifying state.

Pure Functions

Functions can be declared pure in which case they promise not to read from or modify the state.

function f(uint a) pure returns (uint) {
    return a * 42;
}

Payable Functions

Functions that receive Ether are marked as payable function.

Fallback Function

A contract can have exactly one unnamed function. This function cannot have arguments and cannot return anything. It is executed on a call to the contract if none of the other functions match the given function identifier (or if no data was supplied at all).

function() {
  // Do something
}

Contracts

Creating contracts using new

Contracts can be created from another contract using new keyword. The source of the contract has to be known in advance.

contract A {
    function add(uint _a, uint _b) returns (uint) {
        return _a + _b;
    }
}

contract C {
    address a;
    function f(uint _a) {
        a = new A();
    }
}

Contract Inheritance

Solidity supports multiple inheritance and polymorphism.

contract owned {
    function owned() { owner = msg.sender; }
    address owner;
}

contract mortal is owned {
    function kill() {
        if (msg.sender == owner) selfdestruct(owner);
    }
}

contract final is mortal {
    function kill() { 
        super.kill(); // Calls kill() of mortal.
    }
}

Multiple inheritance

contract A {}
contract B {}
contract C is A, B {}

Constructor of base class

contract A {
    uint a;
    constructor(uint _a) { a = _a; }
}

contract B is A(1) {
    constructor(uint _b) A(_b) {
    }
}

Abstract Contracts

Contracts that contain implemented and non-implemented functions. Such contracts cannot be compiled, but they can be used as base contracts.

pragma solidity ^0.4.0;

contract A {
    function C() returns (bytes32);
}

contract B is A {
    function C() returns (bytes32) { return "c"; }
}

Interface

Interfaces are similar to abstract contracts, but they have restrictions:

  • Cannot have any functions implemented.
  • Cannot inherit other contracts or interfaces.
  • Cannot define constructor.
  • Cannot define variables.
  • Cannot define structs.
  • Cannot define enums.
pragma solidity ^0.4.11;

interface Token {
    function transfer(address recipient, uint amount);
}

Events

Events allow the convenient usage of the EVM logging facilities, which in turn can be used to “call” JavaScript callbacks in the user interface of a dapp, which listen for these events.

Up to three parameters can receive the attribute indexed, which will cause the respective arguments to be searched for.

All non-indexed arguments will be stored in the data part of the log.

pragma solidity ^0.4.0;

contract ClientReceipt {
    event Deposit(
        address indexed _from,
        bytes32 indexed _id,
        uint _value
    );

    function deposit(bytes32 _id) payable {
        emit Deposit(msg.sender, _id, msg.value);
    }
}

Library

Libraries are similar to contracts, but they are deployed only once at a specific address, and their code is used with delegatecall (callcode).

library arithmatic {
    function add(uint _a, uint _b) returns (uint) {
        return _a + _b;
    }
}

contract C {
    uint sum;

    function f() {
        sum = arithmatic.add(2, 3);
    }
}

Using - For

using A for B; can be used to attach library functions to any type.

library arithmatic {
    function add(uint _a, uint _b) returns (uint) {
        return _a + _b;
    }
}

contract C {
    using arithmatic for uint;
    
    uint sum;
    function f(uint _a) {
        sum = _a.add(3);
    }
}

Error Handling

  • assert(bool condition): throws if the condition is not met - to be used for internal errors.
  • require(bool condition): throws if the condition is not met - to be used for errors in inputs or external components.
  • revert(): abort execution and revert state changes
function sendHalf(address addr) payable returns (uint balance) {
    require(msg.value % 2 == 0); // Only allow even numbers
    uint balanceBeforeTransfer = this.balance;
    addr.transfer(msg.value / 2);
    assert(this.balance == balanceBeforeTransfer - msg.value / 2);
    return this.balance;
}

Catching exceptions is not yet possible.

Global variables

Block variables

  • block.blockhash(uint blockNumber) returns (bytes32): hash of the given block - only works for the 256 most recent blocks excluding current
  • block.coinbase (address): current block miner’s address
  • block.difficulty (uint): current block difficulty
  • block.gaslimit (uint): current block gaslimit
  • block.number (uint): current block number
  • block.timestamp (uint): current block timestamp as seconds since unix epoch
  • now (uint): current block timestamp (alias for block.timestamp)

Transaction variables

  • msg.data (bytes): complete calldata
  • msg.gas (uint): remaining gas
  • msg.sender (address): sender of the message (current call)
  • msg.sig (bytes4): first four bytes of the calldata (i.e. function identifier)
  • msg.value (uint): number of wei sent with the message
  • tx.gasprice (uint): gas price of the transaction
  • tx.origin (address): sender of the transaction (full call chain)

Mathematical and Cryptographic Functions

  • addmod(uint x, uint y, uint k) returns (uint):compute (x + y) % k where the addition is performed with arbitrary precision and does not wrap around at 2**256.
  • mulmod(uint x, uint y, uint k) returns (uint):compute (x * y) % k where the multiplication is performed with arbitrary precision and does not wrap around at 2**256.
  • keccak256(...) returns (bytes32):compute the Ethereum-SHA-3 (Keccak-256) hash of the (tightly packed) arguments
  • sha256(...) returns (bytes32):compute the SHA-256 hash of the (tightly packed) arguments
  • sha3(...) returns (bytes32):alias to keccak256
  • ripemd160(...) returns (bytes20):compute RIPEMD-160 hash of the (tightly packed) arguments
  • ecrecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) returns (address):recover the address associated with the public key from elliptic curve signature or return zero on error (example usage)

Contract Related

  • this (current contract’s type): the current contract, explicitly convertible to Address
  • selfdestruct(address recipient): destroy the current contract, sending its funds to the given Address
  • suicide(address recipient): alias to selfdestruct. Soon to be deprecated.
  • 深入理解 Solidity 此节将帮助你深入理解Solidity,如果有遗漏,请和我们联系Gitter或者在Githhub上发pull request Layout of a Solidity Source File Importing other Source Files Comments Structure of a Contract Types Value Types Enums Refer

 相关资料
  • Solidity 是一门面向合约的、为实现智能合约而创建的高级编程语言。这门语言受到了 C++,Python 和 Javascript 语言的影响,设计的目的是能在以太坊虚拟机(EVM)上运行。 Solidity 是静态类型语言,支持继承、库和复杂的用户定义类型等特性。 下面您将会看到,使用 Solidity 语言,可以为投票、众筹、秘密竞价(盲拍)、多重签名的钱包以及其他应用创建合约。 注解 目

  • Solidity 是 Ethereum 的一种契约型编程语言,其语法与 JavaScript 类似,并且旨在定位到以太坊虚拟机。 Solidity 是静态类型的,支持继承、库和用户自定义类型以及其他功能。可以用来创建投票、众筹、盲拍、多签名钱包等合同。 Solidity 工具 Dapple 用于 Solidity 的软件包和部署管理器 Solidity REPL  控制台使用命令行尝试使用 Sol

  • Solidity定义了一个汇编语言,可以不同Solidity一起使用。这个汇编语言还可以嵌入到Solidity源码中,以内联汇编的方式使用。下面我们将从内联汇编如何使用着手,介绍其与独立使用的汇编语言的不同,最后再介绍这门汇编语言。 文档尚待完善的补充的地方:待补充内联汇编的变量作用域的不同,尤其是使用含internal的函数的库时所引入的复杂度。另外,还需补充,编译器定义的符号(symbols)

  • Solidity plugin for IntelliJ Features Syntax highlighting Code completion File templates Goto declaration Find usages Code formatting Supporting the plugin You can support the development by sponsorin

  • Browser-solidity 是 Solidity 在浏览器中的 IDE 和运行时环境。Solidity 是 Ethereum 的一种契约型编程语言,其语法与 JavaScript 类似,并且旨在定位到以太坊虚拟机。 离线使用: gh-pages 分支保持有最新的 Browser-solidity 稳定版本。它还包含具有整个构建的 ZIP 文件,下载可脱机使用。 注意:不支持其他编译器版本。

  • Solidity是一种智能合约高级语言,运行在Ethereum虚拟机(EVM)之上。 Solidity与其它语言相关的特点? 它的语法接近于Javascript,是一种面向对象的语言。但作为一种真正意义上运行在网络上的去中心合约,它又有很多的不同,下面列举一些: 以太坊底层是基于帐户,而非UTXO的,所以有一个特殊的Address的类型。用于定位用户,定位合约,定位合约的代码(合约本身也是一个帐户