:2026-03-28 23:42 点击:13
在以太坊乃至整个Web3的世界里,“钱包”是用户与区块链交互的核心,它不仅用于存储和管理以太坊(ETH)及各类代币,更是用户身份、资产和参与去中心化应用(DApps)的入口,很多人以为“发行钱包”是指像银行一样开立一个账户,但在以太坊的语境下,我们通常指的是创建和部署一个自定义的智能合约钱包,这可以是一个具有特定功能、规则或品牌标识的钱包。
本文将采用手把手的方式,带你一步步了解并实践如何在以太坊上发行一个属于自己的智能合约钱包。
准备工作:在开始之前,你需要什么?
在动手之前,请确保你已经具备以下条件:
第一步:创建一个新的Hardhat项目
打开终端,创建一个新的项目目录并进入:
mkdir my-eth-wallet cd my-eth-wallet
初始化Hardhat项目:
npx hardhat init
按照提示选择 "Create a basic sample project",并安装依赖。
第二步:编写智能合约钱包代码
Hardhat初始化后会有一个contracts目录,我们在这里创建我们的钱包合约。
在contracts目录下创建一个新文件,例如MyWallet.sol。
编写一个简单的钱包合约,这里我们创建一个基础的签名钱包,它允许通过指定所有者来控制资金,并能发送ETH和代币。
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
/**MyWallet
* @dev 一个简单的以太坊智能合约钱包,继承自Ownable,由所有者控制。
*/
contract MyWallet is Ownable {
constructor(address initialOwner) Ownable(initialOwner) {}
/**
* @dev 接收ETH的fallback函数
*/
receive() external payable {}
/**
* @dev 获取合约中存储的ETH余额
* @return 合约的ETH余额(以wei为单位)
*/
function getBalance() public view returns (uint256) {
return address(this).balance;
}
/**
* @dev 发送ETH指定地址
* @param recipient 接收ETH的地址
* @param amount 发送的ETH数量(以wei为单位)
*/
function sendETH(address payable recipient, uint256 amount) public onlyOwner {
require(recipient != address(0), "MyWallet: recipient is the zero address");
require(amount <= getBalance(), "MyWallet: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "MyWallet: ETH transfer failed");
}
/**
* @dev 发送ERC20代币指定地址(需要合约已授权)
* @param tokenAddress ERC20代币的合约地址
* @param recipient 接收代币的地址
* @param amount 发送的代币数量
*/
function sendToken(
address tokenAddress,
address recipient,
uint256 amount
) public onlyOwner {
require(recipient != address(0), "MyWallet: recipient is the zero address");
require(amount > 0, "MyWallet: amount must be greater than zero");
IERC20 token = IERC20(tokenAddress);
require(token.balanceOf(address(this)) >= amount, "MyWallet: insufficient token balance");
bool success = token.transfer(recipient, amount);
require(success, "MyWallet: token transfer failed");
}
}
代码解释:
SPDX-License-Identifier 和 pragma solidity:许可证和Solidity版本声明。import:导入OpenZeppelin库中的Ownable(所有权管理)和IERC20(ERC20代币接口)合约,使用OpenZeppelin可以避免重复造轮子,提高安全性。contract MyWallet is Ownable:我们的钱包合约继承自Ownable,这意味着合约会有一个所有者(owner),只有所有者才能执行某些关键操作。constructor(address initialOwner):构造函数,在部署时设置合约的所有者。receive() external payable:使合约能够接收ETH。getBalance():查看合约当前的ETH余额。sendETH():所有者调用此函数向指定地址发送ETH。sendToken():所有者调用此函数向指定地址发送ERC20代币。第三步:编译智能合约
确保你已经安装了OpenZeppelin合约:
npm install @openzeppelin/contracts
在终端中运行Hardhat compile命令:
npx hardhat compile
如果编译成功,你会在artifacts目录下看到编译好的合约字节码和ABI(应用二进制接口)。
第四步:编写部署脚本
在scripts目录下创建一个新的部署脚本,例如deploy.js。
编写部署脚本:
async function main() {
// 获取部署时指定的所有者地址(通常是部署者的地址)
const [deployer] = await ethers.getSigners();
console.log("Deploying contracts with the account:", deployer.address);
console.log("Account balance:", (await deployer.getBalance()).toString());
// 部署MyWallet合约
const MyWallet = await ethers.getContractFactory("MyWallet");
const initialOwner = deployer.address; // 将部署者设为初始所有者
const myWallet = await MyWallet.deploy(initialOwner);
await myWallet.deployed();
console.log("MyWallet deployed to:", myWallet.address);
}
main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});
代码解释:
ethers.getSigners():获取Hardhat网络中的账户(默认第一个是部署者)。ethers.getContractFactory("MyWallet"):获取合约工厂,用于部署合约。MyWallet.deploy(initialOwner):部署合约,并传入初始所有者地址。myWallet.deployed():等待合约部署完成。myWallet.address:输出部署后的合约地址,这就是你的“钱包地址”!第五步:部署合约到测试网
hardhat.config.js文件,添加测试网络的配置(以Goerli测试网为例,你需要替换成你自己的RPC URL和私钥,私钥要妥善保管!):require("@nomicfoundation/hardhat-toolbox");
require('dotenv').config(); // 使用dotenv管理环境变量
/** @type import('hardhat/config').HardhatUserConfig */
module.exports = {
solidity: "0.8.20",
networks: {
goerli: {
url: process.env.GOERLI_RPC_URL, // 从环境变量读取
accounts: [process.env.PRIVATE_KEY] // 从环境变量读取,测试网私钥不要暴露!
}
// 你可以添加其他测试网,如sepolia等
}
};
创建环境变量文件:
在项目根目录创建.env文件(记得将.env添加到.gitignore中,不要上传到代码仓库!):

你可以从Infura、Alchemy等服务提供商获取免费的RPC URL,MetaMask中可以导出私钥(极度谨慎,仅用于测试!)。
安装dotenv:
npm install dotenv
部署合约:
本文由用户投稿上传,若侵权请提供版权资料并联系删除!