web3调用合约提取ETH为何需用send方法且用户支付Gas费?
问题1:为什么提现操作使用call方法会失败,必须使用send方法?
web3.js中call()和send()的核心定位不同,决定了二者的适用场景:
call()是只读状态调用,仅在本地节点模拟执行合约逻辑,不会将交易广播到链上,也永远不会修改链上的任何状态数据,执行过程不需要支付Gas。你的提现函数withDraw包含两个修改链上状态的操作:向目标地址转账Ether、清空对应地址的存款记账变量accounts[receiver],这两个操作都需要链上全网共识确认,用call()执行只会在本地模拟运行,不会触发实际的链上状态变更和转账,自然无法完成提现。send()是上链交易调用,会将你的操作作为交易广播到以太坊网络,由矿工打包执行并同步到全网所有节点,只有用send()才能真正触发合约的状态修改逻辑,完成Ether转账和记账清零的操作。
问题2:为什么从合约提取自有Ether也需要用户支付Gas费,而非由合约承担Gas成本?
这是以太坊底层协议的规则决定的:
- 所有需要修改链上状态的交易,都必须由交易的发起方(也就是你调用
send()时指定的from地址)支付Gas。Gas是给矿工的酬劳,用于覆盖矿工打包、验证、执行交易的计算资源成本,只要交易需要上链共识,就必须支付Gas,和交易的业务逻辑是存币还是提币无关。 - 合约账户本身没有主动发起交易的能力,所有合约代码的执行都必须由外部账户(用户持有的钱包地址)发起交易触发,不存在合约主动给你转币的情况,你发起的提现交易就是触发合约执行转账逻辑的入口,你作为交易发起方自然需要承担Gas成本。
- 以太坊协议规定Gas只能从交易发起方的账户余额中直接扣除,无法从合约的余额里抵扣,哪怕你提的是自己存在合约里的资产,也不能用合约里的Ether来支付这笔交易的Gas。
内容的提问来源于stack exchange,提问作者SYED IMAM
相关产品推荐
相关产品推荐

