ETH Price: $2,258.01 (-0.59%)

Transaction Decoder

Block:
8744753 at Oct-15-2019 08:18:16 AM +UTC
Transaction Fee:
0.000193554 ETH $0.44
Gas Used:
193,554 Gas / 1 Gwei

Account State Difference:

  Address   Before After State Difference Code
0x331769dE...9159aB13a 13.369561129847708667 Eth13.370561129847708667 Eth0.001
0xA6D93468...3147117b3 41.761450000000000001 Eth41.762450000000000001 Eth0.001
0xac7eB194...04d36dF3e
0.350817867971028525 Eth
Nonce: 502
0.340624313971028525 Eth
Nonce: 503
0.010193554
0xb9846a7D...2febDb0A2 8.570835555555555884 Eth8.578835555555555884 Eth0.008
(Ethermine)
478.574740310203402764 Eth478.574933864203402764 Eth0.000193554

Execution Trace

ETH 0.01 EthexLoto.placeBet( params=System.Byte[] )
  • ETH 0.001 EthexHouse.CALL( )
  • ETH 0.001 EthexJackpot.CALL( )
    File 1 of 3: EthexLoto
    {"DeliverFunds.sol":{"content":"pragma solidity 0.5.10;\r\n\r\ncontract DeliverFunds {\r\n    constructor(address payable target) public payable {\r\n        selfdestruct(target);\r\n    }\r\n}"},"EthexHouse.sol":{"content":"pragma solidity ^0.5.0;\r\n\r\n/**\r\n * (E)t)h)e)x) House Contract \r\n *  This smart-contract is the part of Ethex Lottery fair game.\r\n *  See latest version at https://github.com/ethex-bet/ethex-lottery \r\n *  http://ethex.bet\r\n */\r\n \r\n contract EthexHouse {\r\n     address payable private owner;\r\n     \r\n     constructor() public {\r\n         owner = msg.sender;\r\n     }\r\n     \r\n     modifier onlyOwner {\r\n        require(msg.sender == owner);\r\n        _;\r\n    }\r\n    \r\n    function payIn() external payable {\r\n    }\r\n    \r\n    function withdraw() external onlyOwner {\r\n        owner.transfer(address(this).balance);\r\n    }\r\n }"},"EthexJackpot.sol":{"content":"pragma solidity ^0.5.0;\r\n\r\n/**\r\n * (E)t)h)e)x) Jackpot Contract \r\n *  This smart-contract is the part of Ethex Lottery fair game.\r\n *  See latest version at https://github.com/ethex-bet/ethex-contracts \r\n *  http://ethex.bet\r\n */\r\n\r\ncontract EthexJackpot {\r\n    mapping(uint256 =\u003e address payable) public tickets;\r\n    uint256 public numberEnd;\r\n    uint256 public firstNumber;\r\n    uint256 public dailyAmount;\r\n    uint256 public weeklyAmount;\r\n    uint256 public monthlyAmount;\r\n    uint256 public seasonalAmount;\r\n    bool public dailyProcessed;\r\n    bool public weeklyProcessed;\r\n    bool public monthlyProcessed;\r\n    bool public seasonalProcessed;\r\n    address payable private owner;\r\n    address public lotoAddress;\r\n    address payable public newVersionAddress;\r\n    EthexJackpot previousContract;\r\n    uint256 public dailyNumberStartPrev;\r\n    uint256 public weeklyNumberStartPrev;\r\n    uint256 public monthlyNumberStartPrev;\r\n    uint256 public seasonalNumberStartPrev;\r\n    uint256 public dailyStart;\r\n    uint256 public weeklyStart;\r\n    uint256 public monthlyStart;\r\n    uint256 public seasonalStart;\r\n    uint256 public dailyEnd;\r\n    uint256 public weeklyEnd;\r\n    uint256 public monthlyEnd;\r\n    uint256 public seasonalEnd;\r\n    uint256 public dailyNumberStart;\r\n    uint256 public weeklyNumberStart;\r\n    uint256 public monthlyNumberStart;\r\n    uint256 public seasonalNumberStart;\r\n    uint256 public dailyNumberEndPrev;\r\n    uint256 public weeklyNumberEndPrev;\r\n    uint256 public monthlyNumberEndPrev;\r\n    uint256 public seasonalNumberEndPrev;\r\n    \r\n    event Jackpot (\r\n        uint256 number,\r\n        uint256 count,\r\n        uint256 amount,\r\n        byte jackpotType\r\n    );\r\n    \r\n    event Ticket (\r\n        bytes16 indexed id,\r\n        uint256 number\r\n    );\r\n    \r\n    event SuperPrize (\r\n        uint256 amount,\r\n        address winner\r\n    );\r\n    \r\n    uint256 constant DAILY = 5000;\r\n    uint256 constant WEEKLY = 35000;\r\n    uint256 constant MONTHLY = 150000;\r\n    uint256 constant SEASONAL = 450000;\r\n    uint256 constant PRECISION = 1 ether;\r\n    uint256 constant DAILY_PART = 84;\r\n    uint256 constant WEEKLY_PART = 12;\r\n    uint256 constant MONTHLY_PART = 3;\r\n    \r\n    constructor() public payable {\r\n        owner = msg.sender;\r\n    }\r\n    \r\n    function() external payable { }\r\n\r\n    modifier onlyOwner {\r\n        require(msg.sender == owner);\r\n        _;\r\n    }\r\n    \r\n    modifier onlyOwnerOrNewVersion {\r\n        require(msg.sender == owner || msg.sender == newVersionAddress);\r\n        _;\r\n    }\r\n    \r\n    modifier onlyLoto {\r\n        require(msg.sender == lotoAddress, \"Loto only\");\r\n        _;\r\n    }\r\n    \r\n    function migrate() external onlyOwnerOrNewVersion {\r\n        newVersionAddress.transfer(address(this).balance);\r\n    }\r\n\r\n    function registerTicket(bytes16 id, address payable gamer) external onlyLoto {\r\n        uint256 number = numberEnd + 1;\r\n        if (block.number \u003e= dailyEnd) {\r\n            setDaily();\r\n            dailyNumberStart = number;\r\n        }\r\n        else\r\n            if (dailyNumberStart == dailyNumberStartPrev)\r\n                dailyNumberStart = number;\r\n        if (block.number \u003e= weeklyEnd) {\r\n            setWeekly();\r\n            weeklyNumberStart = number;\r\n        }\r\n        else\r\n            if (weeklyNumberStart == weeklyNumberStartPrev)\r\n                weeklyNumberStart = number;\r\n        if (block.number \u003e= monthlyEnd) {\r\n            setMonthly();\r\n            monthlyNumberStart = number;\r\n        }\r\n        else\r\n            if (monthlyNumberStart == monthlyNumberStartPrev)\r\n                monthlyNumberStart = number;\r\n        if (block.number \u003e= seasonalEnd) {\r\n            setSeasonal();\r\n            seasonalNumberStart = number;\r\n        }\r\n        else\r\n            if (seasonalNumberStart == seasonalNumberStartPrev)\r\n                seasonalNumberStart = number;\r\n        numberEnd = number;\r\n        tickets[number] = gamer;\r\n        emit Ticket(id, number);\r\n    }\r\n    \r\n    function setLoto(address loto) external onlyOwner {\r\n        lotoAddress = loto;\r\n    }\r\n    \r\n    function setNewVersion(address payable newVersion) external onlyOwner {\r\n        newVersionAddress = newVersion;\r\n    }\r\n    \r\n    function payIn() external payable {\r\n        uint256 distributedAmount = dailyAmount + weeklyAmount + monthlyAmount + seasonalAmount;\r\n        if (distributedAmount \u003c address(this).balance) {\r\n            uint256 amount = (address(this).balance - distributedAmount) / 4;\r\n            dailyAmount += amount;\r\n            weeklyAmount += amount;\r\n            monthlyAmount += amount;\r\n            seasonalAmount += amount;\r\n        }\r\n    }\r\n    \r\n    function settleJackpot() external {\r\n        if (block.number \u003e= dailyEnd)\r\n            setDaily();\r\n        if (block.number \u003e= weeklyEnd)\r\n            setWeekly();\r\n        if (block.number \u003e= monthlyEnd)\r\n            setMonthly();\r\n        if (block.number \u003e= seasonalEnd)\r\n            setSeasonal();\r\n        \r\n        if (block.number == dailyStart || (dailyStart \u003c block.number - 256))\r\n            return;\r\n        \r\n        uint48 modulo = uint48(bytes6(blockhash(dailyStart) \u003c\u003c 29));\r\n        \r\n        uint256 dailyPayAmount;\r\n        uint256 weeklyPayAmount;\r\n        uint256 monthlyPayAmount;\r\n        uint256 seasonalPayAmount;\r\n        uint256 dailyWin;\r\n        uint256 weeklyWin;\r\n        uint256 monthlyWin;\r\n        uint256 seasonalWin;\r\n        if (dailyProcessed == false) {\r\n            dailyPayAmount = dailyAmount * PRECISION / DAILY_PART / PRECISION;\r\n            dailyAmount -= dailyPayAmount;\r\n            dailyProcessed = true;\r\n            dailyWin = getNumber(dailyNumberStartPrev, dailyNumberEndPrev, modulo);\r\n            emit Jackpot(dailyWin, dailyNumberEndPrev - dailyNumberStartPrev + 1, dailyPayAmount, 0x01);\r\n        }\r\n        if (weeklyProcessed == false) {\r\n            weeklyPayAmount = weeklyAmount * PRECISION / WEEKLY_PART / PRECISION;\r\n            weeklyAmount -= weeklyPayAmount;\r\n            weeklyProcessed = true;\r\n            weeklyWin = getNumber(weeklyNumberStartPrev, weeklyNumberEndPrev, modulo);\r\n            emit Jackpot(weeklyWin, weeklyNumberEndPrev - weeklyNumberStartPrev + 1, weeklyPayAmount, 0x02);\r\n        }\r\n        if (monthlyProcessed == false) {\r\n            monthlyPayAmount = monthlyAmount * PRECISION / MONTHLY_PART / PRECISION;\r\n            monthlyAmount -= monthlyPayAmount;\r\n            monthlyProcessed = true;\r\n            monthlyWin = getNumber(monthlyNumberStartPrev, monthlyNumberEndPrev, modulo);\r\n            emit Jackpot(monthlyWin, monthlyNumberEndPrev - monthlyNumberStartPrev + 1, monthlyPayAmount, 0x04);\r\n        }\r\n        if (seasonalProcessed == false) {\r\n            seasonalPayAmount = seasonalAmount;\r\n            seasonalAmount -= seasonalPayAmount;\r\n            seasonalProcessed = true;\r\n            seasonalWin = getNumber(seasonalNumberStartPrev, seasonalNumberEndPrev, modulo);\r\n            emit Jackpot(seasonalWin, seasonalNumberEndPrev - seasonalNumberStartPrev + 1, seasonalPayAmount, 0x08);\r\n        }\r\n        if (dailyPayAmount \u003e 0)\r\n            getAddress(dailyWin).transfer(dailyPayAmount);\r\n        if (weeklyPayAmount \u003e 0)\r\n            getAddress(weeklyWin).transfer(weeklyPayAmount);\r\n        if (monthlyPayAmount \u003e 0)\r\n            getAddress(monthlyWin).transfer(monthlyPayAmount);\r\n        if (seasonalPayAmount \u003e 0)\r\n            getAddress(seasonalWin).transfer(seasonalPayAmount);\r\n    }\r\n\r\n    function paySuperPrize(address payable winner) external onlyLoto {\r\n        uint256 superPrizeAmount = dailyAmount + weeklyAmount + monthlyAmount + seasonalAmount;\r\n        dailyAmount = 0;\r\n        weeklyAmount = 0;\r\n        monthlyAmount = 0;\r\n        seasonalAmount = 0;\r\n        emit SuperPrize(superPrizeAmount, winner);\r\n        winner.transfer(superPrizeAmount);\r\n    }\r\n    \r\n    function setOldVersion(address payable oldAddress) external onlyOwner {\r\n        previousContract = EthexJackpot(oldAddress);\r\n        dailyStart = previousContract.dailyStart();\r\n        dailyEnd = previousContract.dailyEnd();\r\n        dailyProcessed = previousContract.dailyProcessed();\r\n        weeklyStart = previousContract.weeklyStart();\r\n        weeklyEnd = previousContract.weeklyEnd();\r\n        weeklyProcessed = previousContract.weeklyProcessed();\r\n        monthlyStart = previousContract.monthlyStart();\r\n        monthlyEnd = previousContract.monthlyEnd();\r\n        monthlyProcessed = previousContract.monthlyProcessed();\r\n        seasonalStart = previousContract.seasonalStart();\r\n        seasonalEnd = previousContract.seasonalEnd();\r\n        seasonalProcessed = previousContract.seasonalProcessed();\r\n        dailyNumberStartPrev = previousContract.dailyNumberStartPrev();\r\n        weeklyNumberStartPrev = previousContract.weeklyNumberStartPrev();\r\n        monthlyNumberStartPrev = previousContract.monthlyNumberStartPrev();\r\n        seasonalNumberStartPrev = previousContract.seasonalNumberStartPrev();\r\n        dailyNumberStart = previousContract.dailyNumberStart();\r\n        weeklyNumberStart = previousContract.weeklyNumberStart();\r\n        monthlyNumberStart = previousContract.monthlyNumberStart();\r\n        seasonalNumberStart = previousContract.seasonalNumberStart();\r\n        dailyNumberEndPrev = previousContract.dailyNumberEndPrev();\r\n        weeklyNumberEndPrev = previousContract.weeklyNumberEndPrev();\r\n        monthlyNumberEndPrev = previousContract.monthlyNumberEndPrev();\r\n        seasonalNumberEndPrev = previousContract.seasonalNumberEndPrev();\r\n        numberEnd = previousContract.numberEnd();\r\n        dailyAmount = previousContract.dailyAmount();\r\n        weeklyAmount = previousContract.weeklyAmount();\r\n        monthlyAmount = previousContract.monthlyAmount();\r\n        seasonalAmount = previousContract.seasonalAmount();\r\n        firstNumber = weeklyNumberStart;\r\n        for (uint256 i = firstNumber; i \u003c= numberEnd; i++)\r\n            tickets[i] = previousContract.getAddress(i);\r\n        previousContract.migrate();\r\n    }\r\n    \r\n    function getAddress(uint256 number) public returns (address payable) {\r\n        if (number \u003c= firstNumber)\r\n            return previousContract.getAddress(number);\r\n        return tickets[number];\r\n    }\r\n    \r\n    function setDaily() private {\r\n        dailyProcessed = dailyNumberEndPrev == numberEnd;\r\n        dailyStart = dailyEnd;\r\n        dailyEnd = dailyStart + DAILY;\r\n        dailyNumberStartPrev = dailyNumberStart;\r\n        dailyNumberEndPrev = numberEnd;\r\n    }\r\n    \r\n    function setWeekly() private {\r\n        weeklyProcessed = weeklyNumberEndPrev == numberEnd;\r\n        weeklyStart = weeklyEnd;\r\n        weeklyEnd = weeklyStart + WEEKLY;\r\n        weeklyNumberStartPrev = weeklyNumberStart;\r\n        weeklyNumberEndPrev = numberEnd;\r\n    }\r\n    \r\n    function setMonthly() private {\r\n        monthlyProcessed = monthlyNumberEndPrev == numberEnd;\r\n        monthlyStart = monthlyEnd;\r\n        monthlyEnd = monthlyStart + MONTHLY;\r\n        monthlyNumberStartPrev = monthlyNumberStart;\r\n        monthlyNumberEndPrev = numberEnd;\r\n    }\r\n    \r\n    function setSeasonal() private {\r\n        seasonalProcessed = seasonalNumberEndPrev == numberEnd;\r\n        seasonalStart = seasonalEnd;\r\n        seasonalEnd = seasonalStart + SEASONAL;\r\n        seasonalNumberStartPrev = seasonalNumberStart;\r\n        seasonalNumberEndPrev = numberEnd;\r\n    }\r\n    \r\n    function getNumber(uint256 startNumber, uint256 endNumber, uint48 modulo) pure private returns (uint256) {\r\n        return startNumber + modulo % (endNumber - startNumber + 1);\r\n    }\r\n}"},"EthexLoto.sol":{"content":"pragma solidity 0.5.10;\r\n\r\n/**\r\n * (E)t)h)e)x) Loto Contract \r\n *  This smart-contract is the part of Ethex Lottery fair game.\r\n *  See latest version at https://github.com/ethex-bet/ethex-contacts \r\n *  http://ethex.bet\r\n */\r\n\r\nimport \"./EthexJackpot.sol\";\r\nimport \"./EthexHouse.sol\";\r\nimport \"./EthexSuperprize.sol\";\r\nimport \"./DeliverFunds.sol\";\r\n\r\ncontract EthexLoto {\r\n    struct Bet {\r\n        uint256 blockNumber;\r\n        uint256 amount;\r\n        bytes16 id;\r\n        bytes6 bet;\r\n        address payable gamer;\r\n    }\r\n    \r\n    struct Transaction {\r\n        uint256 amount;\r\n        address payable gamer;\r\n    }\r\n    \r\n    struct Superprize {\r\n        uint256 amount;\r\n        bytes16 id;\r\n    }\r\n    \r\n    mapping(uint256 =\u003e uint256) public blockNumberQueue;\r\n    mapping(uint256 =\u003e uint256) public amountQueue;\r\n    mapping(uint256 =\u003e bytes16) public idQueue;\r\n    mapping(uint256 =\u003e bytes6) public betQueue;\r\n    mapping(uint256 =\u003e address payable) public gamerQueue;\r\n    uint256 public first = 2;\r\n    uint256 public last = 1;\r\n    uint256 public holdBalance;\r\n    \r\n    address payable public jackpotAddress;\r\n    address payable public houseAddress;\r\n    address payable public superprizeAddress;\r\n    address payable private owner;\r\n\r\n    event PayoutBet (\r\n        uint256 amount,\r\n        bytes16 id,\r\n        address gamer\r\n    );\r\n    \r\n    event RefundBet (\r\n        uint256 amount,\r\n        bytes16 id,\r\n        address gamer\r\n    );\r\n    \r\n    uint256 constant MIN_BET = 0.01 ether;\r\n    uint256 constant PRECISION = 1 ether;\r\n    uint256 constant JACKPOT_PERCENT = 10;\r\n    uint256 constant HOUSE_EDGE = 10;\r\n    \r\n    constructor(address payable jackpot, address payable house, address payable superprize) public payable {\r\n        owner = msg.sender;\r\n        jackpotAddress = jackpot;\r\n        houseAddress = house;\r\n        superprizeAddress = superprize;\r\n    }\r\n    \r\n    function() external payable { }\r\n    \r\n    modifier onlyOwner {\r\n        require(msg.sender == owner);\r\n        _;\r\n    }\r\n    \r\n    function placeBet(bytes22 params) external payable {\r\n        require(tx.origin == msg.sender);\r\n        require(msg.value \u003e= MIN_BET, \"Bet amount should be greater or equal than minimal amount\");\r\n        require(bytes16(params) != 0, \"Id should not be 0\");\r\n        \r\n        bytes16 id = bytes16(params);\r\n        bytes6 bet = bytes6(params \u003c\u003c 128);\r\n        \r\n        uint256 coefficient;\r\n        uint8 markedCount;\r\n        uint256 holdAmount;\r\n        uint256 jackpotFee = msg.value * JACKPOT_PERCENT * PRECISION / 100 / PRECISION;\r\n        uint256 houseEdgeFee = msg.value * HOUSE_EDGE * PRECISION / 100 / PRECISION;\r\n        uint256 betAmount = msg.value - jackpotFee - houseEdgeFee;\r\n        \r\n        (coefficient, markedCount, holdAmount) = getHold(betAmount, bet);\r\n        \r\n        require(msg.value * (100 - JACKPOT_PERCENT - HOUSE_EDGE) * (coefficient * 8 - 15 * markedCount) \u003c= 9000 ether * markedCount);\r\n        \r\n        require(\r\n            msg.value * (800 * coefficient - (JACKPOT_PERCENT + HOUSE_EDGE) * (coefficient * 8 + 15 * markedCount)) \u003c= 1500 * markedCount * (address(this).balance - holdBalance));\r\n        \r\n        holdBalance += holdAmount;\r\n        \r\n        enqueue(block.number, betAmount, id, bet, msg.sender);\r\n        \r\n        if (markedCount \u003e 1)\r\n            EthexJackpot(jackpotAddress).registerTicket(id, msg.sender);\r\n        \r\n        EthexHouse(houseAddress).payIn.value(houseEdgeFee)();\r\n        EthexJackpot(jackpotAddress).payIn.value(jackpotFee)();\r\n    }\r\n    \r\n    function settleBets() external {\r\n        if (first \u003e last)\r\n            return;\r\n        uint256 i = 0;\r\n        uint256 length = last - first + 1;\r\n        length = length \u003e 10 ? 10 : length;\r\n        Transaction[] memory transactions = new Transaction[](length);\r\n        Superprize[] memory superprizes = new Superprize[](length);\r\n        uint256 balance = address(this).balance - holdBalance;\r\n        \r\n        for(; i \u003c length; i++) {\r\n            if (blockNumberQueue[first] \u003e= block.number) {\r\n                length = i;\r\n                break;\r\n            }\r\n            else {\r\n                Bet memory bet = dequeue();\r\n                uint256 coefficient = 0;\r\n                uint8 markedCount = 0;\r\n                uint256 holdAmount = 0;\r\n                (coefficient, markedCount, holdAmount) = getHold(bet.amount, bet.bet);\r\n                holdBalance -= holdAmount;\r\n                balance += holdAmount;\r\n                if (bet.blockNumber \u003c block.number - 256) {\r\n                    transactions[i] = Transaction(bet.amount, bet.gamer);\r\n                    emit RefundBet(bet.amount, bet.id, bet.gamer);\r\n                    balance -= bet.amount;\r\n                }\r\n                else {\r\n                    bytes32 blockHash = blockhash(bet.blockNumber);\r\n                    coefficient = 0;\r\n                    uint8 matchesCount;\r\n                    bool isSuperPrize = true;\r\n                    for (uint8 j = 0; j \u003c bet.bet.length; j++) {\r\n                        if (bet.bet[j] \u003e 0x13) {\r\n                            isSuperPrize = false;\r\n                            continue;\r\n                        }\r\n                        byte field;\r\n                        if (j % 2 == 0)\r\n                            field = blockHash[29 + j / 2] \u003e\u003e 4;\r\n                        else\r\n                            field = blockHash[29 + j / 2] \u0026 0x0F;\r\n                        if (bet.bet[j] \u003c 0x10) {\r\n                            if (field == bet.bet[j]) {\r\n                                matchesCount++;\r\n                                coefficient += 30;\r\n                            }\r\n                            else\r\n                                isSuperPrize = false;\r\n                            continue;\r\n                        }\r\n                        else\r\n                            isSuperPrize = false;\r\n                        if (bet.bet[j] == 0x10) {\r\n                            if (field \u003e 0x09 \u0026\u0026 field \u003c 0x10) {\r\n                                matchesCount++;\r\n                                coefficient += 5;\r\n                            }\r\n                            continue;\r\n                        }\r\n                        if (bet.bet[j] == 0x11) {\r\n                            if (field \u003c 0x0A) {\r\n                                matchesCount++;\r\n                                coefficient += 3;\r\n                            }\r\n                            continue;\r\n                        }\r\n                        if (bet.bet[j] == 0x12) {\r\n                            if (field \u003c 0x0A \u0026\u0026 field \u0026 0x01 == 0x01) {\r\n                                matchesCount++;\r\n                                coefficient += 6;\r\n                            }\r\n                            continue;\r\n                        }\r\n                        if (bet.bet[j] == 0x13) {\r\n                            if (field \u003c 0x0A \u0026\u0026 field \u0026 0x01 == 0x0) {\r\n                                matchesCount++;\r\n                                coefficient += 6;\r\n                            }\r\n                            continue;\r\n                        }\r\n                    }\r\n                \r\n                    coefficient *= PRECISION * 8;\r\n                        \r\n                    uint256 payoutAmount = bet.amount * coefficient / (PRECISION * 15 * markedCount);\r\n                    transactions[i] = Transaction(payoutAmount, bet.gamer);\r\n                    emit PayoutBet(payoutAmount, bet.id, bet.gamer);\r\n                    balance -= payoutAmount;\r\n                    \r\n                    if (isSuperPrize == true) {\r\n                        superprizes[i].amount = balance;\r\n                        superprizes[i].id = bet.id;\r\n                        balance = 0;\r\n                    }\r\n                }\r\n            }\r\n        }\r\n        \r\n        for (i = 0; i \u003c length; i++) {\r\n            if (transactions[i].amount \u003e 0 \u0026\u0026 !transactions[i].gamer.send(transactions[i].amount))\r\n                (new DeliverFunds).value(transactions[i].amount)(transactions[i].gamer);\r\n            if (superprizes[i].id != 0) {\r\n                EthexSuperprize(superprizeAddress).initSuperprize(transactions[i].gamer, superprizes[i].id);\r\n                EthexJackpot(jackpotAddress).paySuperPrize(transactions[i].gamer);\r\n                if (superprizes[i].amount \u003e 0 \u0026\u0026 !transactions[i].gamer.send(superprizes[i].amount))\r\n                    (new DeliverFunds).value(superprizes[i].amount)(transactions[i].gamer);\r\n            }\r\n        }\r\n    }\r\n    \r\n    function migrate(address payable newContract) external onlyOwner {\r\n        newContract.transfer(address(this).balance);\r\n    }\r\n\r\n    function setJackpot(address payable jackpot) external onlyOwner {\r\n        jackpotAddress = jackpot;\r\n    }\r\n    \r\n    function setSuperprize(address payable superprize) external onlyOwner {\r\n        superprizeAddress = superprize;\r\n    }\r\n    \r\n    function length() public view returns (uint256) {\r\n        return 1 + last - first;\r\n    }\r\n    \r\n    function enqueue(uint256 blockNumber, uint256 amount, bytes16 id, bytes6 bet, address payable gamer) internal {\r\n        last += 1;\r\n        blockNumberQueue[last] = blockNumber;\r\n        amountQueue[last] = amount;\r\n        idQueue[last] = id;\r\n        betQueue[last] = bet;\r\n        gamerQueue[last] = gamer;\r\n    }\r\n\r\n    function dequeue() internal returns (Bet memory bet) {\r\n        require(last \u003e= first);\r\n\r\n        bet = Bet(blockNumberQueue[first], amountQueue[first], idQueue[first], betQueue[first], gamerQueue[first]);\r\n\r\n        delete blockNumberQueue[first];\r\n        delete amountQueue[first];\r\n        delete idQueue[first];\r\n        delete betQueue[first];\r\n        delete gamerQueue[first];\r\n        \r\n        if (first == last) {\r\n            first = 2;\r\n            last = 1;\r\n        }\r\n        else\r\n            first += 1;\r\n    }\r\n    \r\n    function getHold(uint256 amount, bytes6 bet) internal pure returns (uint256 coefficient, uint8 markedCount, uint256 holdAmount) {\r\n        for (uint8 i = 0; i \u003c bet.length; i++) {\r\n            if (bet[i] \u003e 0x13)\r\n                continue;\r\n            markedCount++;\r\n            if (bet[i] \u003c 0x10) {\r\n                coefficient += 30;\r\n                continue;\r\n            }\r\n            if (bet[i] == 0x10) {\r\n                coefficient += 5;\r\n                continue;\r\n            }\r\n            if (bet[i] == 0x11) {\r\n                coefficient += 3;\r\n                continue;\r\n            }\r\n            if (bet[i] == 0x12) {\r\n                coefficient += 6;\r\n                continue;\r\n            }\r\n            if (bet[i] == 0x13) {\r\n                coefficient += 6;\r\n                continue;\r\n            }\r\n        }\r\n        holdAmount = amount * coefficient * 2 / 375 / markedCount;\r\n    }\r\n}\r\n"},"EthexSuperprize.sol":{"content":"pragma solidity ^0.5.0;\r\n\r\n/**\r\n * (E)t)h)e)x) Superprize Contract \r\n *  This smart-contract is the part of Ethex Lottery fair game.\r\n *  See latest version at https://github.com/ethex-bet/ethex-lottery \r\n *  http://ethex.bet\r\n */\r\n \r\n contract EthexSuperprize {\r\n    struct Payout {\r\n        uint256 index;\r\n        uint256 amount;\r\n        uint256 block;\r\n        address payable winnerAddress;\r\n        bytes16 betId;\r\n    }\r\n     \r\n    Payout[] public payouts;\r\n     \r\n    address payable private owner;\r\n    address public lotoAddress;\r\n    address payable public newVersionAddress;\r\n    EthexSuperprize previousContract;\r\n    uint256 public hold;\r\n    \r\n    event Superprize (\r\n        uint256 index,\r\n        uint256 amount,\r\n        address winner,\r\n        bytes16 betId,\r\n        byte state\r\n    );\r\n    \r\n    uint8 constant PARTS = 6;\r\n    uint256 constant PRECISION = 1 ether;\r\n    uint256 constant MONTHLY = 150000;\r\n     \r\n    constructor() public {\r\n        owner = msg.sender;\r\n    }\r\n     \r\n     modifier onlyOwner {\r\n        require(msg.sender == owner);\r\n        _;\r\n    }\r\n    \r\n    function() external payable { }\r\n    \r\n    function initSuperprize(address payable winner, bytes16 betId) external {\r\n        require(msg.sender == lotoAddress);\r\n        uint256 amount = address(this).balance - hold;\r\n        hold = address(this).balance;\r\n        uint256 sum;\r\n        uint256 temp;\r\n        for (uint256 i = 1; i \u003c PARTS; i++) {\r\n            temp = amount * PRECISION * (i - 1 + 10) / 75 / PRECISION;\r\n            sum += temp;\r\n            payouts.push(Payout(i, temp, block.number + i * MONTHLY, winner, betId));\r\n        }\r\n        payouts.push(Payout(PARTS, amount - sum, block.number + PARTS * MONTHLY, winner, betId));\r\n        emit Superprize(0, amount, winner, betId, 0);\r\n    }\r\n    \r\n    function paySuperprize() external onlyOwner {\r\n        if (payouts.length == 0)\r\n            return;\r\n        Payout[] memory payoutArray = new Payout[](payouts.length);\r\n        uint i = payouts.length;\r\n        while (i \u003e 0) {\r\n            i--;\r\n            if (payouts[i].block \u003c= block.number) {\r\n                emit Superprize(payouts[i].index, payouts[i].amount, payouts[i].winnerAddress, payouts[i].betId, 0x01);\r\n                hold -= payouts[i].amount;\r\n            }\r\n            payoutArray[i] = payouts[i];\r\n            payouts.pop();\r\n        }\r\n        for (i = 0; i \u003c payoutArray.length; i++)\r\n            if (payoutArray[i].block \u003e block.number)\r\n                payouts.push(payoutArray[i]);\r\n        for (i = 0; i \u003c payoutArray.length; i++)\r\n            if (payoutArray[i].block \u003c= block.number)\r\n                payoutArray[i].winnerAddress.transfer(payoutArray[i].amount);\r\n    }\r\n     \r\n    function setOldVersion(address payable oldAddress) external onlyOwner {\r\n        previousContract = EthexSuperprize(oldAddress);\r\n        lotoAddress = previousContract.lotoAddress();\r\n        hold = previousContract.hold();\r\n        uint256 index;\r\n        uint256 amount;\r\n        uint256 betBlock;\r\n        address payable winner;\r\n        bytes16 betId;\r\n        for (uint i = 0; i \u003c previousContract.getPayoutsCount(); i++) {\r\n            (index, amount, betBlock, winner, betId) = previousContract.payouts(i);\r\n            payouts.push(Payout(index, amount, betBlock, winner, betId));\r\n        }\r\n        previousContract.migrate();\r\n    }\r\n    \r\n    function setNewVersion(address payable newVersion) external onlyOwner {\r\n        newVersionAddress = newVersion;\r\n    }\r\n    \r\n    function setLoto(address loto) external onlyOwner {\r\n        lotoAddress = loto;\r\n    }\r\n    \r\n    function migrate() external {\r\n        require(msg.sender == owner || msg.sender == newVersionAddress);\r\n        require(newVersionAddress != address(0));\r\n        newVersionAddress.transfer(address(this).balance);\r\n    }   \r\n\r\n    function getPayoutsCount() view public returns (uint256) {\r\n        return payouts.length;\r\n    }\r\n}"}}

    File 2 of 3: EthexHouse
    pragma solidity ^0.5.0;
    
    /**
     * (E)t)h)e)x) House Contract 
     *  This smart-contract is the part of Ethex Lottery fair game.
     *  See latest version at https://github.com/ethex-bet/ethex-lottery 
     *  http://ethex.bet
     */
     
     contract EthexHouse {
         address payable private owner;
         
         constructor() public {
             owner = msg.sender;
         }
         
         modifier onlyOwner {
            require(msg.sender == owner);
            _;
        }
        
        function payIn() external payable {
        }
        
        function withdraw() external onlyOwner {
            owner.transfer(address(this).balance);
        }
     }

    File 3 of 3: EthexJackpot
    pragma solidity ^0.5.0;
    
    /**
     * (E)t)h)e)x) Jackpot Contract 
     *  This smart-contract is the part of Ethex Lottery fair game.
     *  See latest version at https://github.com/ethex-bet/ethex-contracts 
     *  http://ethex.bet
     */
    
    contract EthexJackpot {
        mapping(uint256 => address payable) public tickets;
        uint256 public numberEnd;
        uint256 public firstNumber;
        uint256 public dailyAmount;
        uint256 public weeklyAmount;
        uint256 public monthlyAmount;
        uint256 public seasonalAmount;
        bool public dailyProcessed;
        bool public weeklyProcessed;
        bool public monthlyProcessed;
        bool public seasonalProcessed;
        address payable private owner;
        address public lotoAddress;
        address payable public newVersionAddress;
        EthexJackpot previousContract;
        uint256 public dailyNumberStartPrev;
        uint256 public weeklyNumberStartPrev;
        uint256 public monthlyNumberStartPrev;
        uint256 public seasonalNumberStartPrev;
        uint256 public dailyStart;
        uint256 public weeklyStart;
        uint256 public monthlyStart;
        uint256 public seasonalStart;
        uint256 public dailyEnd;
        uint256 public weeklyEnd;
        uint256 public monthlyEnd;
        uint256 public seasonalEnd;
        uint256 public dailyNumberStart;
        uint256 public weeklyNumberStart;
        uint256 public monthlyNumberStart;
        uint256 public seasonalNumberStart;
        uint256 public dailyNumberEndPrev;
        uint256 public weeklyNumberEndPrev;
        uint256 public monthlyNumberEndPrev;
        uint256 public seasonalNumberEndPrev;
        
        event Jackpot (
            uint256 number,
            uint256 count,
            uint256 amount,
            byte jackpotType
        );
        
        event Ticket (
            bytes16 indexed id,
            uint256 number
        );
        
        event SuperPrize (
            uint256 amount,
            address winner
        );
        
        uint256 constant DAILY = 5000;
        uint256 constant WEEKLY = 35000;
        uint256 constant MONTHLY = 150000;
        uint256 constant SEASONAL = 450000;
        uint256 constant PRECISION = 1 ether;
        uint256 constant DAILY_PART = 84;
        uint256 constant WEEKLY_PART = 12;
        uint256 constant MONTHLY_PART = 3;
        
        constructor() public payable {
            owner = msg.sender;
        }
        
        function() external payable { }
    
        modifier onlyOwner {
            require(msg.sender == owner);
            _;
        }
        
        modifier onlyOwnerOrNewVersion {
            require(msg.sender == owner || msg.sender == newVersionAddress);
            _;
        }
        
        modifier onlyLoto {
            require(msg.sender == lotoAddress, "Loto only");
            _;
        }
        
        function migrate() external onlyOwnerOrNewVersion {
            newVersionAddress.transfer(address(this).balance);
        }
    
        function registerTicket(bytes16 id, address payable gamer) external onlyLoto {
            uint256 number = numberEnd + 1;
            if (block.number >= dailyEnd) {
                setDaily();
                dailyNumberStart = number;
            }
            else
                if (dailyNumberStart == dailyNumberStartPrev)
                    dailyNumberStart = number;
            if (block.number >= weeklyEnd) {
                setWeekly();
                weeklyNumberStart = number;
            }
            else
                if (weeklyNumberStart == weeklyNumberStartPrev)
                    weeklyNumberStart = number;
            if (block.number >= monthlyEnd) {
                setMonthly();
                monthlyNumberStart = number;
            }
            else
                if (monthlyNumberStart == monthlyNumberStartPrev)
                    monthlyNumberStart = number;
            if (block.number >= seasonalEnd) {
                setSeasonal();
                seasonalNumberStart = number;
            }
            else
                if (seasonalNumberStart == seasonalNumberStartPrev)
                    seasonalNumberStart = number;
            numberEnd = number;
            tickets[number] = gamer;
            emit Ticket(id, number);
        }
        
        function setLoto(address loto) external onlyOwner {
            lotoAddress = loto;
        }
        
        function setNewVersion(address payable newVersion) external onlyOwner {
            newVersionAddress = newVersion;
        }
        
        function payIn() external payable {
            uint256 distributedAmount = dailyAmount + weeklyAmount + monthlyAmount + seasonalAmount;
            if (distributedAmount < address(this).balance) {
                uint256 amount = (address(this).balance - distributedAmount) / 4;
                dailyAmount += amount;
                weeklyAmount += amount;
                monthlyAmount += amount;
                seasonalAmount += amount;
            }
        }
        
        function settleJackpot() external {
            if (block.number >= dailyEnd)
                setDaily();
            if (block.number >= weeklyEnd)
                setWeekly();
            if (block.number >= monthlyEnd)
                setMonthly();
            if (block.number >= seasonalEnd)
                setSeasonal();
            
            if (block.number == dailyStart || (dailyStart < block.number - 256))
                return;
            
            uint48 modulo = uint48(bytes6(blockhash(dailyStart) << 29));
            
            uint256 dailyPayAmount;
            uint256 weeklyPayAmount;
            uint256 monthlyPayAmount;
            uint256 seasonalPayAmount;
            uint256 dailyWin;
            uint256 weeklyWin;
            uint256 monthlyWin;
            uint256 seasonalWin;
            if (dailyProcessed == false) {
                dailyPayAmount = dailyAmount * PRECISION / DAILY_PART / PRECISION;
                dailyAmount -= dailyPayAmount;
                dailyProcessed = true;
                dailyWin = getNumber(dailyNumberStartPrev, dailyNumberEndPrev, modulo);
                emit Jackpot(dailyWin, dailyNumberEndPrev - dailyNumberStartPrev + 1, dailyPayAmount, 0x01);
            }
            if (weeklyProcessed == false) {
                weeklyPayAmount = weeklyAmount * PRECISION / WEEKLY_PART / PRECISION;
                weeklyAmount -= weeklyPayAmount;
                weeklyProcessed = true;
                weeklyWin = getNumber(weeklyNumberStartPrev, weeklyNumberEndPrev, modulo);
                emit Jackpot(weeklyWin, weeklyNumberEndPrev - weeklyNumberStartPrev + 1, weeklyPayAmount, 0x02);
            }
            if (monthlyProcessed == false) {
                monthlyPayAmount = monthlyAmount * PRECISION / MONTHLY_PART / PRECISION;
                monthlyAmount -= monthlyPayAmount;
                monthlyProcessed = true;
                monthlyWin = getNumber(monthlyNumberStartPrev, monthlyNumberEndPrev, modulo);
                emit Jackpot(monthlyWin, monthlyNumberEndPrev - monthlyNumberStartPrev + 1, monthlyPayAmount, 0x04);
            }
            if (seasonalProcessed == false) {
                seasonalPayAmount = seasonalAmount;
                seasonalAmount -= seasonalPayAmount;
                seasonalProcessed = true;
                seasonalWin = getNumber(seasonalNumberStartPrev, seasonalNumberEndPrev, modulo);
                emit Jackpot(seasonalWin, seasonalNumberEndPrev - seasonalNumberStartPrev + 1, seasonalPayAmount, 0x08);
            }
            if (dailyPayAmount > 0)
                getAddress(dailyWin).transfer(dailyPayAmount);
            if (weeklyPayAmount > 0)
                getAddress(weeklyWin).transfer(weeklyPayAmount);
            if (monthlyPayAmount > 0)
                getAddress(monthlyWin).transfer(monthlyPayAmount);
            if (seasonalPayAmount > 0)
                getAddress(seasonalWin).transfer(seasonalPayAmount);
        }
    
        function paySuperPrize(address payable winner) external onlyLoto {
            uint256 superPrizeAmount = dailyAmount + weeklyAmount + monthlyAmount + seasonalAmount;
            dailyAmount = 0;
            weeklyAmount = 0;
            monthlyAmount = 0;
            seasonalAmount = 0;
            emit SuperPrize(superPrizeAmount, winner);
            winner.transfer(superPrizeAmount);
        }
        
        function setOldVersion(address payable oldAddress) external onlyOwner {
            previousContract = EthexJackpot(oldAddress);
            dailyStart = previousContract.dailyStart();
            dailyEnd = previousContract.dailyEnd();
            dailyProcessed = previousContract.dailyProcessed();
            weeklyStart = previousContract.weeklyStart();
            weeklyEnd = previousContract.weeklyEnd();
            weeklyProcessed = previousContract.weeklyProcessed();
            monthlyStart = previousContract.monthlyStart();
            monthlyEnd = previousContract.monthlyEnd();
            monthlyProcessed = previousContract.monthlyProcessed();
            seasonalStart = previousContract.seasonalStart();
            seasonalEnd = previousContract.seasonalEnd();
            seasonalProcessed = previousContract.seasonalProcessed();
            dailyNumberStartPrev = previousContract.dailyNumberStartPrev();
            weeklyNumberStartPrev = previousContract.weeklyNumberStartPrev();
            monthlyNumberStartPrev = previousContract.monthlyNumberStartPrev();
            seasonalNumberStartPrev = previousContract.seasonalNumberStartPrev();
            dailyNumberStart = previousContract.dailyNumberStart();
            weeklyNumberStart = previousContract.weeklyNumberStart();
            monthlyNumberStart = previousContract.monthlyNumberStart();
            seasonalNumberStart = previousContract.seasonalNumberStart();
            dailyNumberEndPrev = previousContract.dailyNumberEndPrev();
            weeklyNumberEndPrev = previousContract.weeklyNumberEndPrev();
            monthlyNumberEndPrev = previousContract.monthlyNumberEndPrev();
            seasonalNumberEndPrev = previousContract.seasonalNumberEndPrev();
            numberEnd = previousContract.numberEnd();
            dailyAmount = previousContract.dailyAmount();
            weeklyAmount = previousContract.weeklyAmount();
            monthlyAmount = previousContract.monthlyAmount();
            seasonalAmount = previousContract.seasonalAmount();
            firstNumber = weeklyNumberStart;
            for (uint256 i = firstNumber; i <= numberEnd; i++)
                tickets[i] = previousContract.getAddress(i);
            previousContract.migrate();
        }
        
        function getAddress(uint256 number) public returns (address payable) {
            if (number <= firstNumber)
                return previousContract.getAddress(number);
            return tickets[number];
        }
        
        function setDaily() private {
            dailyProcessed = dailyNumberEndPrev == numberEnd;
            dailyStart = dailyEnd;
            dailyEnd = dailyStart + DAILY;
            dailyNumberStartPrev = dailyNumberStart;
            dailyNumberEndPrev = numberEnd;
        }
        
        function setWeekly() private {
            weeklyProcessed = weeklyNumberEndPrev == numberEnd;
            weeklyStart = weeklyEnd;
            weeklyEnd = weeklyStart + WEEKLY;
            weeklyNumberStartPrev = weeklyNumberStart;
            weeklyNumberEndPrev = numberEnd;
        }
        
        function setMonthly() private {
            monthlyProcessed = monthlyNumberEndPrev == numberEnd;
            monthlyStart = monthlyEnd;
            monthlyEnd = monthlyStart + MONTHLY;
            monthlyNumberStartPrev = monthlyNumberStart;
            monthlyNumberEndPrev = numberEnd;
        }
        
        function setSeasonal() private {
            seasonalProcessed = seasonalNumberEndPrev == numberEnd;
            seasonalStart = seasonalEnd;
            seasonalEnd = seasonalStart + SEASONAL;
            seasonalNumberStartPrev = seasonalNumberStart;
            seasonalNumberEndPrev = numberEnd;
        }
        
        function getNumber(uint256 startNumber, uint256 endNumber, uint48 modulo) pure private returns (uint256) {
            return startNumber + modulo % (endNumber - startNumber + 1);
        }
    }