Web3 ESP32 send transaction to a smart contract

Hi everyone

Im trying to send the transaction on my deployed smart contract (Sepolia) via ESP32 Web3

The contract is most basic

//SPDX-License-Identifier: GPL-3.0

pragma solidity >=0.8.2 <0.9.0;

contract SmartContractDeployment {
    uint256 number;

    event Log(string message);

    function store(uint256 num) public {
        emit Log("new number stored");
        number = num;
    }

    function retrieve() public view returns (uint256){
        return number;
    }
}

but I encountered some issues with coding

MY_ADDRESS is the address that pays for the transaction
SETUPCONTRACT is the address of the contract deployed on the network

void setup() {
    Serial.begin(115200);
    web3 = new Web3(SEPOLIA_ID);

    WiFi.begin(ssid, password);
    while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
    }
    // Print local IP address and start web server
    Serial.println("");
    Serial.println("WiFi connected.");
    Serial.println("IP address: ");
    Serial.println(WiFi.localIP());
    server.begin();

  sendTransactionToSmartContract(MY_ADDRESS, SETUPCONTRACT);
}

void sendTransactionToSmartContract(const char *toAddr, const char *contractAddr)
{
	string contractAddrStr = contractAddr;  // contract Address
	Contract contract(web3, contractAddr);  // connect to contract in Web3
	contract.SetPrivateKey(PRIVATE_KEY);    // set private key of your wallet
        string address = MY_ADDRESS;            // write address in string

	// //Get contract name (This isn't needed to push the transaction)
	// string param = contract.SetupContractData("name()", &toAddr); // set up contract data to return the name of the contract
	// string result = contract.ViewCall(&param); // 
	// string interpreted = Util::InterpretStringResult(web3->getString(&result).c_str());
	// Serial.println(interpreted.c_str());

	// //Get Contract decimals
	// param = contract.SetupContractData("decimals()", &toAddr);
	// result = contract.ViewCall(&param);
	// int decimals = web3->getInt(&result);
	// Serial.println(decimals);

	// //amount of erc20 token to send, note we use decimal value obtained earlier
	// uint256_t weiValue = Util::ConvertToWei(tokens, decimals);

	//get nonce
  Serial.print("Get Nonce: ");
  string toAddress = toAddr;
	uint32_t nonceVal = (uint32_t)web3->EthGetTransactionCount(&address); // nonce Val
  unsigned long long gasPriceVal = 2200000000LL;
	uint32_t  gasLimitVal = 4300000;
	uint256_t callValue = 0;
  Serial.println(nonceVal);
	Serial.println("Send TX");

	//Setup contract function call
	string p = contract.SetupContractData("store(uint256)", 123);

	//push transaction to ethereum
	string result = contract.SendTransaction(nonceVal, gasPriceVal, gasLimitVal, &contractAddrStr, &callValue, &p);
  Serial.println(result.c_str());
	string transactionHash = web3->getResult(&result);

  Serial.println("TX on Etherscan:");
	Serial.print(ETHERSCAN_TX);
	Serial.println(transactionHash.c_str()); //you can go straight to etherscan and see the pending transaction
}

Loop and wifi connections are fine

Keep receiving this error

WiFi connected.
IP address:
172.20.10.4
Get Nonce: 332
Send TX
Guru Meditation Error: Core 1 panic’ed (LoadProhibited). Exception was unhandled.

Core 1 register dump:
PC : 0x400db0a7 PS : 0x00060530 A0 : 0x800db127 A1 : 0x3ffcc5f0
A2 : 0x0000007b A3 : 0x3ffcc664 A4 : 0x0000007b A5 : 0x3ffd75ac
A6 : 0x3ffcc7d0 A7 : 0x3ffcc960 A8 : 0x8009248c A9 : 0x3ffcc5e0
A10 : 0x3ffd8370 A11 : 0x3ffd8370 A12 : 0x3ffd7594 A13 : 0x3ffcc7a2
A14 : 0x00000036 A15 : 0x00000035 SAR : 0x00000014 EXCCAUSE: 0x0000001c
EXCVADDR: 0x00000082 LBEG : 0x40089975 LEND : 0x40089985 LCOUNT : 0xfffffff7

Backtrace: 0x400db0a4:0x3ffcc5f0 0x400db124:0x3ffcc620 0x400db35a:0x3ffcc640 0x400d6af7:0x3ffcc660 0x400d71c1:0x3ffcc690 0x400d2f51:0x3ffcc7d0 0x400d3191:0x3ffcc980 0x400ddbe6:0x3ffcc9c0

Can somebody help please :pray:

Okay, you have a crash. Do as instructed in here so that it shows you on the serial monitor which function crashed at which line.

Here’s my init file

[env:esp32dev]
platform = espressif32
board = esp32dev
framework = arduino
monitor_speed = 115200
monitor_filters = esp32_exception_decoder
build_type = debug
lib_ldf_mode = deep
lib_deps = alphawallet/Web3E@^1.44

