
编译
点击图中的 "Compile 1_Storage.sol"
存和取一个数的合约,remix自带
js
pragma solidity >=0.8.2 <0.9.0;
/**
* @title Storage
* @dev Store & retrieve value in a variable
* @custom:dev-run-script ./scripts/deploy_with_ethers.ts
*/
contract Storage {
uint256 number;
function store(uint256 num) public {
number = num;
}
function retrieve() public view returns (uint256){
return number;
}
}
部署
复制右侧的 WEB3DEPLOY中的代码,node test.js
js
const {Web3} = require('web3');
const web3 = new Web3('http://192.168.137.131:8545');
var storageContract = new web3.eth.Contract([{
"inputs":[],"name":"retrieve",
"outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"num","type":"uint256"}],
"name":"store","outputs":[],"stateMutability":"nonpayable","type":"function"
}]);
var storage = storageContract.deploy({
data: '0x6080604052348015600e575f5ffd5b506101298061001c5f395ff3fe6080604052348015600e575f5ffd5b50600436106030575f3560e01c80632e64cec11460345780636057361d14604e575b5f5ffd5b603a6066565b60405160459190608d565b60405180910390f35b606460048036038101906060919060cd565b606e565b005b5f5f54905090565b805f8190555050565b5f819050919050565b6087816077565b82525050565b5f602082019050609e5f8301846080565b92915050565b5f5ffd5b60af816077565b811460b8575f5ffd5b50565b5f8135905060c78160a8565b92915050565b5f6020828403121560df5760de60a4565b5b5f60ea8482850160bb565b9150509291505056fea26469706673582212202cea03f67c4fe745ae13812f1274b78c1f2a3eddb43bb7dd680a2b702d0b068664736f6c634300081c0033',
arguments: [
]
}).send({
from: "0xC2b9f3b30fA3d808002adc50836A28d16c14FaF5",
gas: '4700000'
}, function (e, contract){
console.log(e, contract);
if (typeof contract.address !== 'undefined') {
console.log('Contract mined! address: ' + contract.address + ' transactionHash: ' + contract.transactionHash);
}
})
奇怪的是没有打印合约地址,手动查看(合约的那条交易只有FROM 没有TO)
shell
# geth 通过交易 id 找到 contractAddress
> eth.getTransactionReceipt("0xd8fa5bb0052bf19759fed821dc6c8b86bdc70bd8ea31caed92ea36103741048b").contractAddress
"0xb5e4db78acf3a423c7ca5c483064f8d98329b325"

调用
contractABI , contractAddress
js
const { Web3 } = require('web3');
// 连接到以太坊节点
const web3 = new Web3('http://192.168.137.131:8545');
var account_1 = "0xC2b9f3b30fA3d808002adc50836A28d16c14FaF5";
var contractAddress = "0xb5e4db78acf3a423c7ca5c483064f8d98329b325";
var contractABI = [
{
"inputs": [],
"name": "retrieve",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "num",
"type": "uint256"
}
],
"name": "store",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
}
];
// 创建智能合约实例
var Storage_Contract = new web3.eth.Contract(contractABI, contractAddress);
// 调用 retrieve 方法
// Storage_Contract.methods.retrieve().call({ from: account_1 })
// .then((result) => {
// console.log("结果_retrieve: " + result);
// })
// .catch((error) => {
// console.error("调用失败:", error);
// });
// 调用 store 方法,存储数据(例如存储数字 10)
Storage_Contract.methods.store(10).send({ from: account_1 })
.then((receipt) => {
console.log("结果_store:", receipt);
})
.catch((error) => {
console.error("调用失败:", error);
});

ABI
ABI(Application Binary Interface)以太坊采用的是 ABI 编码标准,用于将函数参数转化为字节流。
在以太坊交易中,input 字段包含了与交易相关的附加数据,通常是调用智能合约函数时传递的数据。对于智能合约的函数调用,这些数据会包括方法的签名(即函数的选择器)和函数参数的编码。具体来说,input 字段通常由两部分组成:
-
函数选择器(Function Selector):
0x6057361d
是函数store(uint256)
的Keccak-256哈希值的前4个字节 -
编码的函数参数:每个参数按照其类型进行编码。
这个 input 字段的含义是:向合约的 store
方法传递一个 uint256
类型的参数,值为 a
。
如果函数是参数是 string
类型
0xc63576e4000000000000000000000000000000000000000000000000000000
0000000020
0000000000000000000000000000000000000000000000000000000000000008
3230303131323235
000000000000000000000000000000000000000000000000
0xc63576e4
- 字符串的偏移量 0x20
0008
字符串的长度以32字节为单位进行存储- 3230303131323235 为 16进制编码后的参数
以前的写法(现在是send()
方法):代码第二行明确使用encoderABI()
js
const signContract = async (contractContent) => {
const data = contract.methods.signContract(contractContent).encodeABI();
const gas = await web3.eth.estimateGas({ to: contractAddress, data: data });
const tx = {
to: contractAddress,
data: data,
gas: gas,
};
const signedTx = await web3.eth.accounts.signTransaction(tx, privateKey);
const receipt = await web3.eth.sendSignedTransaction(signedTx.rawTransaction);
console.log('Transaction receipt:', receipt);
};