如何调用 Solidity 函数从智能合约中返回以太币?

Posted

技术标签:

【中文标题】如何调用 Solidity 函数从智能合约中返回以太币?【英文标题】:How to call Solidity Function to return Ether from Smart Contract? 【发布时间】:2021-09-02 23:26:46 【问题描述】:

我已经在本地 truffle 项目上部署了一个智能合约,我正在尝试在一个使用 web3 的 React 项目中与之交互。下面的solidity函数应该将之前存放在合约中的以太币发送到布尔条件下的用户地址:

     function Payout() public

            require( voteEndTime< block.timestamp, "Voting Time is not up. Please come back later" );
            Voter storage sender = voters[msg.sender];

                if (negativeVotes > positiveVotes)
                    require(!sender.option, "Wrong Vote. Stake is distributed among winners");
                    payable(address(msg.sender)).transfer((stakes*sender.amount) / negativeStakes);
                    

                else if (positiveVotes > negativeVotes)
                    require(sender.option, "Wrong Vote. Stake is distributed among winners");
                    payable(address(msg.sender)).transfer((stakes*sender.amount) / positiveStakes);
                

                else
                    payable(address(msg.sender)).transfer((stakes*sender.amount) / stakes);
                
            

合约肯定能够使用msg.sender 读取用户的地址,因为它已经在我拥有的其他功能中工作。合同中的所有其他功能也都可以正常工作。我可以与它交互,我可以向它发送以太币。当我试图将存储在合约中的以太币返还给账户时,就会出现问题。我正在尝试在 React on button click 中使用以下 web3 调用来调用我的 Payout() 函数:

    var response = await BallotContract.methods.Payout().send( from: account, gas: 310000 )

我已经指定了更高的 gas 限制,因为如果我尝试使用下面看到的 gas 估算,合约就会用尽 gas。此调用所在的函数如下所示:

     const giveMeMoney = async (e) => 
        const web3 = await new Web3(window.ethereum);
        await window.ethereum.enable();
        
        var Accounts = await web3.eth.getAccounts() 
            account = Accounts[0]
            console.log(account)
    
          const gas = await BallotContract.methods.Payout().estimateGas();
          console.log(gas)
          
          var response = await BallotContract.methods.Payout().send( from: account, gas: 310000 )

    
      

我可以从前端访问该函数,如果不满足“要求”条件,它会返回正确的字符串。我的问题是,如果满足条件并且这一行,合同不会返回任何以太币:

    payable(address(msg.sender)).transfer((stakes*sender.amount) / positiveStakes);

...被访问。我收到以下错误:

    Uncaught (in promise) Error: Returned error: VM Exception while processing transaction: revert
        at Object.ErrorResponse (errors.js:30)
        at onJsonrpcResult (index.js:162)
        at XMLHttpRequest.request.onreadystatechange (index.js:123)
    ErrorResponse   @   errors.js:30

现在我不确定可能是什么问题,因为如果我在 Remix 中测试合约,它运行得非常好。有没有人发现问题或有解决此类问题的方法?

【问题讨论】:

【参考方案1】:

“out of gas”错误是由transfer 函数引起的。该函数的gas限制为2100;我推荐你使用call,你可以查看here。

Voter 结构的布尔值也默认为false。所以如果反对票获胜,但用户没有投票,他们仍然可以尝试领取奖励,即使金额为 0。我建议你检查如何使用 enum,它会非常有用。

【讨论】:

以上是关于如何调用 Solidity 函数从智能合约中返回以太币?的主要内容,如果未能解决你的问题,请参考以下文章

以太坊智能合约语言Solidity - 5 函数

Solidity 学习

智能合约从入门到精通:调用数据的布局和ABI

Eth,如何从智能合约中调用存款功能

执行智能合约时的 Solidity 错误消息:“如果您发送价值,则应支付被调用的函数......”

solidity编写智能合约遇到的各种问题