以太坊转账代码解析,从原理到实践

投稿 2026-03-03 14:03 点击数: 1

以太坊作为全球领先的智能合约平台,其转账功能是区块链生态中最基础也最核心的操作之一,无论是日常的ETH(以太坊原生加密货币)转移,还是ERC20等代币的流转,都离不开转账代码的执行,本文将深入探讨以太坊转账的底层原理,并通过代码示例展示如何在不同场景下实现转账功能。

以太坊转账的核心原理

以太坊转账本质上是一次交易,它由发起者(EOA,Externally Owned Account,即外部拥有账户)签名后广播到以太坊网络,由矿工打包并确认,转账的核心要素包括:

  1. 发送方 (From):发起交易的账户,需拥有足够的ETH支付 gas 费。
  2. 接收方 (To):接收ETH的账户地址,可以是EOA或智能合约地址。
  3. 转账金额 (Value):要转移的ETH数量,单位是wei(1 ETH = 10^18 wei)。
  4. Gas Limit:发送方愿意为这次交易支付的最大gas量,用于限制交易的计算复杂度。
  5. Gas Price:发送方愿意为每单位gas支付的价格,决定了交易的优先级和矿工的激励。
  6. Nonce:发送方账户发出交易的数量,用于防止重放攻击。

当交易被打包进区块后,以太坊虚拟机(EVM)会执行这笔交易,如果是简单的ETH转账,EVM会验证发送方的签名、nonce、gas等,然后从发送方账户扣除相应数量的ETH和gas费用,并将ETH添加到接收方账户的余额中。

使用Web3.js进行以太坊转账(前端/Node.js环境)

Web3.js是与以太坊交互最流行的JavaScript库之一,以下是一个使用Web3.js进行ETH转账的代码示例:

const Web3 = require('web3');
const web3 = new Web3('https://mainnet.infura.io/v3/YOUR_INFURA_PROJECT_ID'); // 替换为你的Infura项目ID或其他以太坊节点URL
// 发送方私钥(注意:实际项目中应使用安全的方式管理和存储私钥,如硬件钱包或环境变量,切勿硬编码或明文存储!)
const senderPrivateKey = 'YOUR_SENDER_PRIVATE_KEY';
const senderAddress = web3.eth.accounts.privateKeyToAccount(senderPrivateKey).address;
// 接收方地址
const receiverAddress = '0xReceiverAddressHere...'; // 替换为接收方地址
// 转账金额(以ETH为单位,转换为wei)
const amountInETH = '0.1';
const amountInWei = web3.utils.toWei(amountInETH, 'ether');
async function sendTransaction() {
    try {
        // 获取当前nonce
        const nonce = await web3.eth.getTransactionCount(senderAddress, 'latest');
        // 构建交易对象
        const txObject = {
            nonce: nonce,
            to: receiverAddress,
            value: amountInWei,
            gasLimit: web3.utils.toHex(21000), // 转账ETH的gasLimit通常为21000
            gasPrice: web3.utils.toHex(await web3.eth.getGasPrice()), // 获取当前建议的gasPrice
        };
        // 签名交易
        const signedTx = await web3.eth.accounts.signTransaction(txObject, senderPrivateKey);
        // 发送交易
        const txReceipt = await web3.eth.sendSignedTransaction(signedTx.rawTransaction);
        console.log('Transaction hash: ', txReceipt.transactionHash);
        console.log('Transaction receipt: ', txReceipt);
    } catch (error) {
        console.error('Error sending transaction: ', error);
    }
}
sendTransaction();

代码解析

  1. 初始化Web3:连接到以太坊节点(如Infura)。
  2. 账户设置:发送方私钥用于签名交易,地址从私钥派生,接收方地址指定转账目标。
  3. 金额转换:将ETH转换为wei,因为以太坊底层以wei为单位。
  4. 获取Nonce:确保交易按正确顺序执行,防止重复。
  5. 构建交易对象:包含转账所需的所有关键信息。
  6. 签名交易:使用发送方私钥对交易进行签名,证明交易发送权。
  7. 发送交易:将签名后的交易广播到网络,并等待打包和确认,返回收据。

