抱歉,您的瀏覽器無法訪問本站
本頁面需要瀏覽器支持(啟用)JavaScript
了解詳情 >

开始ETH的学习之路把,炒币也要了解下相关原理 ( ̄▽ ̄)”

a7fa01ae-8433-470e-b7e8-ac77c90a7e21

名词学习

EVM:指以太坊虚拟机,以太坊的运行环境,智能合约真正执行代码的地方,EVM的存在是为了“让全网节点按同样规则执行智能合约”。

节点:指参与以太坊网络的一台机器,区块链网络里的参与者,通常负责保存区块链数据、验证区块和交易、执行合约代码、提供RPC接口。

区块:指一批交易和相关信息打包后的数据块,区块链账本里的一页,通常会有多笔交易,上一个区块的信息,时间相关信息,区块元数据。

外部账户 EOA:即Externally Owned Account 外部账户,人控制的钱包账户,我们使用MetaMask,OKX Wallet等创建的就是EOA。

合约账户:即部署在链上的智能合约地址,没有私钥,不能主动发起交易,代码控制的账户。

Gas:在以太坊执行操作所消耗的计算量单位,比如普通ETH转账,要消耗一定的Gas,调用合约函数要消耗更多的Gas。

Gas Limit:这笔交易最多愿意消耗多少Gas,可以理解为预算上限,当Gas Limit 太低导致执行中途消耗完了,会交易失败状态回滚已消耗的Gas不退还

Gas Price:Gas Used * Gas 单价

Base Fee:EIP-1559后的概念,即网络规定的基础手续费单价

Priority Fee:给验证者的小费

wei和gwei:1 ETH = 10^18 wei,1 gwei = 10^9 wei,1 gwei = 0.000000001 ETH1 ETH = 1,000,000,000 gwei

Gas消耗举个例子:

普通转账消耗 Gas Used = 2100

假设 Base Fee = 20 gwei, Priority Fee = 2 gwei

那么实际单价就是 22gwei,总费用就是 21000 * 22gwei

签名:即证明这笔交易确实是这个账户持有人授权发出的,因为EOA有私钥,所以可以对交易数据做数字签名,从而证明 发起人有这个地址对应的私钥(持有钱包)。

Nonce:账户发出的交易序号,通常表示账户已经发送过多少笔交易,作用是防止重放,保证顺序。

交易回执:交易执行完后,链上返回的“结果单据”,包括交易哈希,所在区块,是否成功,消耗Gas等

Solidity相关语法

由于已经是一名程序猿了,所以简单的语法不需要记录了,来了解下Solidity核心语法主干就行了

合约结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24; // 声明编译器版本约束。

contract SimpleStorage { // 一个部署在链上的程序单元,里面有状态变量和函数
uint256 private storedData; // 状态变量,存储在链上数据

function set(uint256 x) public {
storedData = x;
}

function get() public view returns (uint256) {
return storedData;
}
}

常用数据类型

  • uint/uint256:无符号整数,最常用,uint其实就是uint256,不过平常会显性写成uint256
  • int/int256:有符号整数,可正可负
  • bool:布尔值
  • address:地址类型,外部账户或者合约地址
  • string:字符串
  • bytes:动态字节数组 1
  • bytes32:固定32字节,常用于哈希值,标识 1

常量与不可变变量

  • constant:编译期常量,部署后永远不变,更省gas

    1
    uint256 public constant MAX_SUPPLY = 1000000;
  • immutable:部署时确认,之后不变,运行时第一次赋值,后面不在修改

    1
    2
    3
    4
    5
    address public immutable owner;

    constructor() {
    owner = msg.sender;
    }

函数

函数结构拆开来看如下:

  • function:函数关键字
  • set:函数名
  • (uint256 x):参数
  • public:可见性
  • { ... }:函数体
  • returns: 返回值
  • returns (uint256, bool) 多返回值
  • returns (uint256 value, bool ok) 命名返回值
  • pure 既不读状态,也不改状态。
  • view 只读,不改状态
  • payable:代表函数或者地址可以接受ETH
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
function set(uint256 x) public {
storedData = x;
}

