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

投稿 2026-07-22 14:27 点击数: 1

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

以太坊转账的核心原理

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

    随机配图
>发送方 (From):发起交易的账户,需拥有足够的ETH支付 gas 费。
  • 接收方 (To):接收ETH的账户地址,可以是EOA或智能合约地址。
  • 转账金额 (Value):要转移的ETH数量,单位是wei(1 ETH = 10^18 wei)。
  • Gas Limit:发送方愿意为这次交易支付的最大gas量,用于限制交易的计算复杂度。
  • Gas Price:发送方愿意为每单位gas支付的价格,决定了交易的优先级和矿工的激励。
  • 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过高可能导致资金浪费(未