# Solidity零基础速学 **Published by:** [Benson](https://paragraph.com/@bensonxu/) **Published on:** 2023-08-27 **URL:** https://paragraph.com/@bensonxu/solidity ## Content 配套视频教程 https://www.youtube.com/@benson8836/featured1.Hello World// SPDX-License-Identifier: MIT // compiler version must be greater than or equal to 0.8.10 and less than 0.9.0 pragma solidity ^0.8.10; contract HelloWorld { string public greet = "Hello World!"; } 2.类型和值// SPDX-License-Identifier: MIT pragma solidity ^0.8.10; contract Primitives { bool public boo = true; /* uint stands for unsigned integer, meaning non negative integers different sizes are available uint8 ranges from 0 to 2 ** 8 - 1 uint16 ranges from 0 to 2 ** 16 - 1 ... uint256 ranges from 0 to 2 ** 256 - 1 */ uint8 public u8 = 1; uint public u256 = 456; uint public u = 123; // uint is an alias for uint256 /* Negative numbers are allowed for int types. Like uint, different ranges are available from int8 to int256 int256 ranges from -2 ** 255 to 2 ** 255 - 1 int128 ranges from -2 ** 127 to 2 ** 127 - 1 */ int8 public i8 = -1; int public i256 = 456; int public i = -123; // int is same as int256 // minimum and maximum of int int public minInt = type(int).min; int public maxInt = type(int).max; address public addr = 0xCA35b7d915458EF540aDe6068dFe2F44E8fa733c; /* In Solidity, the data type byte represent a sequence of bytes. Solidity presents two type of bytes types : - fixed-sized byte arrays - dynamically-sized byte arrays. The term bytes in Solidity represents a dynamic array of bytes. It’s a shorthand for byte[] . */ bytes1 a = 0xb5; // [10110101] bytes1 b = 0x56; // [01010110] // Default values // Unassigned variables have a default value bool public defaultBoo; // false uint public defaultUint; // 0 int public defaultInt; // 0 address public defaultAddr; // 0x0000000000000000000000000000000000000000 } 3.函数// SPDX-License-Identifier: MIT pragma solidity ^0.8.21; contract Function { function add(uint x, uint y) external pure returns (uint) { return x + y; } function sub(uint x, uint y) external pure returns (uint) { return x - y; } } 4.状态变量// SPDX-License-Identifier: MIT pragma solidity ^0.8.21; //function <function name>(<parameter types>) {internal|external|public|private} [pure|view|payable] [returns (<return types>)] contract StateVariables { uint public myUint = 123; function foo() external pure returns(int) { int s = 321; return s; } } 5.局部变量// SPDX-License-Identifier: MIT pragma solidity ^0.8.21; //function <function name>(<parameter types>) {internal|external|public|private} [pure|view|payable] [returns (<return types>)] contract StateVariables { uint public i; bool public b; address public myAddress; function foo() external { uint x = 123; bool f = false; x +=456; f= true; i = 321; b = true; myAddress = address(1); } } 6.全局变量contract GlobalVariables { function globalVars() external view returns (address, uint, uint) { address sender = msg.sender; uint timestamp = block.timestamp; uint blockNum = block.number; return (sender,timestamp,blockNum); } } 7.只读函数// SPDX-License-Identifier: MIT pragma solidity ^0.8.21; contract ViewAndPureFunction { uint public num; function viewFunc() external view returns (uint) { return num; } function pureFunc() external pure returns (uint) { return 1; } function addToNum(uint x) external view returns (uint) { return num + x; } function add(uint x, uint y) external pure returns (uint) { return x + y; } } 8.计数器合约// SPDX-License-Identifier: MIT pragma solidity ^0.8.21; contract Counter { uint public count; function inc() external { count += 1; } function dec() external { count -= 1; } } 9.默认值// SPDX-License-Identifier: MIT pragma solidity ^0.8.21; contract DefaultValues { bool public b; // false uint public u; // 0 int public i; // 0 address public a; // 0x0000000000000000000000000000000000000000 bytes32 public b32; // 0x0000000000000000000000000000000000000000000000000000000000000000 } 10.常量// SPDX-License-Identifier: MIT pragma solidity ^0.8.21; contract Constants { address public constant MY_ADDRESS = 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4; uint public constant MY_UINT = 123; } contract Var { address public MY_ADDRESS = 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4; } 11.结构控制// SPDX-License-Identifier: MIT pragma solidity ^0.8.21; contract IfElse { function example(uint _x) external pure returns (uint) { if (_x < 10) { return 1; } else if (_x < 20) { return 2; } else { return 3; } } function ternary(uint _x) external pure returns (uint) { // if (_x < 10) { // return 1; // } // return 2; return _x < 10 ? 1 : 2; } } 12.循环// SPDX-License-Identifier: MIT pragma solidity ^0.8.21; contract ForAndWhileLoops { function loops() external pure { for (uint i = 0; i< 10; i++) { // code if (i == 3) { continue; } // more code if (i == 5) { break; } } uint j = 0; while (j < 10) { // code j++; } } function sum(uint _n) external pure returns (uint) { uint s; for (uint i = 1; i <= _n; i++) { s += i; } return s; } } 13.报错控制// SPDX-License-Identifier: MIT pragma solidity ^0.8.21; contract testError { function testRequire(uint _i) public pure { require(_i <= 10, "i > 10"); // code } function testRevert(uint _i) public pure { if (_i > 10) { revert("i > 10"); } } uint public num = 123; function testAssert() public view { assert(num == 123); } function foo(uint _i) public { num += 1; require(_i < 10); } function testCustomError(uint _i) public pure { require(_i <= 10, "error msg xxxxxxxxxxxxxxxxxxxxxx"); // code } error MyError(address caller, uint i); function testCustomSetError(uint _i) public view { if (_i > 10) { revert MyError(msg.sender, _i); } } } 14.函数修改器// SPDX-License-Identifier: MIT pragma solidity ^0.8.21; // basic input sandwich // 原版本 contract FunctionModifier { bool public paused; uint public count; function setPause(bool _paused) external { paused = _paused; } function inc() external { require(!paused, "paused"); count += 1; } function dec() external { require(!paused, "paused"); count -= 1; } } // 使用修改器后 contract FunctionModifier { bool public paused; uint public count; function setPause(bool _paused) external { paused = _paused; } modifier whenNotPaused() { require(!paused, "paused"); _; } function inc() external whenNotPaused { count += 1; } function dec() external whenNotPaused{ count -= 1; } } // 带参数修改器 contract FunctionModifier { bool public paused; uint public count; function setPause(bool _paused) external { paused = _paused; } modifier cap(uint _x) { require(_x < 100, "x > 100"); _; } function incBy(uint _x) external whenNotPaused cap(_x) { count += _x } } //三明治 contract FunctionModifier { bool public paused; uint public count; function setPause(bool _paused) external { paused = _paused; } modifier sandwitch() { // code count += 10; _; count *= 2; } function foo() external sandwitch{ count += 1; } } 15.构造函数// SPDX-License-Identifier: MIT pragma solidity ^0.8.21; contract Constructor { address public owner; uint public x; constructor(uint _x) { owner = msg.sender; x = _x; } } 16.Ownable// SPDX-License-Identifier: MIT pragma solidity ^0.8.21; contract Ownable { address public owner; constructor() { owner = msg.sender; } modifier onlyOwner() { require(msg.sender == owner, "not owner"); _; } function setOwner(address _newOwner) external onlyOwner { require(_newOwner != address(0), "invalid sender"); owner = _newOwner; } function onlyOwnerCanCallThisFunc() external onlyOwner { // code } function anyOneCanCall() external { // code } } 17.函数返回值// SPDX-License-Identifier: MIT pragma solidity ^0.8.21; contract FunctionOutputs { function returnMany() public pure returns (uint, bool) { return (1, true); } function named() public pure returns (uint x, bool b) { return (1, true); } function assigned() public pure returns (uint x, bool b) { x = 1; b = true; } function destructingAssigments() public pure returns { (uint x, bool b) = returnMany(); (, bool b) = returnMany(); } } 18.数组// SPDX-License-Identifier: MIT pragma solidity ^0.8.21; contract Array { uint[] public nums = [1, 2, 3]; uint[3] public numsFixed = [4, 5, 6]; function examples() external { nums.push(4); // [1,2,3,4] uint x = nums[1]; nums[2] = 777; // [1,2,777,4] delete nums[1]; // [1,0,777,4] nums.pop; // [1,0,777] uint len = nums.length; // create in memory 内存中只能创建定长数组,不能改变长度 uint[] memory a = new uintUnsupported embed; a[1] = 123; } function returnArray() external view returns (uint[] memory) { return nums; } } contract Array2 { // 通过元素移动位置删除数组元素(gas高,但顺序不乱) uint[] public arr; // [1,2,3] -remove(1)->[1,3,3]->[1,3] // [1,2,3,4,5,6] -removed(2)->[1,2,4,5,6,6]->[1,2,4,5,6] function remove(uint _index) public { require(_index < arr.length, "index out of bound"); for (uint i = _index; i < arr.length - 1; i++) { arr[i] = arr[i + 1]; } arr.pop(); } function test() external { arr = [1, 2, 3, 4, 5]; remove(2); assert(arr[0] == 1); assert(arr[1] == 2); assert(arr[2] == 4); assert(arr[3] == 5); assert(arr.length == 4); arr = [1]; remove(0); // [] assert(arr.length == 0); } } contract Array3 { uint[] public arr; // 通过元素替换删除数组元素 (gas低,但顺序打乱) // 【1,2,3,4】-remove2(1) -> 【1,4,3,4】 ->[1,4,3] function remove(uint _index) public { arr[_index] = arr[arr.length - 1]; arr.pop(); } function test2() external { arr = [1, 2, 3, 4]; remove(1); // [1, 4, 3] assert(arr.length == 3); assert(arr[0] == 1); assert(arr[1] == 4); assert(arr[2] == 3); } } 19.映射// SPDX-License-Identifier: MIT pragma solidity ^0.8.21; contract Mapping { mapping(address => uint) public balances; mapping(address => mapping(address => bool)) public isFriend; function examples() external { balances[msg.sender] = 123; uint bal = balances[msg.sender]; uint bal2 = balances[address(1)]; // 0 balances[msg.sender] += 456; delete balances[msg.sender]; isFriend[msg.sender][address(this)] = true; } } // 结合遍历和映射 contract IterableMapping { mapping(address => uint) public balances; mapping(address => bool) public inserted; // 地址是否存在 address[] public keys; function set(address _key, uint _val) external { balances[_key] = _val; if (!inserted[_key]) { inserted[_key] = true; keys.push(_key); } } function getSize() external view returns (uint) { return keys.length; } function first() external view returns (uint) { return balances[keys[0]]; } function last() external view returns (uint) { return balances[keys[keys.length - 1]]; } function get(uint _i) external view returns (uint) { return balances[keys[_i]]; } } 20.结构体// SPDX-License-Identifier: MIT pragma solidity ^0.8.21; contract Structs { struct Car { string model; uint year; address owner; } Car public car; Car[] public cars; mapping(address => Car[]) public carsByOwner; function examples() external { Car memory toyota = Car("Toyota", 1990, msg.sender); Car memory lambo = Car({model:"Lamborghini", year:1980, owner: msg.sender}); Car memory tesla; tesla.model = "Tesla"; tesla.year = 2010; tesla.owner = msg.sender; cars.push(toyota); cars.push(lambo); cars.push(tesla); cars.push(Car("Ferrari", 2020, msg.sender)); //取读 Car memory _car = cars[0]; _car.model; //连带状态变量修改(带指针) Car storage _car2 = cars[0]; _car2.year = 1999; delete _car2.owner; delete cars[1]; } } 21.枚举// SPDX-License-Identifier: MIT pragma solidity ^0.8.21; contract Enum { enum Status { None, // 默认 Pending, Shipped, Completed, Rejected, Canceled } Status public status; struct Order { address buyer; Status status; } Order[] public orders; //获取 function get() view external returns (Status) { return status; } //修改 通过索引 function set(Status _status) external { status = _status; } //修改 通过值 function ship() external { status = Status.Shipped; } //重置 function reset() external { delete status; } } 22.存储位置// SPDX-License-Identifier: MIT pragma solidity ^0.8.21; // storage memory calldata contract DataLocations { struct MyStruct { uint foo; string text; } mapping(address => MyStruct) public myStructs; function examples() external { myStructs[msg.sender] = MyStruct({foo: 123, text: "bar"}); MyStruct storage myStruct = myStructs[msg.sender]; myStruct.text = "foo";//存储:全局变量myStructs也被改变 MyStruct memory myStructReadOnly = myStructs[msg.sender]; myStruct.text = "xxx";//内存:局部变量myStructs不会改变 } //calldata function examples(uint[] memory y, string memory s) external return (uint[] memory){ myStructs[msg.sender] = MyStruct({foo: 123, text: "bar"}); MyStruct storage myStruct = myStructs[msg.sender]; myStruct.text = "foo";//全局变量myStructs也被改变 MyStruct memory myStructReadOnly = myStructs[msg.sender]; myStruct.text = "xxx";//全局变量myStructs不会改变 uint[] memory memArr = new uintUnsupported embed; memArr[0] = 234; return memArr } //calldata 只能用在参数中,更节省gas function examples(uint[] calldata y, string calldata s) external return (uint[] memory){ myStructs[msg.sender] = MyStruct({foo: 123, text: "bar"}); MyStruct storage myStruct = myStructs[msg.sender]; myStruct.text = "foo";//全局变量myStructs也被改变 MyStruct memory myStructReadOnly = myStructs[msg.sender]; myStruct.text = "xxx";//全局变量myStructs不会改变 _internal(y); uint[] memory memArr = new uintpUnsupported embed; memArr[0] = 234; return memArr; function _internal(uint[] calldata y) private { uint x = y[0]; } } } 23.事件// SPDX-License-Identifier: MIT pragma solidity ^0.8.21; contract Event { event Log(string message, uint val); event IndexLog(address indexed sender, uint val); // 最多三个索引 function example() external { emit Log("foo", 1234); //写入方法 emit IndexLog(msg.sender, 789); } event Message(address indexed _from, address index _to, string message); function sendMessage(address _to, string calldata message) external { emit Message(msg.sender, _to, message); } } 24.继承// SPDX-License-Identifier: MIT pragma solidity ^0.8.21; contract A{ function foo() public pure virtual returns (string memory) { return "A"; } function bar() public pure virtual returns (string memory) { return "A"; } // more code } contract B is A { function foo() public pure override returns (string memory) { return "B"; } function bar() public pure virtual override returns (string memory) { return "B"; } // more code } contract C is B { function bar() public pure override returns (string memory) { return "C"; } } 25.多线继承// SPDX-License-Identifier: MIT pragma solidity ^0.8.21; /* 从最基础到最派生,从前到后 X / | Y | \ | Z // X-Y-Z X / \ Y A | | | B \ / Z // X-Y-A-B-Z */ contract X { function foo() public pure virtual returns (string memory) { return "X"; } function bar() public pure virtual returns (string memory) { return "X"; } function x() public pure returns (string memory) { return "X"; } } contract Y is X { function foo() public pure virtual override returns (string memory) { return "Y"; } function bar() public pure virtual override returns (string memory) { return "Y"; } function y() public pure returns (string memory) { return "Y"; } } contract Z is X, Y { function foo() public pure override(X, Y) returns (string memory) { return "Z"; } function bar() public pure override(X, Y) returns (string memory) { return "Z"; } } 26.父级合约构造函数及函数调用// SPDX-License-Identifier: MIT pragma solidity ^0.8.21; contract S { string public name; constructor(string memory _name) { name = _name; } } contract T { string public text; constructor(string memory _text) { text = _text; } } // 知道需要什么初始参数的情况下 contract U is S("s"), T("t") { } // 不知道初始参数需要开始的时候输入 contract V is S, T { constructor(string memory _name, string memory _text) S(_name) T(_text) { } } // 混合的情况 contract VV is S("s"), T { constructor(string memory _text) T(_text) { } } // 初始化的顺序是根据继承顺序 // S-T-V0 contract V0 is S, T { constructor(string memory _name, string memory _text) S(_name) T(_text) { } } // S-T-V1 contract V1 is S, T { constructor(string memory _name, string memory _text) T(_text) S(_name) { } } // T-S-V2 contract V2 is T, S { constructor(string memory _name, string memory _text) T(_text) S(_name) { } } //调用父级 contract E { event Log(string message); function foo() public virtual { emit Log("E.foo"); } function bar() public virtual { emit Log("E.bar"); } } contract F is E { function foo() public virtual override { emit Log("F.foo"); E.foo(); } function bar() public virtual override { emit Log("F.bar"); super.bar(); } } contract G is E { function foo() public virtual override { emit Log("G.foo"); E.foo(); } function bar() public virtual override { emit Log("G.bar"); super.bar(); } } contract H is F, G { function foo() public override(F, G) { F.foo; } function bar() public override(F, G) { super.bar(); } } ## Publication Information - [Benson](https://paragraph.com/@bensonxu/): Publication homepage - [All Posts](https://paragraph.com/@bensonxu/): More posts from this publication - [RSS Feed](https://api.paragraph.com/blogs/rss/@bensonxu): Subscribe to updates - [Twitter](https://twitter.com/benson_btc): Follow on Twitter