// Contract: RemovePutinBounty
// Target function: function predictRemoval(bytes32 commitment) external payable
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;

/**
 * @title Remove Putin Bounty
 * @dev This contract is made to incentivize Russians to remove Putin from power by any mean necessary.
 * It is also made to incentivize Putin to stop his agression against Ukraine.
 * It is not affiliated with the state of Ukraine nor any other nation state.
 * This contract is made only as a legitimate defense mean (see a discussion on this right of legitimate defense: https://scholarship.law.cornell.edu/cgi/viewcontent.cgi?article=2562&context=facpub).
 * - The fear of harm is geniune. Putin already attacked Ukraine leading to thousands of deaths.
 * - The threat is imminent. The bounty shall be cancelled if Putin recalls its troop or if he is removed from power during a ceasefire.
 * - The response is proportional. Thousands people (in both sides) already died.
 *   One could argue that heads of state are special and "worth" more than regular citizens, we do not share this point of view, but for those who do, Putin already tried to eliminate the president of Ukraine multiple times https://www.msn.com/en-us/news/world/volodymyr-zelensky-survives-three-assassination-attempts-in-one-week/ar-AAUBwac 
 *   The bounty only targets the individual responsible.
 *   This individual is a military target: The Supreme Commander-in-Chief of the Russian Armed Forces (https://en.wikipedia.org/wiki/Supreme_Commander-in-Chief_of_the_Russian_Armed_Forces).
 *   The bounty is neutral about whether violence should be used or not (any mean to remove him from power would fullfill the bounty).
 *   The bounty provides a way out to Putin as it would be cancelled if he were to recall his troops.
 */
contract RemovePutinBounty {


    /* Owner */
    // The DAO or multisig which will report the events.
    address public owner;

    modifier isOwner() {
        require(msg.sender == owner, "Caller is not owner");
        _;
    }
    
    /**
     * @dev Set contract deployer as owner
     */
    constructor() {
        owner = msg.sender; 
    }

    /**
     * @dev Change owner
     * @param newOwner address of new owner
     */
    function changeOwner(address newOwner) public isOwner {
        owner = newOwner;
    }

    /* ERC20 */
    // Contributors get a token representing their contribution.
    // In case the bounty is cancelled (Putin recalls his troops or is removed from power during a ceasefire), those tokens can be redeemed for the ETH.
    // In case the bounty is paid out. The tokens will end up as collectibles, or maybe even used in the Guardians of the Galaxy organisation.
    event Transfer(address indexed from, address indexed to, uint value);
    event Approval(address indexed owner, address indexed spender, uint value);
    
    uint public totalSupply;
    mapping(address => uint) public balanceOf;
    mapping(address => mapping(address => uint)) public allowance;
    string public name = "Putin Bounty";
    string public symbol = "PBTY";
    uint8 public decimals = 14;

    /**
     * @dev Transfer tokens.
     * @param recipient The recipient of the tokens.
     * @param amount The amount to transfer.
     */
    function transfer(address recipient, uint amount) external returns (bool) {
        balanceOf[msg.sender] -= amount;
        balanceOf[recipient] += amount;
        emit Transfer(msg.sender, recipient, amount);
        return true;
    }

    /**
     * @dev Approve another account to spend tokens.
     * @param spender The account to be allowed the spending of tokens.
     * @param amount The amount of tokens which can be spent.
     */
    function approve(address spender, uint amount) external returns (bool) {
        allowance[msg.sender][spender] = amount;
        emit Approval(msg.sender, spender, amount);
        return true;
    }

    /**
     * @dev Transfer tokens on behalf of another account.
     * @param sender The account the tokens should be sent from.
     * @param recipient The account to receive the tokens.
     * @param amount The amount of tokens to send.
     */
    function transferFrom(
        address sender,
        address recipient,
        uint amount
    ) external returns (bool) {
        allowance[sender][msg.sender] -= amount;
        balanceOf[sender] -= amount;
        balanceOf[recipient] += amount;
        emit Transfer(sender, recipient, amount);
        return true;
    }

    /* General constants */

    uint constant public ACTION_ERROR_MARGIN = 36 hours;
    uint constant public PREDICTION_ACTIVATION = 12 hours;
    uint constant public REDEEM_TIME = 100 days;
    uint constant public REVEAL_TIME = 100 days;

    /* General state variables */
    enum State{ initial, cancelled, executed }
    State public state; // State of the contract.
    uint public executionTime; // Time the contract was executed.
    uint public cancellationTime; // Time the bounty was cancelled.
    uint public totalPredictionShares; // The amount of ETH used for correct predictions.
    mapping(address => uint) public predictionShares; // The amount of correct prediction shares an address has.
    uint public totalBounty; // The total amount of ETH as a bounty. Set when the bounty is executed.

    struct Prediction { 
        address payable predictor; // The predictor which would be paid.
        uint value; // The amount paid by the predictor.
        uint time; // The time the prediction was made. Should be at least 12h before the action.
        bytes32 commitment; // keccak256(timestamp,salt), where timestamp is the predicted time of the action and salt a random value.
    }
    Prediction[] public predictions;

    /* General functions */
    /**
     * @dev Contribute to the bounty and receive some tokens which may be redeemed to ETH if the bounty is cancelled and use in the Guardian of the Galaxy organisation.
     * Contributors may want to contribute:
     * - Making a charitable donation to stop the war.
     * - Making a charitable donation for democracy.
     * - In order to receive tokens.
     * - In order to remove Putin which is bad for their buisness (sanctions and cie).
     * - For any other reason they see fit.
     */
    receive() external payable {
        require(state == State.initial); // Can only contribute if the bounty is not cancelled nor executed.
        balanceOf[msg.sender] += msg.value;
        totalSupply += msg.value;
        emit Transfer(address(0), msg.sender, msg.value);
    }