关于我创建的智能合约的几个问题(刚刚开始学习)

Few questions about smart contract I created (just start learning)

我刚开始学习 solidity,对我为 pratice/fun 创建的智能合约有一些疑问。 如果我的任何概念不准确,请告诉我,感谢所有的意见和建议。

描述:

这个智能合约的概念非常简单,谁向合约中发送更多的以太币,谁就获胜,它将把你和你之前的人配对(如果没有人在你之前,你就是 player_one) 并且会在 2 个播放器播放后重置(因此可以再次播放)

代码:

contract zero_one {

address public player_one;
address public player_two;
uint public player_one_amount;
uint public player_two_amount;


function zero_one() public{
    reset();
}

function play() public payable{
    //Scenario #1 Already have two player in game, dont accpet new player. do I even need this check at all? since smart contract execute serially i should never face this condition?
    if(player_one != address(0) && player_two != address(0)) throw;

    //Scenario #2 First player enter the game
    else if(player_one == address(0) && player_two == address(0)){
        player_one=msg.sender;
        player_one_amount = msg.value;
    }

    //Scenario #3 Second player join in, execute the game
    else{
        player_two = msg.sender;
        player_two_amount = msg.value;

        //check the amount send from player_one and player two,  whoever has the bigger amount win and get their money 
        if(player_two_amount>player_one_amount){
            player_one.transfer(player_one_amount+player_two_amount);
            reset();
        }
        else if(player_two_amount<player_one_amount){
            player_two.transfer(player_one_amount+player_two_amount);
            reset();
        }
        else{
            //return fund back to both player
            player_one.transfer(player_one_amount);
            player_two.transfer(player_two_amount);
            reset();
        }
    }
}

function reset() internal{
    player_one = address(0);
    player_two = address(0);
    player_one_amount = 0;
    player_two_amount = 0;
}
}

问题

谢谢!

When sending ether back to users, do I need to calcualate how much gas is going to take? or would smart contract automatically deduct the gas from the amount i am going to send

执行交易时指定的gas limit需要覆盖所有activity端到端。这包括调用其他合约、转账等。在交易被开采后未使用的任何 gas returned 给你。

Is it correct to set reset() as interal since i only want it to be called within the smart contract, it shouldn't be called by anyone else

internal 很适合您打算做的事情。但是,它更像是 protected 访问。一个子合约可以调用 internal 方法。 private 提供最严格的可见性。

Would Scenario#1 ever happen? since from what I understand smart contract do not have to worry about race condition and it should never be in that state?

不,这不应该发生。你是正确的,事务是串行处理的,所以你真的不必担心竞争条件。这并不意味着您的代码中不应该有这种保护...

Is adding playable to play correct? ( since user are going to send ether with this call)

是的。任何期望接收 wei 并使用 msg.value 的方法都需要标记为 payable.

Is using throw a bad practice? (warning on remix)

throw 已弃用。从 0.4.13 开始,您想使用 revertrequireassert 之一。您使用的支票类型取决于您进行的支票类型以及是否应退还汽油。有关详细信息,请参阅 this

transfer vs send, why is it better to use transfer?

sendtransfer是相似的。不同之处在于 send 限制了发送给调用的 gas 量,因此如果接收合约试图执行任何逻辑,它很可能 运行 耗尽 gas 并失败。此外,send 期间的失败不会传播错误,而只是 return falseSource

I coded this smart contract as a practice. I can already see that if someone want to game the system, he could just wait for someone to be player_one and check the amount player_one send(after the block is mined) and just send a bigger sum than that. Is there anyway this exploit could be stopped? Is there other security/flaws I did not see?

安全是一个更深入的话题。交易中发送的任何数据都是可见的,因此除非您使用私有区块链,否则您无法隐藏您提到的漏洞。你可以自己加密交易中发送的数据,但我不相信你可以加密发送以太币。

就其他安全问题而言,有几种工具可以对合约执行安全检查。我建议调查其中一个。此外,请通读 Solidity 文档中的 security considerations 页面。