Solidity is the main programming language for Ethereum. Solidity is a statically typed javasco-esque language that is contract-oriented, high-level programming language created to implement smart contracts and designed to run on the Ethereum Virtual Machine (EVM).

IO /zh/

contract

The Solidity code is wrapped in the contract. A contract is the basic building block of Ethernet applications. All variables and functions belong to a contract. It’s the starting point for all your applications.

An empty contract named HelloWorld reads as follows:

contract HelloWorld {

}
Copy the code

hello world

Let’s start with a simple smart contract.

pragma solidity ^0.4. 0;

contract SimpleStorage {
    uint storedData; // Declare a state variable of type uint (256-bit unsigned integer) called storedData

    function set(uint x) public {
        storedData = x; // State variables can be accessed directly without using this. Or self. Such a prefix
    }

    function get() public view returns (uint) {
        returnstoredData; }}Copy the code

All Solidity source code must be titled with “Version pragma” – indicating the version of the Solidity compiler. To avoid the possibility that a new compiler might break your code in the future.

For example: pragma solidity ^0.4.0; (The latest version of Solidity is 0.4.0).

The meaning of the keyword pragma is that, in general, pragmas (compile instructions) are instructions that tell the compiler how to process source code (e.g., pragma once).

What a contract means in Solidity is a set of code (its functions) and data (its state) at a specific address on the Ethereum blockchain.

The contract does not accomplish much: it allows anyone to store a single number in the contract, and that number can be accessed by anyone in the world, and there is no viable way to stop you publishing that number. Of course, anyone can call set again, passing in a different value and overwriting your number, but that number will still be stored in the blockchain’s history.

Solidity statements start with a semicolon (;) At the end

State variables

State variables are permanently stored in the contract. That is, they are written to the Ethereum blockchain, imagine writing to a database.

contract HelloWorld {
   // The unsigned integer will be permanently stored in the blockchain
   uint myUnsignedInteger = 100;
}
Copy the code

In the example above, define myUnsignedInteger as uint and assign 100.

Uint Unsigned data type, meaning that its value cannot be negative. There is a data type named int for signed integers.

In Solidity, uint is actually a uint256 pronoun, a 256-bit unsigned integer.

Programs sometimes need to operate on different types of data because Solidity is a statically typed language and running on different types of data will throw exceptions such as:

uint8 a = 5;
uint b = 6;
// An error will be thrown because a * b returns uint instead of uint8:
uint8 c = a * b;
Copy the code

The a * b return type is uint, but there is a potential error when we try to receive it with the Uint8 type. In this case, an explicit cast is required:

// We need to convert b to uint8:
uint8 c = a * uint8(b);
Copy the code

Convert its data type to uint8 and the compiler will not fail.

Solidity supports multiple data types, such as:

  • String (string) : A string is used to hold utF-8 encoded data of any length
  • FixedArray: Arrays of fixed length
  • DynamicArray: An array of variable length to which elements can be added dynamically
  • Enum (enum)
  • mapping
  • Etc.

Mathematical operations

In Solidity, the math is straightforward, the same as in other programming languages:

  • Add:x + y
  • Subtraction:x - y.
  • Method:x * y
  • Division:x / y
  • Mod/mod:x % y (For example, 13%5 has a remainder of 3, because 13 divided by 5 has a remainder of 3)
  • Power:x ** y

The structure of the body

Solidity provides constructs for representing more complex data types.

struct Person {
  uint age;
  string name;
}
Copy the code

Structs allow you to generate a more complex data type with multiple attributes.

Create a structure as follows:

// Create a new Person:
Person satoshi = Person(172."Satoshi");
Copy the code

An array of

Solidity provides two types of arrays: static and dynamic.

// Static array of fixed length 2:
uint[2] fixedArray;
// Static array of fixed length 5 string:
string[5] stringArray;
// Dynamic array, the length is not fixed, can dynamically add elements:
uint[] dynamicArray;
Copy the code

Add values to the array using the push function:

fixedArray.push[123] 
fixedArray.push[234]
// fixedArray values are [123, 234]
Copy the code

Array.push () adds new elements to the end of the array, so the order in which elements are added in the array is the order in which they were added. Array.push () returns the length of the array.

The Solidity array supports several types, such as structs:

struct Person {
  uint age;
  string name;
}

Person[] people; // dynamic Array, we can keep adding to it
Copy the code

Arrays of struct type can be added as follows:

people.push(Person(16."Vitalik"));
// You can also use the following method. The simple one-line method is recommended

Person satoshi = Person(172."Satoshi");
people.push(satoshi);
Copy the code

Public array

You can also define public arrays using public and Solidity will automatically create getter methods. The syntax is as follows:

struct Person {
  uint age;
  string name;
}

Person[] public people; // dynamic Array, we can keep adding to it
Copy the code

Public arrays allow other contracts to read (but not write) data, so this is a useful schema for holding public data in contracts. (Sort of like global variables, all contracts share the same “memory space.” Cool!)

function

In Solidity, the functions are defined as follows:

function eatHamburgers(string _name, uint _amount) {}Copy the code

Solidity It is customary (but not mandatory) for variables in Solidity functions to start with (_) to distinguish between global variables.

This is a function called eatHamburgers that takes two arguments: a string and a uint. Now the inside of the function is empty.

The function call is as follows:

eatHamburgers("vitalik".100);
Copy the code

Private/public functions

Solidity functions are divided into private and common functions.

Properties of Solidity defined functions are public by default. This means that any party (or other contract) can call your contract’s functions.

