solidity basics

1. Solidity is a high-level language with a syntax similar to JavaScript, which is designed to generate Ethereum virtual machine code in a compiled manner. As you'll find in the following pages, it's easy to use it to create contracts for voting, crowdfunding, closed auctions, multi-signature wallets, and more.

solidity在线IDE:https://ethereum.github.io/browser-solidity/#optimize=false&version=soljson-v0.4.23+commit.124ca40d.js

2. Smart contracts

A smart contract is a computer protocol designed to disseminate, verify or execute contracts in an informative manner. Only contracts allow for trusted transactions without third parties. These transactions are traceable and irreversible. The smart contract concept was first pointed out by Nick Azabo in 1994.

      The purpose of smart contracts is to provide security that is superior to traditional contracting methods, while reducing other costs associated with contract transactions.

3. Ethereum Virtual Machine

The Ethereum Virtual Machine (EVM) is a contract-only runtime environment in Ethereum. Not only is it sandboxed, in fact it is completely isolated, which means that code inside the EVM cannot pager to the network, filesystem, or other processes. Even only contracts have limited contact with other only contracts.

3.1. Account

There are two types of accounts in Ethereum. They share the same address space. An external account that is controlled by a public-private key pair (human). Contract accounts, which are controlled by the code stored in the account.

The external account is determined by the public key; the contract account is determined when the contract is created (calculated by the address of the contract creator + the number of transactions sent by the address. The number of transactions sent by the address is also called nonce); the contract account stores the code.

Additionally, each account has an ether balance (in wei) that can be changed by sending it a transaction with ether.

3.2. Transaction

A transaction is a message sent from one account to another (possibly the same account or zero account). Transactions can contain binary data (payload) and ether.

Also, if the target account has zero account (the account address is zero), the transaction will create a new contract. That is, creating a contract is also a transaction process, but the target account is 0.

3.3、Gas

Every transaction on Ethereum charges a certain amount of gas, and the purpose of gas is to limit the amount of work required to execute a transaction, while paying a fee for execution. When the EVM executes a transaction, gas will be gradually consumed according to certain rules.

The gas price (in ether) is designed by the transaction creator, and the sending account needs to prepay the transaction fee = gas price * gas amount. If there is any remaining gas after the execution, the gas will be returned to the sending account.

No matter where the execution is, once the gas is exhausted, an out-of-gas exception will be triggered. All state modifications made by the current calling frame will be rolled back.

3.3 Storage, Main Memory and Stack

Each account has a persistent area called storage, which is in the form of key-value, and the length of both key and value is 256 bits. In the contract, the storage of the account cannot be traversed. Compared with the other two, the read operation overhead of storage is larger, and the modification storage is even more expensive. A contract can only read and write to its own storage.

The second memory area is called main memory. Every time the contract executes a message call, there is a new piece of main memory that has been cleared. Main memory can be addressed at byte granularity, but read and write granularity is 32 bytes (256 bits). The overhead of operating main memory grows (square level) as it grows.

The EVM is not a register-based, but a stack-based virtual machine, so all computations are performed in an area called the stack. The stack has a maximum of 1024 elements, each of which is 256 bits, and access to the stack is limited to its top, by allowing one of the top 16 elements to be copied to the top of the stack, or swapping the top element and the bottom 16 elements one of the. All other operations take only the top two (or one, more) elements and push the result on top of the stack. Of course, you can put elements on the stack into storage or main memory, but you cannot access the element at the specified depth on the stack. Before that, all elements above the specified depth must be removed from the stack.

3.4, instruction set

The instruction set of the EVM is deliberately kept to a minimum size to avoid buggy implementations that could lead to consensus issues as much as possible. All instructions operate on the basic data type of 256 bits. Equipped with common arithmetic, bit, logic and comparison operations. Conditional and unconditional jumps are also possible. Additionally, the contract can access relevant properties of the current block, such as its number and timestamp.

3.5, message call

Contracts can call other contracts or send ether to non-contract accounts through message calls. Message calls and transactions are very similar in that they both have a source, a destination, data payload, ether, gas and return data. In fact each transaction can be thought of as a top-level message call, which in turn spawns more message calls.

