Solidity

獲取 ParserError: Expected ‘,’ but got ‘payable’ 以及契約的一個重要安全問題

  • December 19, 2018

我為彩票系統編寫了一個小型智能合約。但是有問題。請參閱下面的完整程式碼。

pragma solidity >=0.4.22 <0.6.0;

contract Lottery{
address[] public players; //dynamic array with players addresses
address public manager; //contract manager

//contract constructor, runs once at contract deployment
constructor() public{
   //the manager is account address that deploys the contract
   manager = msg.sender; 
}

//this fallback payable function will be automatically called when 
  somebody
//sends ether to our contract address
function  ()  payable  external {
   require(msg.value >= 0.01 ether);
   players.push(msg.sender); //add the address of the account that 

                             //ether to players array
  }

function get_balance() public view returns(uint){
   require(msg.sender == manager);
   return address(this).balance; //return contract balance
}

//returns a very big pseodo-random integer no.
function random() public view returns(uint256){
return uint256(keccak256(block.difficulty, block.timestamp, 
players.length));  
}

function selectWinner() public {
   require(msg.sender == manager);


   uint r = random();

   address winner;

   //a random index
   uint index = r % players.length;
   winner = players[index];

   //transfer contract balance to the winner address
   winner.transfer(address payable(this).balance);

   players = new address[](0); //resetting the players dynamic array
}
}

我遇到了以下問題。

  1. 我收到 ParserError: Expected ‘,’ but got ‘payable’ Winner.transfer(address paid (this).balance); 線上的。
   winner.transfer(address payable(this).balance);

2)以下程式碼存在一個安全問題。它們並不是真正隨機的,因為未成年人可以修改或設置特定的時間戳。未成年人可以提前知道該難度,並且未成年人可以通過某種方式知道有多少玩家進入彩票。因此,還有其他方法可以從上述問題中確保契約的安全。

function random() public view returns(uint256){
  return uint256(keccak256(block.difficulty, block.timestamp, 
 players.length));
}

1)避免在鑄造時支付:

winner.transfer(address payable(this).balance);

必須寫成:

   winner.transfer(address(this).balance);   

因為投射到應付地址必須沒有“應付”。您的契約屬於“應付”類型,只是因為確實存在應付回退。這就夠了。參考:https ://solidity.readthedocs.io/en/v0.5.1/050-break-changes.html?highlight=Address%20payable

一般來說,如果您遇到將“地址”轉換為“應付地址”的問題,您需要通過 uint160(在這種情況下不是!):

// We can define a library for explicitly converting ``address``
// to ``address payable`` as a workaround.
library address_make_payable {
  function make_payable(address x) internal pure returns (address payable) {
 return address(uint160(x));
  }
}

2)你的隨機函式對於區塊的礦工來說根本不是隨機的,他可以通過稍微改變區塊的時間戳來操縱結果以獲得一些期望的結果。這是一個眾所周知的問題。您應該使用外部源來獲得隨機性,因為在乙太坊區塊鏈上,根據定義,沒有什麼可以被視為真正隨機的。

引用自:https://ethereum.stackexchange.com/questions/64325