You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ESP32 WROOM-32D连接Web3触发core abort()异常求助

ESP32使用web3-arduino库触发abort异常的分析与解决

问题背景

使用web3-arduino库将ESP32 WROOM-32D连接Web3,在Arduino IDE和PlatformIO中测试eth_send示例,设备连接WiFi后触发abort异常,控制台输出:

[SETUP] WAIT 4...
[SETUP] WAIT 3...
[SETUP] WAIT 2...
[SETUP] WAIT 1...
.Connected
abort() was called at PC 0x40162ff7 on core 1

Backtrace:0x40162ff7:0x3ffb23d00x4008cd21:0x3ffb23f0 0x40091ed1:0x3ffb2410 
0x40162ff7:0x3ffb2490 0x4016303e:0x3ffb24b0 0x40154283:0x3ffb24d0 0x40153d92:0x3ffb24f0
 0x40155275:0x3ffb2510 0x4015551d:0x3ffb2530
 0x400dddef:0x3ffb2560 0x400de337:0x3ffb2580 0x400d293a:0x3ffb2610 0x400d2ada:0x3ffb27f0
 0x400e0366:0x3ffb2820

经ESP exception Decoder解码后,关键调用栈片段:

0x400de337: Web3::EthGetTransactionCount(std::__cxx11::basic_string<char, std::allocator<char> > const*) (C:\Program Files (x86)\Arduino\libraries\web3-arduino\src\Web3.cpp line 137
0x400d293a: eth_send_example() at C:\Users\yanna\Documents\Arduino\basic_web3\eth_send/eth_send.ino line 53

异常原因分析

从解码后的栈信息可定位,异常触发在EthGetTransactionCount函数内的字符串拼接操作,根源是代码中多次错误地将C风格字符串/数组强制转换为std::string*类型,导致内存访问非法:

  • 初始化Web3对象时,直接把const char*类型的INFURA_HOST/INFURA_PATH强转为string*,传入的指针并非指向合法的std::string对象
  • 调用EthGetTransactionCount时,将宏定义的C字符串MY_ADDRESS强转为string*,属于非法类型转换
  • 后续Contract初始化、SendTransaction调用中,存在uint8_t[]强转string*的错误,进一步引发内存操作异常

解决方案

修正所有非法类型转换,正确构造std::string对象,修改后的完整代码如下:

#include <WiFi.h>
#include <Web3.h>
#include <Contract.h>

#define USE_SERIAL Serial

const char* ssid = "V1A7C";
const char* password =  /*<password>*/;
#define MY_ADDRESS "0x1b9aE0Be6d87e79b9Bd5A6FcDc67d92F76F6e0F6"
#define CONTRACT_ADDRESS "0xDA832c3825A37d693d17D9360d5289B8B2b580f0"
#define INFURA_HOST "eth-rinkeby.alchemyapi.io"
#define INFURA_PATH "/v2/1yNgxbZKvL4JzOIjnNUywYue0ruh_Fjt"

const char PRIVATE_KEY[] = {/*<32 bytes of private key>*/};

// 正确构造std::string对象,避免强制类型转换
Web3 web3(string(INFURA_HOST), string(INFURA_PATH));

void eth_send_example();

void setup() {
    USE_SERIAL.begin(115200);

    for(uint8_t t = 4; t > 0; t--) {
        USE_SERIAL.printf("[SETUP] WAIT %d...\n", t);
        USE_SERIAL.flush();
        delay(1000);
    }

    WiFi.begin(ssid, password);

    while (WiFi.status() != WL_CONNECTED) {
        Serial.print(".");
        delay(1000);
    }

    USE_SERIAL.println("Connected");

    eth_send_example();
}

void loop() {
}

void eth_send_example() {
    // 正确构造Contract对象,传入合法的string
    Contract contract(&web3, string(CONTRACT_ADDRESS));
    // 直接传入PRIVATE_KEY,const char*可隐式转换为uint8_t*
    contract.SetPrivateKey((uint8_t*)PRIVATE_KEY);
    // 传入std::string对象,而非强转C字符串
    uint32_t nonceVal = (uint32_t)web3.EthGetTransactionCount(string(MY_ADDRESS));

    uint32_t gasPriceVal = 141006540;
    uint32_t gasLimitVal = 3000000;
    // 用std::string替代uint8_t数组,消除类型不匹配问题
    string toStr = CONTRACT_ADDRESS;
    string valueStr = "0x00";
    string func = "mint(uint256)";
    string p = contract.SetupContractData(&func, 123);
    // 传入合法的std::string对象
    string result = contract.SendTransaction(nonceVal, gasPriceVal, gasLimitVal, toStr, valueStr, p);

    Serial.println(result.c_str());
}

关键修改点

  1. 初始化Web3时,用string(INFURA_HOST)和string(INFURA_PATH)构造合法的std::string对象,不再强制转换指针
  2. 调用EthGetTransactionCount时,传入string(MY_ADDRESS),避免C字符串转string*的非法操作
  3. 替换uint8_t[]类型的toStr、valueStr为std::string,消除类型不匹配问题
  4. SendTransaction调用时直接传入std::string对象(若库函数要求指针则传&toStr,优先直接传对象)
  5. 打印result时用c_str()转换为C风格字符串,适配Serial.println的参数要求

额外注意事项

  • 确保PRIVATE_KEY是正确的32字节私钥(无0x前缀),若带前缀需去掉后再传入
  • 注意Rinkeby测试网已废弃,建议切换到Sepolia等活跃测试网,并同步修改节点地址
  • ESP32内存有限,若后续仍有内存异常,可尝试增大堆内存或优化字符串操作

内容的提问来源于stack exchange,提问作者Yan Naing Win

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 23:33:24