A contract can decide the allocation of remaining gas. Such as how much gas is used for internal message calls, or how much gas is expected to be reserved. If an out-of-gas exception (or other exception) occurs during the internal message call, the contract will be notified and an error code will be pushed on the stack. This situation is just gas running out of internal message calls. In solidity, the contract making the call in this case triggers an artificial exception by default. This exception will print out the call stack. As said before, the called contract (and the calling contract as well) will have fresh main memory and be able to access the calling payload. The call payload is stored in a separate area called calldata. After the call is executed, the returned data will be stored in a block of memory pre-allocated by the caller.

Call levels are limited to 1024, so for more complex operations we should use loops instead of recursion.

3.6. Code calls and libraries

There is a special type of message call, called callcode. It is almost identical to a message call, except that the code that loads the target address will run in the context of the contract that made the call. This means that a contract can dynamically load code from another address at runtime. Both the current address and the balance of the store point to the contract that initiated the call, and only the code is obtained by the called address.

This enables solidity to implement libraries. The ingestible library code can be applied to a contract store and can be used to implement complex data structures.

3.7, log

At the block level, data can be stored using a special indexable data world. This feature is called logging, and Solidity uses it to implement events. Log data cannot be accessed after the contract is created, but this data can be efficiently accessed from outside the blockchain. Because part of the log data is stored in a bloom filter, we can search logs efficiently and securely, so that those logs can also be found by network nodes (light clients) that do not download the entire blockchain.

3.8. Create

Contracts can even create other contracts with a special instruction (not simply making a call to address zero). The difference between a call to create a contract and a normal message call is that the result of the execution of the payload data is treated as code. The caller/creator gets the new contract on the stack.

3.9. Self-destruction

The contract code is only removed from the blockchain when the contract at an address performs a self-destructing operation. The remaining ether on the contract address is sent to the designated target, and its storage and code are removed.

 4. Grammar

4.1. Import source files

Source files include any number of contract definitions and include directives

solidity supports import statements.

At the global level, you can use:

(1) import "filename"; will be from "filename"

(2)**import** ****** as symbolName from "filename" Create a global symbol named sumbolName, whose members come from all symbols of filename

(3) import {symbol as alias, symbol2} from "filename"; will create a new global variable alias: alias and symbol2, which will import symbol1 and symbol2 from filename respectively

(4) import "filename" as symbolName;//It is recommended to use equivalent to import * as symbolName from "filename"

path:

(1) In the above, the file name always uses / as the directory separator, . is the current directory, .. is the parent directory, and the path name does not need to start with . It will be regarded as an absolute path.

(2) Import a folder x from the same directory as the current file, use import "./x" as x; if you use import "x" as x; it is a different file reference (use "include directory" in the global )

(3) import "x" as X is a different file reference (use "include directory" in global).

(4) It will rely on the compiler (see later) to resolve the path. In general, the directory hierarchy doesn't have to map strictly to your local filesystem, it can also map to ipfs, http or other resources on git

4.2. Notes

//Single-line and multi-line comments (/../) 