I have also changed the function a bit to this one

void SendTransToContract(const char *contractAddr)
{
Contract contract(web3, SETUPCONTRACT);

string contractAddrStr = contractAddr;

// Set your secret to contract.
// This secret will not send to server (of course!) but use in local to sign.
contract.SetPrivateKey(PRIVATE_KEY);


// set required data to execute sendTransaction
// nonce can be get with web3.EthGetTransactionCount() API
string address = MY_ADDRESS;
uint32_t nonceVal = (uint32_t)web3->EthGetTransactionCount(&address);
uint32_t gasPriceVal = 141006540;
uint32_t  gasLimitVal = 3000000;
uint8_t toStr[] = SETUPCONTRACT;
uint256_t callValue = 0;
uint8_t dataStr[100];
memset(dataStr, 0, 100);

// Generate binary data to send contract.
// In this case, generate data to send to "set(uint256)" and use "123" as first parameter.
string p = contract.SetupContractData("store(uint256)", 123);

// send transaction
string result = contract.SendTransaction(nonceVal, gasPriceVal, gasLimitVal, &contractAddrStr, &callValue, &p);
string transactionHash = web3->getResult(&result); // get the result as transaction hash
Serial.println("TX on Etherscan:");
Serial.print(ETHERSCAN_TX); // link to etherscan
Serial.println(transactionHash.c_str());
}

And have received this errors

#0  0x400de228:0x3ffcc510 in uint128_t::ConvertToVector(std::vector<unsigned char, std::allocator<unsigned char> >&, unsigned long long const&) const at .pio/libdeps/esp32dev/Web3E/src/uint256/uint128_t.cpp:305
#1  0x400de2a8:0x3ffcc540 in uint128_t::export_bits(std::vector<unsigned char, std::allocator<unsigned char> >&) const at .pio/libdeps/esp32dev/Web3E/src/uint256/uint128_t.cpp:317
#2  0x400dee86:0x3ffcc560 in uint256_t::export_bits() const at .pio/libdeps/esp32dev/Web3E/src/uint256/uint256_t.cpp:507
#3  0x400d6c8b:0x3ffcc580 in Contract::GenerateBytesForUint[abi:cxx11](uint256_t const*) at .pio/libdeps/esp32dev/Web3E/src/Contract.cpp:250
#4  0x400d8775:0x3ffcc5b0 in Contract::SetupContractData[abi:cxx11](char const*, ...) at .pio/libdeps/esp32dev/Web3E/src/Contract.cpp:86
#5  0x400d2fbd:0x3ffcc780 in SendTransToContract(char const*) at src/main.cpp:225
#6  0x400d31d6:0x3ffcc980 in setup() at src/main.cpp:64
#7  0x400e117e:0x3ffcc9c0 in loopTask(void*) at /Users/*myuser*/.platformio/packages/framework-arduinoespressif32/cores/esp32/main.cpp:42

I basically try to implement this code

https://medium.com/@takahirookada/handle-smart-contract-on-ethereum-with-arduino-or-esp32-1bb5cbaddbf4

But it seems there are some differences in the libraries

Recent news

I changed the code a bit

void SendTransToContract(const char *contractAddr)
{
// Generate contract instance. Pass contract address as 2nd parameter.
Contract contract(web3, SETUPCONTRACT);

// Set your secret to contract.
// This secret will not send to server (of course!) but use locally to sign.
contract.SetPrivateKey(PRIVATE_KEY);
string address = MY_ADDRESS;

// Get nonce with web3->EthGetTransactionCount() API
uint32_t nonceVal = (uint32_t)web3->EthGetTransactionCount(&address);
uint32_t gasPriceVal = 141006540;
uint32_t gasLimitVal = 3000000;
string toStr = SETUPCONTRACT;
uint256_t valueStr = 0x00;
uint8_t dataStr[100];
memset(dataStr, 0, 100);
Serial.println(nonceVal);
// Generate binary data to send contract.
// In this case, generate data to send to "store(uint256)" and use "123" as the first parameter.
contract.SetupContractData((char*)dataStr, "store(uint256)", 123);

// Convert dataStr to std::string
std::string dataString(reinterpret_cast<char*>(dataStr));

// send transaction
string result = contract.SendTransaction(nonceVal, gasPriceVal, gasLimitVal, &toStr, &valueStr, &dataString);
Serial.println(result.c_str());
  string transactionHash = web3->getResult(&result);

Serial.println("TX on Etherscan:");
  Serial.print(ETHERSCAN_TX);
  Serial.println(transactionHash.c_str()); 

}

And it actually worked!

https://sepolia.etherscan.io/tx/e99fa396a529a997a6930f4280ba4d2b8ba453a698b731bbe94eda50a2381c47

However for some reason the pending is very long. It took more than 10 mins and still nothing

Do i need to send some money on the contract? Or change gasLimit gasPrice values?

I don’t know how this relates to PlatformIO.

The chance of getting an answer increases if you ask the question in a specialized smart contract forum.