Solidity 智能开发知识点记录

Solidity 智能开发知识点记录

    • [1. 特性](#1. 特性)
    • [2. ==存储区域==](#2. ==存储区域==)
    • [3. 事件(Event)](#3. 事件(Event))
  • ABI

1. 特性

Solidity 的核心特性包括:

  • 面向合约 :以 contract 为基本单位,合约类似面向对象语言中的类,包含状态变量、函数、事件等。
  • 静态类型:变量类型在编译时确定,且不可动态改变。
  • 继承与多态 :支持多重继承,使用 is 关键字,并允许子合约重写父合约函数。
  • EVM 原生兼容:编译后生成以太坊虚拟机字节码,可直接部署在以太坊及兼容链上。
  • 错误处理 :提供 requireassertrevert 等断言式错误抛出机制。
  • 内置区块链信息 :可访问 block.numbermsg.sendertx.gasprice 等环境变量。
  • Gas 感知 :通过 viewpure 等修饰符标明函数消耗 Gas 的情况。

2. 存储区域

Solidity 中的数据有明确的存储位置,主要分为四类:

区域 关键字 生命周期 适用场景 特点
Storage storage 永久(合约状态) 状态变量(默认) 写入需消耗 Gas,数据存储在链上
Memory memory 临时(函数调用) 函数内临时变量、函数参数(某些类型)、动态数组拷贝 读写成本低于 Storage,调用结束释放
Calldata calldata 临时(仅外部调用) 外部函数的参数(不可修改) 只读,不占用 Memory 拷贝,节省 Gas
Stack 无关键字 短暂(表达式内) 局部基本类型(如 uintbool),存放指令操作数 深度限制 1024 个元素

重要规则

  • 状态变量(合约内声明的变量)默认storage
  • 函数局部变量的存储位置需要显式指定(结构体、数组、映射等复杂类型)。
  • 赋值时注意引用传递:storage 赋值给 storage 会传递引用;memory 赋值给 storage 会拷贝。
solidity 复制代码
contract Example {
    uint[] public arr; // storage

    function test(uint[] calldata source) external {
        uint[] memory tmp = new uint[](10); // memory
        arr = tmp;      // 从 memory 拷贝到 storage
        arr = source;   // 从 calldata 拷贝到 storage
    }
}

常见数据类型:uintintbooladdressbytesstringmapping、数组、结构体、enum


3. 事件(Event)

事件是 Solidity 中日志 的抽象,用于和链外应用通信。

核心作用

  • 智能合约返回数据给前端/后端监听者。
  • 比普通返回值更 Gas 高效(日志存储在交易收据中,合约无法访问)。
  • 可以带索引参数(indexed),方便链外按条件快速检索。

语法

solidity 复制代码
event EventName(
    type indexed param1,
    type param2
);
  • 事件日志由两部分组成:主题(topics)和数据(data)
    • 第一个参数:事件签名的哈希值。
    • 第二个参数:自定义 indexed 参数
    • 第三个参数:自定义 indexed 参数
    • 第四个参数:自定义 indexed 参数
  • indexed 参数最多 3 个,会被日志的 topic 区域存储,可用于过滤。
  • 非索引参数(data 区域)原样存储,无法直接检索
  • 合约执行每触发一次事件,在交易回执里的 logs 数据项数组里就会多一条日志条目
java 复制代码
{
    "jsonrpc": "2.0",
    "id": 1,
    "result": {
        "blockHash": "0x6a0e591eb3c266bd1d499f17caea929dc3a1b396b6e08d3d12b1df7abb4b1daf",
        "blockNumber": "0x12d11ab",
        "contractAddress": null,
        "cumulativeGasUsed": "0x679b6b",
        "effectiveGasPrice": "0x1ff2895dc",
        "from": "0xe4de99fbf078eff6ba02b076e503b304c2a7b1c5",
        "gasUsed": "0xe074",
        "logs": [
            {
                "address": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
                "topics": [
                    "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
                    "0x000000000000000000000000e4de99fbf078eff6ba02b076e503b304c2a7b1c5",
                    "0x0000000000000000000000006177d42837d88b1f6dd0ad14e2f80c17df3d0617"
                ],
                "data": "0x000000000000000000000000000000000000000000000000000000000ee6b280",
                "blockNumber": "0x12d11ab",
                "transactionHash": "0xe26a8add9f159c22d8d10f4b4069ed20ec9245ba07bf742dc2054d6b2561654a",
                "transactionIndex": "0x4b",
                "blockHash": "0x6a0e591eb3c266bd1d499f17caea929dc3a1b396b6e08d3d12b1df7abb4b1daf",
                "logIndex": "0xb2",
                "removed": false
            }
        ],
        "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000800000000000000000008000008000400000000010000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000100000000000000000000000010000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000002000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
        "status": "0x1",
        "to": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
        "transactionHash": "0xe26a8add9f159c22d8d10f4b4069ed20ec9245ba07bf742dc2054d6b2561654a",
        "transactionIndex": "0x4b",
        "type": "0x2"
    }
}

触发事件

solidity 复制代码
emit EventName(param1, param2);

链外监听示例(JavaScript + ethers.js)

javascript 复制代码
contract.on("EventName", (param1, param2, event) => {
    console.log(param1, param2);
});

典型应用场景:代币转账 Transfer 事件、去中心化交易所订单状态变更、治理投票记录等。

ABI

ABI(Application Binary Interface,应用二进制接口)是智能合约与外部世界(前端、其他合约、钱包等)交互的标准化规范。

智能合约在以太坊上以字节码形式存在,人类无法直接理解。ABI 就像是"说明书",告诉外部程序:

  1. 合约有哪些函数
  2. 函数参数和返回值是什么类型
  3. 如何编码调用数据
  4. 如何解码返回结果
solidity 复制代码
// ContractABI.json
[
  {
    "inputs": [{ "internalType": "uint256", "name": "x", "type": "uint256" }],
    "name": "set",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "get",
    "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }],
    "stateMutability": "view",
    "type": "function"
  },
  {
    "anonymous": false,
    "inputs": [
      { "indexed": true, "internalType": "address", "name": "caller", "type": "address" },
      { "indexed": false, "internalType": "uint256", "name": "value", "type": "uint256" }
    ],
    "name": "ValueSet",
    "type": "event"
  }
]

如何调用?

java 复制代码
package com.example;

import org.web3j.abi.FunctionEncoder;
import org.web3j.abi.FunctionReturnDecoder;
import org.web3j.abi.TypeReference;
import org.web3j.abi.datatypes.Address;
import org.web3j.abi.datatypes.Function;
import org.web3j.abi.datatypes.Type;
import org.web3j.abi.datatypes.generated.Uint256;
import org.web3j.crypto.Credentials;
import org.web3j.protocol.Web3j;
import org.web3j.protocol.core.DefaultBlockParameterName;
import org.web3j.protocol.core.methods.request.Transaction;
import org.web3j.protocol.core.methods.response.EthCall;
import org.web3j.protocol.core.methods.response.EthGetLogs;
import org.web3j.protocol.core.methods.response.EthSendTransaction;
import org.web3j.protocol.core.methods.response.Log;
import org.web3j.protocol.core.methods.response.TransactionReceipt;
import org.web3j.protocol.http.HttpService;
import org.web3j.tx.RawTransactionManager;
import org.web3j.tx.gas.DefaultGasProvider;
import org.web3j.tx.gas.StaticGasProvider;

import java.math.BigInteger;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class CallContractWithABI {
    
    private static final String RPC_URL = "https://sepolia.infura.io/v3/YOUR_KEY";
    private static final String CONTRACT_ADDRESS = "0x1234567890abcdef...";
    private static final String PRIVATE_KEY = "YOUR_PRIVATE_KEY";
    
    public static void main(String[] args) throws Exception {
        Web3j web3j = Web3j.build(new HttpService(RPC_URL));
        Credentials credentials = Credentials.create(PRIVATE_KEY);
        
        // 调用只读方法
        callReadMethod(web3j);
        
        // 调用写入方法
        callWriteMethod(web3j, credentials);
        
        // 查询历史事件
        queryEvents(web3j);
        
        // 实时监听事件
        listenEvents(web3j);
        
        web3j.shutdown();
    }
    
    /**
     * 调用只读方法(view/pure)- 不消耗 Gas
     */
    private static void callReadMethod(Web3j web3j) throws Exception {
        System.out.println("=== 调用 get() 方法 ===");
        
        // 1. 创建 Function 对象
        Function function = new Function(
            "get",                           // 函数名
            Collections.emptyList(),         // 参数列表(无参数)
            Arrays.asList(new TypeReference<Uint256>() {})  // 返回值类型
        );
        
        // 2. 编码调用数据
        String encodedFunction = FunctionEncoder.encode(function);
        
        // 3. 创建交易请求
        Transaction transaction = Transaction.createEthCallTransaction(
            null,                    // from(只读可以为 null)
            CONTRACT_ADDRESS,        // to
            encodedFunction          // data
        );
        
        // 4. 执行调用
        EthCall response = web3j.ethCall(transaction, DefaultBlockParameterName.LATEST).send();
        
        // 5. 解码返回值
        if (response.isReverted()) {
            System.out.println("调用失败: " + response.getRevertReason());
            return;
        }
        
        String rawOutput = response.getResult();
        List<Type> decoded = FunctionReturnDecoder.decode(rawOutput, function.getOutputParameters());
        
        if (!decoded.isEmpty()) {
            BigInteger value = (BigInteger) decoded.get(0).getValue();
            System.out.println("当前存储值: " + value);
        }
    }
相关推荐
m0_3801671410 小时前
面向开发者的Top10加密货币数据API(2026年最新)
大数据·人工智能·区块链
2601_9594801514 小时前
Moneta Markets亿汇:“比特币高位修复风险偏好”
区块链
m0_380167141 天前
加密货币价格 API、市场数据 API 与 分析 API 有什么区别?
人工智能·ai·区块链
LedgerNinja1 天前
AEGET:提升决策效率,助力交易者建立清晰的交易体系
区块链
2601_961963382 天前
Spring Boot集成电子签章的7个典型问题与解决方案:从入门到生产级实践
大数据·人工智能·spring boot·python·区块链·智能合约
zhuhai_xigedian2 天前
物联网技术在源网荷储系统中的创新应用
大数据·运维·人工智能·区块链·能源
2601_959480152 天前
Moneta Markets亿汇:“比特币长期预期继续升温”
区块链
2601_961963382 天前
数据室里的“第一道锁”:电子保密协议(NDA)签署与防泄漏机制全解析
网络·人工智能·安全·金融·区块链·政务
HavenlonLabs2 天前
重塑链上未来的隐形基石:长期主义下的生态演进
大数据·人工智能·安全·区块链
LedgerNinja3 天前
2026美国5月未季调CPI年率
区块链