There is a special kind of comment called "natspec" (which will be written later in the documentation), with three slashes (///) or two types (/*.../) to the right of a function declaration or definition. If you want Call a function that can use the documentation function in the doxygen-style tag, form validation, and provide a textual comment that confirms the condition to be displayed to the user.

 4.3. Type

solidity is a statically typed language, meaning that every variable (declared and local) is defined at compile time (or at least known, see type derivation later). Solidity provides several primitive types to be combined into complex types.

(1) Variable type

The following types are called value types because variables of these types are always assigned, as function parameters or in assignments, and always need to be copied.

boolean type

boolean: bool values ​​are true and false

Operators: ! (logical not), && (logical and), || (logical or), == (equal), != (not equal).

The operators || and && can apply the normal short-circuit rules, || if one side is true, the other side is not evaluated, and && if one side is false, the other side is not evaluated.

Integer types: int and uint, signed and unsigned integers, keywords uint8 to uint256 step size 8 (unsigned integers from 8 to 256 bits). uint and int are aliases for uint256 and int256 respectively.

Operators: comparison (<=,<,==,!=,>=,> to calculate boolean quantities), bitwise operators (&, |, ^ (bit exclusive or), ~ (bit inversion)), arithmetic operations (+, -, unary -, unary +, *, /, % (remainder), ** (power)).

Address member: address, which can transfer and query the balance (balance, send, transfer.

Note: If x is the contract address, its code will be executed together with the send call (this is a limitation of the EVM and cannot be modified), if the gas runs out or fails, the ether transfer will be rolled back, in this case, send returns false .

call and callcode: Calling these two functions will return true or false. The purpose of callcode is to use library code stored in another contract. The user must ensure that the layouts stored in both contracts are suitable for callcode. These two functions are very low-level functions that can be used as a last resort to break the type safety of solidity.

(2) Reference type

Complex types, copying complex types can be quite time consuming to store, we must consider storing them in memory (this is not persistent) or storage (where state variables are stored)

Function return parameters are stored in memory, and local variables are stored in memory by default.

(3) Data storage location: memory, storage, calldata

Arguments to external functions (no return): calldata

state variable: memory

Default data storage location

Function (with return) parameters: memory

Other local variables: memory.

Note that variables stored in different locations cannot be assigned directly.

Assignment between memory and memory, memory and memory is a reference assignment, the value will change, the other is copy, will not change the value.

(4) Array

Arrays can be fixed size or dynamic, and for memory arrays, the member type can be arbitrary (or other arrays, maps, or structures). For in-memory arrays, the member type cannot be a map; if it is a publicly visible function parameter, the member type must be of ABI type.

Dynamic array: string[] str;

Fixed-length array: string[3] str;

bytesh and string are special types of arrays. bytes is similar to byte[], but it is compacted in calldata. string is equal to bytes, but access by length or index is not allowed. Also if you want to access a certain byte of the string s, use bytes(s).length/bytes(s)[7] = "x"; remember, you are accessing the low-level utf - 8 byte representation, instead of a single character!

member:

length: The number of arrays. Once the length of the array is determined, an error will be reported if data other than the length is accessed. If the data in the array is deleted, the length and data location must be adjusted manually. Because deletion just initializes the value, it does not delete it.

push: add data to the end of the array.

Note: As of now it is not possible to use arrays of arrays in external functions. Due to the limitations of EVM, it is impossible for the contract function f contract C { function f() returns (uint[]) { ... } } to return a dynamic array from an external function call (cannot return an array). There is a return value, but using solidity calls, there is no return value.

(5) Structure

struct shape{uint height;uint width;} The function assigns shape(1,2). The structure can contain any type of data, but it cannot contain itself. That is, you cannot consider yourself a member of your own.

(6) Mapping

A key-value pair mapping relationship storage structure. Defined as mapping(_KeyType => _KeyValue). The type of key allows all types except mapping. The type of value is unlimited. A map can be thought of as a hash table where all possible keys have been virtualized created, mapped to a default value (zero in binary representation). But in the mapping table, we do not store the data of the key, only its keccak256 hash value, which is used for lookup. So the map has no length. mapping(address => uint) public balances;添加数据balance[msg.sender]=msg.value;

(7) Delete delete (Reference: http://baijiahao.baidu.com/s?id=1566265348199485&wfr=spider&for=pc)

delete is used to free space, and freeing space will return some gas.

Remove primitive types and set their values ​​to initial values. When an enumeration is deleted, its value is reset to the value of ordinal 0. The function cannot be deleted. Deleting the structure will set the variables in the structure to the initial value. Deleting the mapping will report an error, but you can delete an item in it. Remove all elements of the full-trial array and set it to 0.

The essence of deletion is to assign an initial value to a variable. Therefore, we will report an error when we delete the storage reference, because the storage reference does not have its own allocated storage space, so we cannot directly assign an initial value to the storage reference.

(8) Type conversion

Implicit conversion: If an operator is applied to a different type, the compiler will attempt to implicitly convert the operand types from one type to the other. In general, an implicit conversion between value types is possible, and if it is sensitive, information is not lost; int8 can be converted to int16, int256, etc., but int8 cannot be converted to uint256, because the uint256 range does not contain int8 part of the content.

Explicit conversions: int8 a = 2; uint b = uint(a); If a type is explicitly converted to a smaller type, the high-order bits are removed.

(9) Unit (Reference: https://blog.csdn.net/wo541075754/article/details/79049425)

Ether unit: wei, finney, szabo, ether, the default unit of ether quantity is wei.

1kwei(babbage) = 1e3wei (e is multiplied by 10 to the power of 3)

1Mwei(lovelace) = 1e6wei;  1Gwei(shannon) = 1e9; 1microether(szabo) = 1e12; 1milliether(finney) = 1e15wei; 1ether = 1e18wei;

Time unit: now gets the current time of the system, the type is int, no date: 1 seconds; minutes, hours, days, weeks, years , etc.

If you use these units to perform calendar calculations, be aware of the following issues. Every year is not always equal to 365 days, and not even every day has 24 hours, because of leap seconds. Since leap seconds cannot be predicted, an accurate calendar library must be updated by an external oracle. 

(10) Special variables and functions

There are special variables and functions that always exist in the global namespace and are mainly used to provide information about the blockchain.

Block and transaction properties:

  • block.coinbase (address): : The address of the miner of the current block
  • block.difficulty (uint): Difficulty coefficient of the current block
  • block.gaslimit (uint): current block gas limit
  • block.number (uint): current block number
  • block.blockhash (function(uint) returns (bytes32)): The hash of the specified block - the hash of the latest 256 blocks
  • block.timestamp (uint): timestamp of the current block
  • msg.data (bytes): complete calldata
  • msg.gas (uint): remaining gas
  • msg.sender (address): sender of the message (current call)
  • msg.sig (bytes4): the first four bytes of calldata (that is, the function identifier)
  • msg.value (uint): the amount of wei in the sent message
  • now (uint): current block timestamp (alias for block.timestamp)
  • tx.gasprice (uint): The gas price of the transaction
  • tx.origin (address): transaction sender (complete call chain)

Due to the scalability of all blocks, the hash value of (all) blocks is not available, you can only access the hash value of the most recent 256 blocks, and the other values ​​are zero.

(11) Math and encryption functions

addmod(uint x,uint y,uint z) return (uint) Calculate (X+y)%z

mulmod(uint x,uint y,uint z) return (uint) Calculate (X*y)%z

encrypted data

sha3(……) returns (byte32);

sha256(……) returns (byte32);

(12) Self-destruct

selfdestruct(address); Destroy the current contract and send its assets to the specified address. Also, all functions of the current contract can be called directly (including the current function)

4.4. Expressions and Control Structures

(1) Control structure:

Except for switch and goto, most of solidity's control structures come from C/JavaScript, and the semantics of if, else, while, for, break, continue, return, ? :, are the same as C/JavaScript.

Parentheses in conditional statements cannot be omitted, but curly braces before and after a single statement can be omitted.

(2) Function call

Internal function call: call the function directly;

External function call: To call a function externally and externally, the parameters must be stored in memory. Special attention is that the function cannot be called with this in the contract constructor. Because the current contract has not been created yet. If the contract name is called directly without instantiation, the contract does not execute the constructor,

Named parameter call: can be called directly, entering values ​​in order, or ({parameter: value,})

Function returns can return multiple values ​​of different types. Return tuple types are supported.

(3) Abnormal

There are some cases where exceptions are automatically thrown (see below). You can manually throw an exception using the throw directive. The effect of the exception is that the currently executing call is stopped and resumed (i.e. all state and balance changes have not occurred). In addition, exceptions can also be "buried" through Solidity functions, (once an "exception" occurs, send "exceptions", and the underlying functions of call and callcode return false).

It is impossible to catch exceptions.

Currently, Solidity exceptions occur automatically, in three cases: if you access the array beyond its length (i.e. x[i] where i >= x.length); if a function called via a message does not end properly (i.e. with gas finished, or itself throws an exception); if a function that does not exist in the library is called, or Ether is sent to a function library.

Exceptions are also bubbled up through solidity's function calls. (send, and the underlying function call call, delegatecall, callcode is an exception, when the exception occurs, these functions return false).

By assertjudging whether the internal conditions are met, requirethe validity of the input is verified. Such analysis tools can assume correct input and reduce errors. Such invalid opcodes will never appear. (return value is false)

 

5. Contract

Contracts are object-oriented language classes that persist in state variables and functions that can be modified. When the contract is created, the constructor will be called.

(1) Visibility and Modifiers

Function calls are divided into internal calls and external calls. Internal calls do not create a real EVM call, also known as message calls. External calls need to create a real EVM call.

Function modifiers include external, public, internal, and private, and the default is public. For state variables, external is not possible, the default is internal.

external: External functions are part of the contract interface, which means they can be called from other contracts, as well as through transactions. If the external contract is called in this contract, it is the same as the external contract calling this function, and cannot be called directly. External and public decorated functions can be accessed by external functions, but external saves gas.

public: Public functions are part of the contract interface and can be called internally or via messages. For public state variables, there will be automatic access modifier function generation (if a state variable is modified with public, the contract will automatically generate a get function for this variable, and to obtain this variable, you need to call the get method)

internal: These functions and state variables can only be accessed internally (i.e. the current contract or contracts derived from it) without using (keyword) this

private: Private functions and state variables are only visible in the contract that defines it, not in derived contracts.

Notice:

From outside observers, everything inside the contract is visible. Using private only prevents other contracts from accessing and modifying information (in this contract). But it is still visible to the whole world outside the blockchain.

The visibility specifier is placed after the type of the state variable, and (and optionally) between the parameter list and the parameter list returned by the function.

(2) function modifier (modifier)

Modifiers can be used to easily change the behavior of a function. For example, conditions are automatically checked before the function is executed. They are properties of inheritable contracts and can also be overridden by derived contracts. (You can encapsulate some conditions, etc., or encapsulate reused code. A function can use multiple modifiers, which are separated by spaces)

(3) constant (constant)

(4) Fallback function (callback)

A contract can have an anonymous function. If no other function matches the given legal entity function identifier, the function will have no parameters and will execute a contract call (if no data is provided).

1) When the contract receives a plain ether, the function will be executed (without data). In such a case, there is almost no gas for the function call, so it is very cheap to call the fallback function, which is very important.

2) This function is also executed when the contract receives ether (without any other data). In order to receive ether, the fallback function must be marked as payable. If such a feature does not exist, the contract cannot receive ether through normal transactions.

3) A contract that does not define a fallback function. If ether is received, an exception will be triggered and ether will be returned (since solidity v0.4.0). Therefore, in order to receive ether, the contract must implement a fallback function. Before deploying the contract to the network, make sure to thoroughly test your fallback function to ensure that the cost of function execution is controlled within 2300gas.

(5) Events

Events allow the convenient use of the EVM logging functionality, which can then be invoked sequentially in javascript in the dapp's user interface to listen for these events.

Events are inheritable members of contracts. When they are called, they cause some parameters to be stored in the transaction log - a special data structure on the blockchain. These logs are associated with the address of the contract, will be included in the blockchain, and stored in the block for easy access (permanent storage in Frontier and Homestead, but some changes in Serenity). Inside the contract, log and event data is not accessible (from the contract that created the log)

In the parameters of the event, if the parameter is set to indexed (up to three parameters can be set to indexed), to set whether to index, after setting the index, you can use this parameter to find the log, and even filter by a specific value.

If the parameter increases indexed, it is stored in the topic part of the log. If the parameter value corresponding to the event parameter is only a single value, it is normal storage (storage reaches the topic part of the log). If the parameter value corresponding to the event parameter is an array type, because The length of the complex type of the array type is uncertain, and it is first converted into a hash value.

If the parameter does not increase indexed, it is stored in the data part of the log.

Different index events stored in the log are called different topics. For example, event definition, event transfer(address indexed _from, address indexed _to, uint value) has three topics, the first topic is the default topic, namely event signature transfer(address, address, uint256), but if it is declared as anonymous event, there is no such topic; the other two indexed parameters will also form two topics, which can be filtered by _from and _to topics respectively. If arrays, including strings, and byte data are used as index parameters, the actual subject is the Keccak-256 hash of the corresponding value.

(6) Inheritance (is)

Solidity supports multiple inheritance, unless explicitly given in the contract, all function calls are virtual, and most derived functions can be called. Even if the contract inherits from multiple others.

Subclasses can access variables and functions controlled by public and internal permissions. State variables can be accessed in subclasses because state variables are internal by default.

1) Inheritance supports parameter passing. If the parent class constructor has parameters, it is Base(1) during inheritance

