You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ganache Cli私有网络账户ETH莫名归零问题求助

问题描述

我使用以下命令启动Ganache CLI私有网络,为3个账户初始化了大额ETH:

ganache-cli -h "159.89.119.189" -a 3 -e "1000000000000000000000000000" --secure -u 0 -u 1 -u 2 -s 20

但运行数分钟后,所有账户的ETH全部归零,无法执行任何交易或合约调用。我的DApp通过以下app.js代码连接该网络,请求帮忙排查问题:

App = {
    web3Provider: null,
    contracts: {},
    account: 0x0,
    coinbase: 0x0,
    coinbase_amount: 0,
    loading: false,
    init: function () {
        return App.initWeb3();
    },
    initWeb3: function () {
        // initialize web3
        if (typeof web3 !== 'undefined') {
            //reuse the provider of the Web3 object injected by Metamask
            App.web3Provider = web3.currentProvider;
        } else {
            //create a new provider and plug it directly into our local node
            //App.web3Provider = new Web3.providers.HttpProvider('http://localhost:8545');
            App.web3Provider = new Web3.providers.HttpProvider('http://159.89.119.189:8545');
        }
        web3 = new Web3(App.web3Provider);
        App.getCoinbase();
        return App.initContract();
    },
    hostname: function () {
        return window.location.origin;
    },
    setAccount: function (address) {
        App.account = address;
    },
    displayAccountInfo: function () {
        // console.log(App);
        if (App.account != 0) {
            toastr.remove();
            toastr.info('Getting Account Info', {timeOut: 300000});
            $('#account').text(App.account);
            App.getBalance();
        }
    },
    getBalance: function() {
        web3.eth.getBalance(App.account, function (err, balance) {
            if (err === null) {
                if(web3.fromWei(balance, "ether") == 0){
                    setTimeout(App.getBalance(), 60000);
                } else {
                    console.log(web3.fromWei(balance, "ether"));
                    toastr.remove();
                    $('#accountBalance').text(web3.fromWei(balance, "ether") + " ETH");
                }
            }
        })
    },
    getCoinbase: function () {
        web3.eth.getCoinbase(function (err, account) {
            if (err === null) {
                App.coinbase = account;
                // $('#account').text(account);
                web3.eth.getBalance(account, function (err, balance) {
                    if (err === null) {
                        App.coinbase_amount = web3.fromWei(balance, "ether").toNumber();
                        console.log(App.coinbase, App.coinbase_amount)
                    }
                })
            }
        });
    },
    transfer: function() {
        web3.personal.unlockAccount(App.coinbase, "pass12345", 100000, function (err, result) {
            console.log(result)
            console.log(err)
            web3.personal.unlockAccount(App.account, "pass@123", 100000, function (err, result) {
                web3.eth.sendTransaction({
                    from: App.coinbase,
                    to: App.account,
                    value: web3.toWei(10, "ether")
                }, function (err, result) {
                    if (err == null) {
                        console.log("sent money");
                        console.log(result)
                        console.log(err)
                        web3.eth.getBalance(App.account, function (err, balance) {
                            if (err === null) {
                                console.log(web3.fromWei(balance, "ether") + " ETH");
                            }
                        })
                    } else {
                        console.log(err);
                    }
                })
            });
        });
    },
    register: function () {
        let email = $('#inputEmail');
        let fname = $('#inputFname');
        let lname = $('#inputLname');
        let password = $('#inputPassword');
        let btnRegister = $('#btnRegister');

        if (email.val() == "" || fname.val() == "" || lname.val() == "" || password.val() == "") {
            toastr.error('Please fill all fields');
            return false;
        }

        btnRegister.attr("disabled", 'disabled');

        web3.personal.newAccount("pass@123", function (err, data) {
            let address = data;
            if (err === null) {
                let postData = {
                    email: email.val(),
                    fname: fname.val(),
                    lname: lname.val(),
                    password: password.val(),
                    address: data
                }
                $.ajax({
                    method: "POST",
                    url: App.hostname() + "/register",
                    data: postData,
                    success: function (data) {
                        console.log(data)
                        if (data.status == "success") {
                            web3.personal.unlockAccount(address, "pass@123", 1000, function (err, result) {
                                web3.eth.sendTransaction({
                                    from: App.coinbase,
                                    to: address,
                                    value: web3.toWei(10, "ether")
                                }, function (err, result) {
                                    if (err == null) {
                                        console.log("sent money");
                                        console.log(result)
                                        web3.eth.getBalance(App.coinbase, function (err, balance) {
                                            if (err === null) {
                                                console.log("coinbase "+web3.fromWei(balance, "ether") + " ETH");
                                            }
                                        })
                                        web3.eth.getBalance(address, function (err, balance) {
                                            if (err === null) {
                                                console.log(web3.fromWei(balance, "ether") + " ETH");
                                            }
                                        })
                                    } else {
                                        console.log(err);
                                    }
                                    toastr.success("Success.");
                                    window.location.href = App.hostname();
                                })
                            });
                        } else {
                            toastr.error(data.data);
                        }
                        btnRegister.attr("disabled", false);
                    },
                    error: function (err) {
                        toastr.error('Error Registering');
                        btnRegister.attr("disabled", false);
                    }
                });
            } else {
                toastr.error('Error Registering');
                btnRegister.attr("disabled", false);
                return false;
            }
        })
    },
    login: function () {
        let email = $('#inputEmail');
        let password = $('#inputPassword');
        let btnLogin = $('#btnLogin');

        if (email.val() == "" || password.val() == "") {
            toastr.error('Please fill all fields');
            return false;
        }

        btnLogin.attr("disabled", 'disabled');

        let postData = {
            email: email.val(),
            password: password.val(),
        }
        $.ajax({
            method: "POST",
            url: App.hostname() + "/login",
            data: postData,
            success: function (data) {
                console.log(data)
                if (data.status == "success") {
                    toastr.success("Success.");
                    window.location.href = App.hostname();
                } else {
                    toastr.error(data.data);
                }
                btnLogin.attr("disabled", false);
            });
    }
}
排查与解决方案

我帮你梳理几个可能导致账户余额归零的原因,以及对应的解决办法:

  • --secure参数与账户解锁的冲突
    你启动Ganache时加了--secure参数,这个参数会强制所有交易必须签名,同时默认禁用账户解锁功能。虽然你用-u 0 -u 1 -u 2解锁了前三个账户,但--secure可能会覆盖或干扰这个设置,甚至在运行一段时间后重置账户状态。

    建议先去掉--secure参数重新启动Ganache,因为-u已经帮你解锁了指定账户,--secure在这里不仅多余,还可能引发异常。修改后的启动命令如下:

    ganache-cli -h "159.89.119.189" -a 3 -e "1000000000000000000000000000" -u 0 -u 1 -u 2 -s 20
    
  • 内存链状态丢失(进程意外终止)
    Ganache CLI默认是内存区块链,所有数据只存放在内存中。如果Ganache进程因为服务器资源不足(比如内存耗尽被系统杀死)、网络波动或其他意外原因终止,再重启的话会重新生成全新的账户和状态,之前的余额自然就没了。

    你可以先检查服务器上Ganache进程是否还在运行,或者查看系统日志(比如/var/log/syslog或dmesg)有没有进程被终止的记录。如果要持久化数据,加上--db参数指定一个存储目录:

    ganache-cli -h "159.89.119.189" -a 3 -e "1000000000000000000000000000" -u 0 -u 1 -u 2 -s 20 --db ./ganache-data
    

    这样即使重启Ganache,也会从指定目录加载之前的区块链数据。

  • DApp代码中的潜在问题
    看你的app.js代码,有几个细节需要修正:

    1. getBalance中的延迟调用错误:当余额为0时,你写的setTimeout(App.getBalance(), 60000);会立即执行getBalance,而不是延迟60秒执行,这会导致频繁递归调用,可能触发Ganache的限制或者消耗大量资源。应该改成:
      setTimeout(App.getBalance, 60000);
      
    2. 账户解锁的冗余操作:你在transfer和register中反复调用unlockAccount,如果Ganache的解锁状态是持久的(默认解锁是永久的,除非进程重启),多次解锁可能没必要,甚至引发异常。可以先检查账户是否已经解锁,再决定是否调用解锁函数。
    3. 交易后余额查询的时机:发送交易后立即查询余额,可能交易还没被打包上链,导致余额显示不准确。建议监听交易回执,确认交易上链后再查询余额。
  • 服务器资源限制
    如果你的服务器内存不足,Ganache作为内存链,运行一段时间后可能因为内存耗尽被系统的OOM Killer终止。你可以通过free -h命令查看服务器内存使用情况,或者检查系统日志中的OOM相关记录。如果是内存不足,建议升级服务器配置,或者限制Ganache的内存使用。

内容的提问来源于stack exchange,提问作者Dike Jude

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 07:03:25