Obviously, this is not always needed, and such contracts are vulnerable. So it’s a good programming practice to make your function private, and only make it public if you need the outside world to call it.

You can get around this problem by explicitly declaring all functions public and private.

To define a private function, you simply add the private keyword to the function argument. The following is an example:

uint[] numbers;

function _addToArray(uint _number) private {
  numbers.push(_number);
}
Copy the code

This means that only other functions in our contract can call this function to add new members to the numbers array.

Like function arguments, private function names start with (_).

Note: Everything you use in a smart contract is publicly visible, even local variables and state variables marked private.

The return value

Like in other languages, the Solidity function has a return value as shown in the following example:

string greeting = "What's up dog";

function sayHello() public returns (string) {
  return greeting;
}
Copy the code

Return values are annotated with the RETURNS keyword. (This is already a very strange way to write it.)

The modifier

view

Constant is an alias for view

string greeting = "What's up dog";

function sayHello() public returns (string) {
  return greeting;
}
Copy the code

In cases where the sayHello function does not actually change the contents of the data in the contract, the function can be defined as view, which means that the function is read-only and does not modify the data. The following declarations can be used:

function sayHello() public view returns (string) {}
Copy the code

You can declare a function to be of type View, in which case you must ensure that the state is not changed.

The following statement is considered to be in modified state:

  1. Modify state variables.
  2. Generates an event.
  3. Create additional contracts.
  4. useselfdestruct.
  5. Send ether through a call.
  6. Calls anything not marked asvieworpureThe function.
  7. Use low-level calls.
  8. Use an inline assembly that contains a specific opcode.
pure

Pure is lighter than View, and functions decorated with this modifier do not even read the data in the contract, for example:

function _multiply(uint a, uint b) private pure returns (uint) { return a * b; }
Copy the code

This function does not read the state of the application; its return value depends only on the parameters it entered.

The Solidity editor will give you a prompt to remind you to use the pure/ View modifier.

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

In addition to the list of state modification statements explained above, the following are considered to be read from the state:

  1. Read state variables.
  2. accessthis.balanceor<address>.balance.
  3. accessblock.tx.msgAny member of themsg.sigmsg.dataOutside).
  4. Calls any unmarked aspureThe function.
  5. Use an inline assembly that contains some opcodes.
payable

The ‘payable’ keyword is used to say that the function can accept Ether, and without it the function will automatically reject all ether sent to it.

The event

Events are a mechanism by which contracts and blockchain communicate. Your front-end application “listens” for certain events and reacts to them. Such as:

// Set up the event here
event IntegersAdded(uint x, uint y, uint result);

function add(uint _x, uint _y) public {
  uint result = _x + _y;
  // Trigger an event to notify app
  IntegersAdded(_x, _y, result);
  return result;
}
Copy the code

The user interface (and of course the server application) can listen for events being sent on the blockchain without much cost. Once it is emitted, listeners listening for the event are notified. All events contain from, to, and amount parameters, making it easy to track transactions. To listen for this event, you can use the following code (implemented in javascript) :

var abi = The abi is produced by the compiler */;
var ClientReceipt = web3.eth.contract(abi);
var clientReceipt = ClientReceipt.at("0x1234... ab67" / * * / address);

var event = clientReceipt.IntegersAdded();

// Monitor changes
event.watch(function(error, result){
    // The result includes various information including the call parameters to 'Deposit'.
    if(! error)console.log(result);
});

// Or start observing immediately with a callback
var event = clientReceipt.IntegersAdded(function(error, result) {
    if(! error)console.log(result);
});
Copy the code

Code sample

Here is a complete code example:

pragma solidity ^0.419.;

contract ZombieFactory {

    // Create the event
    event NewZombie(uint zombieId, string name, uint dna);

    uint dnaDigits = 16;  // Define state variables
    uint dnaModulus = 10 ** dnaDigits;

    struct Zombie {  // Define the structure
        string name;
        uint dna;
    }

    Zombie[] public zombies;  // Define a dynamic array

    // Create a private function named with the _ prefix
    function _createZombie(string _name, uint _dna) private {
        // Function parameter names are prefixed with _
        // arrays.push() adds elements to the end of the array and returns the array length
        uint id = zombies.push(Zombie(_name, _dna)) - 1;
        // Trigger the event
        NewZombie(id, _name, _dna);
    }

    // View is a function modifier, indicating that the function does not need to update or create state variables
    // pure means that the function does not need to use state variables
    function _generateRandomDna(string _str) private view returns (uint) {
        // Create a pseudorandom number using keccak256
        uint rand = uint(keccak256(_str));
        return rand % dnaModulus;
    }

    function createRandomZombie(string _name) public { uint randDna = _generateRandomDna(_name); _createZombie(_name, randDna); }}Copy the code

Ethereum has an internal hash function, keccAK256, that uses the SHA3 version. A hash function basically converts a string to a 256-bit hexadecimal number. It is difficult to use random numbers in smart contracts to prevent nodes from cheating. This is because random numbers in smart contracts generally depend on the local time of the compute node, and the local time can be forged by malicious nodes. Therefore, this method is not secure. The common practice is to use off-chain third-party services such as Oraclize to obtain random numbers.

Refer to the link

  • Solidity document: https://solidity-cn.readthedocs.io/zh/develop/index.html
  • cryptozombie-lessons: https://cryptozombies.io/zh/

Finally, thanks to the girlfriend support and tolerance, than ❤️

Around the male can also enter the keywords for historical article: male number & small program | | concurrent design mode & coroutines