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

如何使用web3.py调用Solidity提现函数提取智能合约以太币余额?

问题结论

你当前编写的withdraw函数不能直接把合约里的以太币转到任意指定账户,该函数逻辑固定将合约余额转给调用者(被onlyOwner限制只能是合约所有者调用),资金只会转入合约所有者的地址。

下面提供两种可实现需求的方案:

方案1:修改Solidity合约,支持直接提现到任意地址

先更新合约代码,新增支持指定收款地址的提现函数,保留权限限制:

function withdrawTo(address payable _to) public payable onlyOwner {
    _to.transfer(address(this).balance);
}

重新部署合约后,web3.py调用代码如下:

booking_contract = w3.eth.contract(address=self.receipt.contractAddress, abi=abi)
# 此处必须传入合约所有者的地址
nonce = w3.eth.getTransactionCount(owner_address)
# 替换为你要转入的目标地址
target_address = "0x你指定的收款地址"
withdraw_txn = booking_contract.functions.withdrawTo(target_address).buildTransaction(
    {
        "chainId": chain_id,
        "gasPrice": w3.eth.gas_price,
        "from": owner_address,
        "nonce": nonce,
        # 此处不需要填value,value是用户向合约转钱时才需要的参数
    }
)
signed_txn = w3.eth.account.sign_transaction(withdraw_txn, private_key=owner_private_key)
txn_hash = w3.eth.send_raw_transaction(signed_txn.rawTransaction)
# 可选:等待交易上链确认
tx_receipt = w3.eth.wait_for_transaction_receipt(txn_hash)

方案2:不修改现有合约的实现方式

如果不想改动已部署的合约,分两步操作即可:

  1. 调用现有withdraw函数把合约余额全部转到合约所有者地址
  2. 从所有者地址向你指定的目标地址转对应金额的以太币

第一步:调用现有提现函数提币到所有者地址

booking_contract = w3.eth.contract(address=self.receipt.contractAddress, abi=abi)
nonce = w3.eth.getTransactionCount(owner_address)
withdraw_txn = booking_contract.functions.withdraw().buildTransaction(
    {
        "chainId": chain_id,
        "gasPrice": w3.eth.gas_price,
        "from": owner_address,
        "nonce": nonce,
    }
)
signed_txn = w3.eth.account.sign_transaction(withdraw_txn, private_key=owner_private_key)
txn_hash = w3.eth.send_raw_transaction(signed_txn.rawTransaction)
w3.eth.wait_for_transaction_receipt(txn_hash)

第二步:从所有者地址转币到指定目标地址

target_address = "0x你指定的收款地址"
# 转账金额单位为wei,以下示例是余额扣除少量gas费后全额转出,可按需修改
transfer_amount = w3.eth.get_balance(owner_address) - w3.to_wei(0.001, 'ether')
nonce = w3.eth.getTransactionCount(owner_address)
tx = {
    'nonce': nonce,
    'to': target_address,
    'value': transfer_amount,
    'gas': 21000, # ETH普通转账固定gas上限
    'gasPrice': w3.eth.gas_price,
    'chainId': chain_id
}
signed_tx = w3.eth.account.sign_transaction(tx, private_key=owner_private_key)
tx_hash = w3.eth.send_raw_transaction(signed_tx.rawTransaction)
w3.eth.wait_for_transaction_receipt(tx_hash)

注意事项

  • 所有涉及提现的操作必须使用合约所有者的私钥签名,否则会被onlyOwner修饰符拦截
  • 提现交易不需要填value字段,该字段仅在用户向合约转账时使用
  • 操作前确保合约所有者地址有足够的ETH支付gas费

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 02:27:04