contract Proxy {
    address etheroll;
    address micro;
    address owner;
    uint roundID = 0;

    event GotFunds(uint indexed roundID, address indexed sender, uint indexed amount);
    event SentFunds(uint indexed roundID, uint indexed amount, uint indexed rollUnder);
    event WithdrawPendingTransactionsResult(bool indexed result);

    constructor(address etherollAddress, address ownerAddress) public {
        etheroll = etherollAddress;
        owner = ownerAddress;
        micro = msg.sender;
        roundID = 0;
    }

//// Getters

    function getBalance() view external returns (uint) {
        return address(this).balance;
    }

    function getRoundID() view external returns (uint) {
        return roundID;
    }

    function getEtherollAddress() view external returns (address) {
        return etheroll;
    }


//// Secutity modifier

    modifier onlyOwner {
        require(msg.sender == owner);
        _;
    }

    modifier onlyMicro {
        require(msg.sender == micro);
        _;
    }

//// Insecure public payable fallback function

    function () external payable {
        emit GotFunds(roundID, msg.sender, msg.value);
    }

//// Sending bets and withdrawing winnings

    function sendToEtheroll(uint rollUnder, uint newRoundID) external payable
            onlyMicro
    {
        roundID = newRoundID;
        Etheroll e = Etheroll(etheroll);
        e.playerRollDice.value(msg.value)(rollUnder);
        emit SentFunds(roundID, msg.value, rollUnder);
    }

    function withdrawWinnings() external
            onlyMicro
    {
        Micro m = Micro(micro);
        m.withdrawWinnings.value(address(this).balance)();
    }

//// Owner security & maintenance functions

    function withdrawRefund() external
            onlyMicro
    {
        Micro m = Micro(micro);
        m.withdrawRefund.value(address(this).balance)();
    }
    
    function withdrawPendingTransactions() external
            onlyOwner
    {
        Etheroll e = Etheroll(etheroll);
        emit WithdrawPendingTransactionsResult(e.playerWithdrawPendingTransactions());
    }
    
    function ownerWithdraw() external
            onlyOwner
    {
        owner.transfer(address(this).balance);
    }
    
    function setEtherollAddress(address etherollAddress) external
            onlyOwner
    {
        etheroll = etherollAddress;
    }
    
}
//// Proxy contract for Micro Etheroll - providing a cheap and empty payable fallback function
function sendToEtheroll(uint rollUnder, uint newRoundID) external payable
        onlyMicro
{
    roundID = newRoundID;
    Etheroll e = Etheroll(etheroll);
    e.playerRollDice.value(msg.value)(rollUnder);
    emit SentFunds(roundID, msg.value, rollUnder);
}

//// Sending bets and withdrawing winnings