function get() public view returns (uint256) {
return storedData;
}

function getPair() public pure returns (uint256, bool) {
return (100, true);
}

function getInfo() public pure returns (uint256 value, bool ok) {
value = 1;
ok = true;
}

function get() public view returns (uint256) {
return count;
}

function deposit() public payable {
}

可见性

public

内外都可以调用,无论是外部账户调用还是合约内部调用

1
function foo() public {}
external

只能从外部调用更合适,常用于对外接口,内部合约也可以调用,只是要this.xxx一下

1
function bar(uint256 x) external {}
internal

只能合约内部和子合约才能调用

1
function _calc() internal {}
private

只能当前合约内部调用,子合约也不行

1
function _secret() private {}

数据位置

这个算是Solidity最关键的语法了,因为涉及钱

Storage

链上持久化存储,永久保存到链上,最贵

1
uint256 public value;
Memory

临时内存,只在函数执行期间存在。临时,函数执行完后消失,比storage便宜

1
2
3
4
function foo() public pure returns (string memory) {
string memory s = "hello";
return s;
}
calldata

外部函数参数只读区。只读、常用于external函数参数,更省gas

错误处理

require

条件不满足就回滚,用于输入检查和权限检查

1
require(msg.sender == owner, "not owner");
revert

手动版require,不满足条件手动回滚

1
2
3
if (amount > balance) {
revert("insufficient balance");
}

自定义错误error,结构化、更清晰、更省gas

1
2
3
4
5
6
7
error InsufficientBalance(uint256 requested, uint256 available);

function withdraw(uint256 amount) public {
if (amount > balance[msg.sender]) {
revert InsufficientBalance(amount, balance[msg.sender]);
}
}

事件

事件是链上和链下交互的重要桥梁,给前端监听、给后端索引、给区块浏览器展示、给外部系统感知链上变化

1
2
3
4
5
event Transfer(address from, address to, uint256 amount); // 定义事件

emit Transfer(msg.sender, to, amount); // 触发事件

event Transfer(address indexed from, address indexed to, uint256 amount); // 通常会给indexed添加检索关键字

复杂数据结构

mapping

就是键值对,按key存值,常用于余额、权限、白名单等,注意不能遍历,如果key不存在返回默认值

1
mapping(address => uint256) public balances;
array

就是数组,分为动态数组和固定长度数组

1
2
3
4
5
uint256[3] public nums; // 固定长度为3的uint256数组
uint256[] public items; // 动态数组

items.push(10); // 追加元素
items.length; // 查看长度
struct

自定义复合结构体,做对象

1
2
3
4
5
6
7
struct User {
uint256 id;
string name;
bool active;
}

User public user;
enum

有限状态枚举,基本用于状态机这种

1
2
enum Status { Pending, Active, Closed }
Status public status;

构造函数,modifier,继承

constructor

部署时只会执行一次,通常用于初始化合约owner,参数,配置等

1
2
3
constructor() {
owner = msg.sender;
}
modifier

modifier可以理解成AOP切面的语法,就是用来通用前置校验,基本用于权限检查

_就是被修饰函数的函数体

1
2
3
4
5
6
7
8
modifier onlyOwner() {
require(msg.sender == owner, "not owner");
_;
}

function set(uint256 x) public onlyOwner {
value = x;
}
继承 is

就是代码复用,逻辑扩展,没啥特殊

1
2
3
4
5
6
7
contract Ownable {
address public owner;
}

contract MyContract is Ownable {
...
}

全局变量和特殊单位

msg.sender:当前调用者地址

msg.value:本次调用附带的ETH数量

block.timestamp:当前区块时间戳

wei、gwei、ether:ETH不同单位

特殊函数

receive

当有ETH向这个合约转账时会触发该函数

1
receive() external payable {}
fallback

当执行了该合约不存在的函数时会被调用

1
fallback() external payable {}
转账
1
2
(bool success, ) = payable(to).call{value: amount}("");
require(success, "transfer failed");