Method Two:

contract Base{
     uint a;
     function Base(uint _a){ 
        a = _a; 
    }
}
contract InheritParaModifier is Base{
     function InheritParaModifier(uint _a) Base(_a * _a){}
     function getBasePara() returns (uint){
           return a; 
     }
}
View Code

If you want to pass simple constants to the base class, the first way will be more concise. But if the incoming parameter is related to the input parameter of the subclass, then you should use the second way to get the parameter value. If you use both methods, the latter method will eventually take effect.

2) Multiple inheritance will have several problems, such as diamond inheritance problem (diamond problem), so multiple inheritance should pay attention to the order of inheritance. At the same time, if the inherited contract has methods or variables of different types with the same name, it will be regarded as an error. So it is recommended to use single inheritance.

(7) Abstract (contracts without keywords, but without method bodies will be regarded as abstract contracts)

If a contract inherits from an abstract contract, but does not implement all functions, then it is also an abstract contract.

(8) Interface (interface)

An interface is similar to an abstract contract. The difference is that no function in the interface is implemented, and there are also the following restrictions: . Cannot inherit other contracts or interfaces; cannot define constructors; cannot define variables; cannot define structures body; .Cannot define enum class.

(9) Library (library)

A library is similar to a contract, but its purpose is to deploy it only once at a specified address, and then reuse the code through the DELEGATECALL feature of the EVM. This means that when a library function is called, its code is executed in the context of the calling contract. Using this will point to the calling contract and have access to the calling contract's storage. Because a contract is an independent block of code, it only has access to state variables explicitly provided by the calling contract, otherwise there is no way to know about those state variables. (Call the local library (./libraryName.sol) in the same directory)

