ETH中的账户分为两类:外部账户和合约账户。账户类型谁能控制如何创建地址来源外部账户(EOA)拥有私钥的人生成一对密钥(私钥+公钥)address=keccak256(pubkey)[12:]合约账户由代码控制通过部署合约交易创建add
ETH中的账户分为两类:外部账户 和 合约账户。
账户类型 | 谁能控制 | 如何创建 | 地址来源 |
---|---|---|---|
外部账户 (EOA) | 拥有私钥的人 | 生成一对密钥(私钥 + 公钥) | address = keccak256(pubkey)[12:] |
合约账户 | 由代码控制 | 通过部署合约交易创建 | address = keccak256(creator, nonce) 或 create2 |
那么账户是怎么创建的呢?哪些行为会创建账户呢?
就这个问题,一步一步从头讲,尽量通俗易懂地串起来讲清楚这几个概念:从公钥私钥 → 外部账户 → 合约账户 → 交易 → 合约部署。
以太坊账户的本质是由椭圆曲线加密算法(secp256k1)生成的。
随机
生成 32 字节私钥 后 20 字节
,得到地址ethers.js
):import { Wallet } from "ethers";
// 生成新钱包(随机私钥)
const wallet = Wallet.createRandom();
console.log("私钥:", wallet.privateKey);
console.log("公钥:", wallet.publicKey);
console.log("地址:", wallet.address);
在安装 MetaMask 并点击“创建新钱包”时,它会:
MetaMask 的助记词可以生成无限多个账户(它们都来自同一个种子)。
🌐 MetaMask 或代码生成:
↓
助记词(Mnemonic) 或 随机数
↓
私钥(Private Key)
↓
公钥(Public Key)
↓
地址(Address)
EOA 由私钥控制,具备以下特性:
发起交易
在钱包(如 MetaMask)里看到的账户,就是一个 EOA。
合约账户的地址是由一个 EOA 或合约创建交易时计算得出的
参考文章:ETH 之合约账户
交易有三种类型:
交易内容包括:
const provider = new ethers.JsonRpcProvider("http://localhost:8545"); // 或 Infura 等
const signer = wallet.connect(provider);
const tx = await signer.sendTransaction({
to: "0x1234...abcd",
value: ethers.parseEther("0.01"),
});
console.log("交易哈希:", tx.hash);
部署合约本质是:
to
为 null
(即新地址)data
是合约的 初始化字节码(bytecode)keccak256(rlp(sender_address, nonce))
得出ethers.js
部署合约import { ethers } from "ethers";
import { abi, bytecode } from "./MyContract.json";
const provider = new ethers.JsonRpcProvider("http://localhost:8545");
const signer = wallet.connect(provider);
const factory = new ethers.ContractFactory(abi, bytecode, signer);
const contract = await factory.deploy();
await contract.waitForDeployment();
console.log("合约部署地址:", contract.target);
私钥 → 公钥 → 地址(EOA)
↓
EOA 发交易(包含 bytecode)→ 新地址(Contract Account)
↓
链上部署合约,合约账户诞生
↓
之后可以通过交易调用合约方法
你可以把这个过程理解成:
🔑 你拥有钥匙 → 👤 创建账户 → 📦 发布代码 → 🧠 拥有合约 → 🚀 运行逻辑
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!