使用Ethers.js进行以太坊转账(现代前端/Node.js环境)

Ethers.js是另一个功能强大且用户友好的以太坊交互库,其API设计更现代化。

const { ethers } = require('ethers');
// 初始化Provider(连接到以太坊节点)
const provider = new ethers.providers.JsonRpcProvider('https://mainnet.infura.io/v3/YOUR_INFURA_PROJECT_ID');
// 发送方钱包(使用私钥创建)
const senderPrivateKey = 'YOUR_SENDER_PRIVATE_KEY';
const wallet = new ethers.Wallet(senderPrivateKey, provider);
// 接收方地址
const receiverAddress = '0xReceiverAddressHere...'; // 替换为接收方地址
// 转账金额(以ETH为单位)
const amountInETH = '0.1';
const amountInWei = ethers.utils.parseEther(amountInETH); // parseEther用于将ETH字符串转为wei(BigNumber)
async function sendTransactionWithEthers() {
    try {
        // 获取当前nonce
        const nonce = await provider.getTransactionCount(wallet.address, 'latest');
        // 发送交易(ethers.js的sendTransaction会自动构建交易对象、签名并发送)
        const txResponse = await wallet.sendTransaction({
            to: receiverAddress,
            value: amountInWei,
            gasLimit: 21000,
            // gasPrice可以省略,provider会自动估算或使用默认值
        });
        console.log('Transaction hash: ', txResponse.hash);
        console.log('Waiting for transaction to be mined...');
        // 等待交易被打包
        const txReceipt = await txResponse.wait();
        console.log
随机配图
('Transaction mined in block: ', txReceipt.blockNumber); console.log('Transaction receipt: ', txReceipt); } catch (error) { console.error('Error sending transaction: ', error); } } sendTransactionWithEthers();

代码解析

  1. Provider:用于连接以太坊网络,只读。
  2. Wallet:使用私钥和Provider创建钱包对象,具备发送交易的能力。
  3. parseEther:将ETH字符串转换为BigNumber类型的wei。
  4. sendTransaction:钱包对象的方法,简化了交易构建、签名和发送过程。
  5. wait():等待交易被打包,并返回收据。

使用Solidity编写智能合约进行转账(合约到账户/合约到合约)

虽然直接的ETH转账通常由EOA发起,但在智能合约内部也可以进行转账,常见于合约提取资金或向其他账户/合约转ETH。

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
contract EtherTransferor {
    // 合约接收ETH的fallback函数
    receive() external payable {}
    // 转账函数:将合约中的ETH转给指定EOA
    function transferToEOA(address payable recipient, uint256 amount) external {
        require(address(this).balance >= amount, "Insufficient balance in contract");
        require(recipient != address(0), "Invalid recipient address");
        (bool success, ) = recipient.call{value: amount}("");
        require(success, "Transfer failed");
    }
    // 转账函数:将合约中的ETH转给另一个合约(假设目标合约有receive或fallback函数)
    function transferToContract(address payable recipientContract, uint256 amount) external {
        require(address(this).balance >= amount, "Insufficient balance in contract");
        require(recipientContract != address(0), "Invalid recipient contract address");
        (bool success, ) = recipientContract.call{value: amount}("");
        require(success, "Transfer to contract failed");
    }
    // 获取合约当前ETH余额
    function getBalance() external view returns (uint256) {
        return address(this).balance;
    }
}

Solidity代码解析

  1. receive() external payable:使合约能够接收直接发送的ETH。
  2. transferToEOA/transferToContract
    • payable关键字表示该地址可以接收ETH。
    • require语句进行条件检查,如余额充足、地址有效。
    • recipient.call{value: amount}(""):这是在Solidity中推荐的使用call进行ETH转账的方式,可以传递value和gas。call返回一个布尔值表示成功与否。
  3. getBalance:查询合约当前的ETH余额。

注意事项与最佳实践

  1. 私钥安全:私钥是控制账户的唯一凭证,务必妥善保管,避免泄露或丢失,建议使用硬件钱包(如Ledger, Trezor)或专业的密钥管理服务。
  2. Gas管理:合理设置Gas Limit和Gas Price,Gas Limit过高可能导致资金浪费(未