Libraries have limitations compared to normal contracts: no state variables. Cannot inherit or be inherited cannot receive ether.

Common for the library - "pit" The value of msg.sender The value of msg.sender will be the value of the contract calling the library function. For example, if A calls contract B, B internally calls library C. In the library C library function call, msg.sender will be the address of contract B. The expression LibraryName.functionName() completes the external function call with CALLCODE, which maps to a real EVM call, like otherContract.functionName() or this.functionName(). This call can extend the call depth level by level (up to 1024 levels), store msg.sender as the current caller, and then execute the code of the library contract instead of executing the current contract storage. This execution takes place in a completely new memory environment where the memory type will be copied and references cannot be bypassed. Transfer Ether In principle, use LibraryName.functionName.value(x)() to transfer Ether. But if CALLCODE is used, Ether will be used up in the current contract.

1) The directive using A for B; can be used to attach a library function (from library A) to any type (B). These functions will receive an object (like the self variable in Python) as the first argument.

using A for *;, means that the function is attached to any type from library A.

In both cases, all functions will be appended, (even those whose first argument's type does not match the object's type). The entry type of the called function will be checked, and function overload resolution will be performed.

 

6. Modifiers

modifier

  • constant for state variables: No assignment (except initialization) allowed, no memory block.

  • constant for functions: state changes are not allowed - this is not currently enforced.

  • anonymous for events: topic cannot be stored as event fingerprint.

  • Functions can declare views, in which case they are guaranteed not to modify the state. (The following declarations are considered to modify the state: 1). Write the state variable. 2). Send the event. 3). Create other contracts. 4). Use selfdestruct. 5). Send ether over the phone. 6). Call any function not marked as view or pure. 7). Use low level calls. 8). Use inline assembly that includes certain opcodes. .
    )
  • Functions can be declared pure, in which case they have no right to read or modify state. (In addition to the list of state modification statements explained above, the following are considered to be read from state: 1). Read from state variables 2). Access this.balance or <address>.balance. 3). Access to any member of block, tx, msg (except msg.sig and msg.data). 4). Call any function not marked pure. 5). Use inline assembly that includes certain opcodes.
    )

Guess you like

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