:2026-08-13 10:48 点击:2
随着区块链技术的飞速发展,Web3正逐渐从一个概念走向现实,去中心化应用(DApps)作为其重要载体,正吸引着越来越多的开发者和创业者,而智能合约,作为DApps的核心逻辑载体,其部署过程是每一位Web3开发者必须掌握的技能,本文将以目前最受欢迎的公链之一——以太坊(Ethereum)为例,并结合Web3技术栈,详细讲解如何一步步部署你的第一个智能合约。
在开始部署之前,我们需要准备一些必要的工具和环境,就像盖房子前需要准备好砖瓦水泥一样。
智能合约是一段部署在区块链上的自动执行的代码,我们以一个简单的“存储合约”(Storage Contract)为例,它允许用户存储和获取一个字符串。
创建项目目录:
mkdir my-first-contract cd my-first-contract npm init -y
安装必要的依赖:
# 安装web3.js,用于与以太坊交互 npm install web3 # 安装solc,solidity编译器(也可以全局安装或使用node-gyp编译本地版本) npm install solc
编写Solidity合约代码:
在项目目录下创建一个名为 Storage.sol 的文件,并写入以下代码:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @title Storage
* @dev 这是一个简单的存储合约,允许用户存储和检索一个字符串。
*/
contract Storage {
string private storedData;
event DataSet(string indexed newData);
/**
* @dev 存储一个字符串到合约中。
* @param _data 要存储的字符串。
*/
function set(string memory _data) public {
storedData = _data;
emit DataSet(_data);
}
/**
* @dev 检索存储的字符串。
* @return 存储的字符串。
*/
function get() public view returns (string memory) {
return storedData;
}
}
这段代码定义了一个名为 Storage 的合约,包含一个 set 函数(用于存储数据)和一个 get 函数(用于获取数据),以及一个事件 DataSet。
编写好合约代码后,我们需要使用Solidity编译器将其编译成ABI(Application Binary Interface,应用程序二进制接口)和字节码(Bytecode),ABI是合约与外部交互的接口规范,字节码是部署到EVM的实际代码。
在项目目录下创建一个名为 compile.js 的文件,用于编写编译脚本:
const path = require('path');
const fs = require('fs');
const solc = require('solc');
// 获取合约文件路径
const contractPath = path.resolve(__dirname, 'contracts', 'Storage.sol');
// 读取合约文件内容
const contractSource = fs.readFileSync(contractPath, 'utf8');
// 配置编译选项
const input = {
language: 'Solidity',
sources: {
'Storage.sol': {
content: contractSource
}
},
settings: {
outputSelection: {
'*': {
'*': ['*']
}
}
}
};
// 编译合约
const compiledOutput = JSON.parse(solc.compile(JSON.stringify(input)));
// 获取编译后的合约信息
const contract = compiledOutput.contracts['Storage.sol']['Storage'];
// 将ABI和字节码写入单独的文件
fs.writeFileSync(
path.resolve(__dirname, 'build', 'Storage.json'),
JSON.stringify(contract, null, 2)
);
console.log('合约编译成功!');
注意:请确保你的 contracts 文件夹下有 Storage.sol 文件,并在项目根目录下创建 build 文件夹。
运行编译脚本:
node compile.js
如果成功,你会在 build 文件夹下看到一个 Storage.json 文件,里面包含了合约的ABI和字节码(evm.bytecode.object)。
编译完成后,就可以将合约部署到以太坊测试网了,部署合约需要发送一笔包含合约创建代码的交易到以太坊网络。
连接到以太坊节点: 你可以连接到自己的以太坊节点,但更简单的方式是使用第三方Infura或Alchemy提供的节点服务。
编写部署脚本:
在项目目录下创建一个名为 deploy.js 的文件:
const Web3 = require('web3');
const fs = require('fs');
const path = require('path');
// 1. 初始化Web3实例,连接到以太坊节点(这里以Goerli测试网为例)
const web3 = new Web3('https://goerli.infura.io/v3/YOUR_INFURA_PROJECT_ID'); // 替换为你的Infura项目ID
// 或者,如果你使用本地节点:const web3 = new Web3('http://localhost:8545');
// 2. 获取编译后的合约ABI和字节码
const contractPath = path.resolve(__dirname, 'build', 'Storage.json');
const contractJson = JSON.parse(fs.readFileSync(contractPath, 'utf8'));
const abi = contractJson.abi;
const bytecode = contractJson.evm.bytecode.object;
// 3. 设置部署账户(使用MetaMask导入的账户)
// 注意:在实际部署中,不应该在代码中硬编码私钥!
// 这里仅作演示,你应该通过环境变量或其他安全方式管理私钥。
// 或者,使用web3.eth.personal.unlockAccount(如果节点支持)或通过MetaMask发送交易。
// 更推荐的方式是使用web3.eth.sendTransaction,让MetaMask处理签名。
const privateKey = 'YOUR_PRIVATE_KEY_HERE'; // 替换为你的MetaMask账户私钥(仅测试网使用,且不要泄露!)
const account = web3.eth.accounts.privateK
eyToAccount(privateKey);
web3.eth.accounts.wallet.add(account);
// 4. 创建合约实例
const contract = new web3.eth.Contract(abi);
// 5. 部署合约
const deploy = async () => {
try {
const gasEstimate = await contract.deploy({
data: bytecode,
arguments: ['Hello, Web3!'] // 这是构造函数的参数,我们的Storage合约没有构造函数参数,所以传空数组或省略
}).estimateGas({
from: account.address
});
const deployedContract = await contract.deploy({
data: bytecode,
arguments: ['Hello, Web3!'] // 如果构造函数需要参数,在这里传入
}).send({
from: account.address,
gas: gasEstimate,
gasPrice: await web3.eth.getGasPrice()
});
console.log('合约部署成功!');
console.log('合约地址:', deployedContract.options.address);
console.log('交易哈希:', deployedContract.transactionHash);
} catch (error) {
console.error('部署失败:', error);
}
};
deploy();
重要提示:
将 `YOUR_INF
本文由用户投稿上传,若侵权请提供版权资料并联系删除!