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

Brownie主网分叉存入WETH到Aave报SafeMath减法溢出错误

根因分析

这个报错本质是合约执行SafeMath安全减法时,被减数小于减数触发的链上回滚,结合代码逻辑和环境配置,共有两个核心问题:

  • 操作账户不匹配:代码中主网分叉分支的get_weth()调用未指定发送账户,默认使用Brownie加载的索引为0的测试账户兑换了0.1 WETH,但后续授权、存款操作使用的是get_account(1)拿到的索引为1的账户,该账户实际WETH余额为0。

    注意:ERC20的approve授权操作不会校验调用者的代币余额,哪怕持有0枚代币也可以成功给其他地址授权任意额度,因此授权步骤不会报错;只有借贷池调用transferFrom实际转走WETH时,WETH合约会执行用户余额 = 用户余额 - 转账金额的逻辑,0减0.1ETH对应的数值就会触发SafeMath减法溢出。

  • 分叉环境硬分叉版本配置错误:启动ganache-cli时指定了--hardfork istanbul,该硬分叉是2019年上线的旧版本,主网Aave V2协议2020年底才部署,依赖更高版本的EVM特性,旧硬分叉环境下执行新合约逻辑会出现异常。
    Kovan测试网脚本可正常运行,是因为测试网逻辑中get_weth()传入了正确的操作账户,且测试网节点的硬分叉版本和合约版本匹配。
修复方案

1. 修正ganache分叉启动命令

去掉过时的istanbul硬分叉指定,让ganache自动匹配fork区块对应的EVM版本,修改后的启动命令如下:

ganache-cli.cmd --accounts 10 --fork https://eth-mainnet.alchemyapi.io/v2/_Z-H35Cw4-kIaLun7L14IU92c1AcDNYx --mnemonic brownie --port 8545

如果需要手动指定硬分叉版本,使用--hardfork london即可兼容当前主网Aave合约逻辑。

2. 修正业务代码逻辑

核心是保证兑换WETH、授权、存款三个操作使用同一个账户,同时补上原代码缺失的依赖导入、增加余额校验提前发现问题,修正后的完整代码如下:

from scripts.helpful_scripts import get_account
from scripts.get_weth import get_weth
from brownie import network, config, interface
from web3 import Web3

AMOUNT = Web3.toWei(0.1, "ether")

def main():
    account = get_account(1)
    erc20_address = config["networks"][network.show_active()]["weth_token"]
    if network.show_active() in ["mainnet-fork"]:
        # 修复:指定用当前操作账户兑换WETH,保证WETH到账到正确地址
        get_weth(account=account)
    lending_pool = get_lending_pool()

    # 增加余额前置校验,提前排查配置问题
    weth_contract = interface.IERC20(erc20_address)
    balance = weth_contract.balanceOf(account.address)
    print(f"当前账户WETH余额: {Web3.fromWei(balance, 'ether')} WETH")
    assert balance >= AMOUNT, "账户WETH余额不足,无法执行存款"

    approve_erc20_tokens(AMOUNT, lending_pool.address, erc20_address, account)

    print("Depositing !!!")
    tx = lending_pool.deposit(erc20_address, AMOUNT, account.address, 0, {"from": account})
    tx.wait(1)
    print("Deposited !!!")

def approve_erc20_tokens(amount, spender, erc20_address, account):
    print("Approving ERC20 token !!!")
    erc20 = interface.IERC20(erc20_address)
    tx = erc20.approve(spender, amount, {"from": account})
    tx.wait(1)
    print("Approved !!!")
    return tx

def get_lending_pool():
    lending_pool_addresses_provider = interface.ILendingPoolAddressesProvider(config["networks"][network.show_active()]["lending_pool_addresses_provider"])
    lending_pool_address = lending_pool_addresses_provider.getLendingPool()
    lending_pool = interface.ILendingPool(lending_pool_address)
    return lending_pool

注意:需要确认你的get_weth函数支持接收account参数,如果原函数没有该入参,给函数加上即可,核心逻辑是调用WETH合约的deposit方法发送0.1ETH时,{"from": account}指定为当前操作账户。

3. 验证修复

重新启动ganache分叉环境,执行脚本即可正常完成WETH存入Aave借贷池的全流程,不会再触发SafeMath溢出报错。

内容的提问来源于stack exchange,提问作者aman pal

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 01:12:26