3
\$\begingroup\$

I have written a Lottery contract that picks winner based on the amount they contributed to the pool. I am looking if the code of weightedWinner function can be optimized. And if there is a better way to write the random function.

pragma solidity ^0.5.12;

//import "./SafeMath.sol";

contract WeightedLottery {
    //using SafeMath for uint256;

    address public owner;
    address payable[] private players;
    mapping(address => uint256) private amounts;
    uint256 totalAmount = 0;

    constructor() public {
        owner = msg.sender;
    }

    function random() private view returns (uint) {
        return uint(keccak256(abi.encodePacked(blockhash(block.number - 1 - players.length), block.difficulty, now, players)));
    }

    function weightedWinner() private view returns(address payable) {
        require(msg.sender == owner);
        require(totalAmount != 0);
        require(players.length != 0);
        uint256 val = random() % totalAmount;
        uint256 temp = 0;
        for(uint256 i = 0; i < players.length; i++) {
            temp += amounts[players[i]];
            if(val < temp) {
                return players[i];
            }
        }
        return address(0x0);
    }

    function getPlayers() public view returns(address payable[] memory) {
        return players;
    }

    function join() payable public {
        require(msg.sender != owner);
        require(msg.value != 0);
        if(amounts[msg.sender] == 0) {
            players.push(msg.sender);
        }
        amounts[msg.sender] += msg.value;
        totalAmount += msg.value;
    }

    function pickWinner() public {
        address payable winner = weightedWinner();
        require(winner != address(0x0));
        winner.transfer(totalAmount);
    }
}

How it works

Players join with an initial amount of tokens. Later s/he can increase the amount. When pickWinner is called, player with the highest amount has the height probability of winning.

Example:

  1. player 1 joins with 10 tokens.
  2. player 2 joins with 10 tokens.
  3. player 1 adds 10 tokens.
  4. player 3 joins with 10 tokens.
  5. player 3 adds 10 tokens.
  6. pickWinner is called.

Now we have player 1 and 3 with 20 tokens and 2 has 10 tokens. So player 1 and 3 has (20/50) probability of winning and player 2 has (10/50) probability.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.