配套视频教程
// 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!";
}
// 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
}
// 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;
}
}
// 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;
}
}
// 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);
}
}
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);
}
}
// 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;
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.21;
contract Counter {
uint public count;
function inc() external {
count += 1;
}
function dec() external {
count -= 1;
}
}
// 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
}
// 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;
}
// 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;
}
}
// 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;
}
}
// 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);
}
}
}
// 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;
}
}
// 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;
}
}
// 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
}
}
// 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();
}
}
// 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 uint[](5);
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);
}
}
// 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]];
}
}
// 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];
}
}
// 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;
}
}
// 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 uint[](3);
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 uintp[](3);
memArr[0] = 234;
return memArr;
function _internal(uint[] calldata y) private {
uint x = y[0];
}
}
}
// 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);
}
}
// 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";
}
}
// 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";
}
}
// 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();
}
}