Contract 0x839bd174e10246b674e7573a5196c637e3992ca9

Contract Overview

Balance:
153.023779 Ether
TxHash Block Age From To Value [TxFee]
0xabd072a018f7f4aa118ba77e4f8636875f99b62f1fb5ef4d18a85dac1ee64dd2397079714 days 14 hrs ago0x153aa9a03a255cc635f00c54666f3686bf881001 IN  0x839bd174e10246b674e7573a5196c637e3992ca90 Ether0.000033163
0x1b6d84a2a6f52632a4a4362ee1547425128c7c162f4271d065bfc6ec4f472add397079314 days 14 hrs ago0xb4aaffeaacb27098d9545a3c0e36924af9eedfe0 IN  0x839bd174e10246b674e7573a5196c637e3992ca90 Ether0.001247886
0x6e8622461795d1885d40919d62e3a67eaddf8680eb0f62829067792d0f6dd889397079314 days 14 hrs ago0xb4aaffeaacb27098d9545a3c0e36924af9eedfe0 IN  0x839bd174e10246b674e7573a5196c637e3992ca90 Ether0.000371494
0x5e95234912116a67d7974e7eefeb23534042996e010df372e4b8fce94e6dcc2c397079214 days 14 hrs ago0x153aa9a03a255cc635f00c54666f3686bf881001 IN  0x839bd174e10246b674e7573a5196c637e3992ca90 Ether0.000062277
0x59f08e004f3dd7c61ada8462dfaca8a5369ea402487731ac5619e49e386c733f397052214 days 15 hrs ago0xb4aaffeaacb27098d9545a3c0e36924af9eedfe0 IN  0x839bd174e10246b674e7573a5196c637e3992ca90 Ether0.001223718
0xad56bc287bb2d94029177f27f9d5f07bece3780e0f22c516aa2edb2751c56a1d397052014 days 15 hrs ago0xb4aaffeaacb27098d9545a3c0e36924af9eedfe0 IN  0x839bd174e10246b674e7573a5196c637e3992ca90 Ether0.000250354
0x7c3ba0b9138e8f14f1d4d5ef1170d322a3e0e02b5be14baa3376083a2d60a10e397049914 days 15 hrs ago0xb4aaffeaacb27098d9545a3c0e36924af9eedfe0 IN  0x839bd174e10246b674e7573a5196c637e3992ca90 Ether0.001227252
0x0881987149f64627840f519bd8532df38e93d26701916dee3c03729efca534f0397049914 days 15 hrs ago0xb4aaffeaacb27098d9545a3c0e36924af9eedfe0 IN  0x839bd174e10246b674e7573a5196c637e3992ca90 Ether0.000264298
0x59d70c1a11ae32eca937a484b5e5bc376f5a3dc60a4f6b7984e5b0cd3da77289397049814 days 15 hrs ago0x8f902825b3fd7a4ca1cfc751282ec29366c013cd IN  0x839bd174e10246b674e7573a5196c637e3992ca90.1 Ether0.000153887
0xfefb976369e714417d745db2ff64fe7aeb1cb9877e77e7d2011e4a8d91bf0b97393940820 days 1 hr ago0xb4aaffeaacb27098d9545a3c0e36924af9eedfe0 IN  0x839bd174e10246b674e7573a5196c637e3992ca90 Ether0.001223846
0x8a420debcdc8bb2f1806c33fae9b9fcfce59dac55e42af0b8ff70b33b8300ef0393940620 days 1 hr ago0xb4aaffeaacb27098d9545a3c0e36924af9eedfe0 IN  0x839bd174e10246b674e7573a5196c637e3992ca90 Ether0.000250354
0xd4f981e311f9223c219bf8505c53d6a7041d933f9909a494a0f0254f8a487441393422920 days 22 hrs ago0xb4aaffeaacb27098d9545a3c0e36924af9eedfe0 IN  0x839bd174e10246b674e7573a5196c637e3992ca90 Ether0.00122738
0x57e02c5fd73f6b415bd42a583b4de891801de05b3159d02a20b716f75a6f0ded393422920 days 22 hrs ago0xb4aaffeaacb27098d9545a3c0e36924af9eedfe0 IN  0x839bd174e10246b674e7573a5196c637e3992ca90 Ether0.000264298
0xbef909fcf4c2393db5ab6b484c3ede4c404c11f62e9d42f8f12db0e08ae41695393422620 days 22 hrs ago0x627306090abab3a6e1400e9345bc60c78a8bef57 IN  0x839bd174e10246b674e7573a5196c637e3992ca91.5 Ether0.000083571
0x0f03d947ce489850c313c7b2e55a6e492b0071e245819a59afcfc6757883703a393422120 days 22 hrs ago0xb4aaffeaacb27098d9545a3c0e36924af9eedfe0 IN  0x839bd174e10246b674e7573a5196c637e3992ca90 Ether0.001227124
0x1e3607b893117a20960a3054b9e256a35c6fb7ca036ebb4cab56d6c7b3d2827f393422020 days 22 hrs ago0xb4aaffeaacb27098d9545a3c0e36924af9eedfe0 IN  0x839bd174e10246b674e7573a5196c637e3992ca90 Ether0.000264298
0xf6c3c22adde0cccaa8bbe06f7211d88c9f8f44f0f60cae0b78d3f304fd522175393421920 days 22 hrs ago0x627306090abab3a6e1400e9345bc60c78a8bef57 IN  0x839bd174e10246b674e7573a5196c637e3992ca91.5 Ether0.000083571
0x66f1800dc2c07d37a070be1fbc77828135755de652d51c33531389605de4e529393387521 days 3 mins ago0x519836d44b2b4a0a3b6d41759308f1227fdd3f4d IN  0x839bd174e10246b674e7573a5196c637e3992ca90 Ether0.000031664
0xdb3332dee3a1518cfc1bf3882cc1f8e8ba2ce0fbdcd291ce94ce534b184e1270393387421 days 4 mins ago0x519836d44b2b4a0a3b6d41759308f1227fdd3f4d IN  0x839bd174e10246b674e7573a5196c637e3992ca90 Ether0.000023982
0x6e6297918af34bb7c9f9e5ed7f6fdd342cfe1e44372590162dc690ea26def2c0393386721 days 5 mins ago0xb4aaffeaacb27098d9545a3c0e36924af9eedfe0 IN  0x839bd174e10246b674e7573a5196c637e3992ca90 Ether0.001223846
0xe21417911ff9ddb569f79d137f5f5945f127c1e1b12b6a2f377b6a0c82c1818d393386621 days 6 mins ago0xb4aaffeaacb27098d9545a3c0e36924af9eedfe0 IN  0x839bd174e10246b674e7573a5196c637e3992ca90 Ether0.000381284
0x6d11f774b2d44e2a0f683a4ade162f95e4b707878e6780ab5ff111bedbee27fc393381621 days 18 mins ago0xb4aaffeaacb27098d9545a3c0e36924af9eedfe0 IN  0x839bd174e10246b674e7573a5196c637e3992ca90 Ether0.001223846
0xc1f26b6bb784a216ddf8a113378af44448f1606d488551e80dfedcb11baae92b393381421 days 19 mins ago0xb4aaffeaacb27098d9545a3c0e36924af9eedfe0 IN  0x839bd174e10246b674e7573a5196c637e3992ca90 Ether0.000250354
0xf7e9439ae81cb8aba3fe9a9cb4130d57c0d214f25dd4597d4bfb86bdbcf70b21393379421 days 24 mins ago0xb4aaffeaacb27098d9545a3c0e36924af9eedfe0 IN  0x839bd174e10246b674e7573a5196c637e3992ca90 Ether0.00122738
0xa918b35d27cd6927d3402f036d32b59429b7f4ac308695f691ff01cf0f91cbae393379421 days 24 mins ago0xb4aaffeaacb27098d9545a3c0e36924af9eedfe0 IN  0x839bd174e10246b674e7573a5196c637e3992ca90 Ether0.000264298
[ Download CSV Export 

Latest 25 internal transaction, Click here to view more Internal Transactions as a result of Contract Execution

Parent TxHash Block Age From To Value
0xabd072a018f7f4aa118ba77e4f8636875f99b62f1fb5ef4d18a85dac1ee64dd2397079714 days 14 hrs ago0x839bd174e10246b674e7573a5196c637e3992ca90x153aa9a03a255cc635f00c54666f3686bf8810010.078 Ether
0xabd072a018f7f4aa118ba77e4f8636875f99b62f1fb5ef4d18a85dac1ee64dd2397079714 days 14 hrs ago0x839bd174e10246b674e7573a5196c637e3992ca90x651fab6db5e3389cd6e85eb94356962049f2bca90 Ether
0xabd072a018f7f4aa118ba77e4f8636875f99b62f1fb5ef4d18a85dac1ee64dd2397079714 days 14 hrs ago0x839bd174e10246b674e7573a5196c637e3992ca90xaa4c5d545417f06fcd13e0b70391218c46f0007b0 Ether
0x1b6d84a2a6f52632a4a4362ee1547425128c7c162f4271d065bfc6ec4f472add397079314 days 14 hrs ago0x839bd174e10246b674e7573a5196c637e3992ca90x651fab6db5e3389cd6e85eb94356962049f2bca90 Ether
0x1b6d84a2a6f52632a4a4362ee1547425128c7c162f4271d065bfc6ec4f472add397079314 days 14 hrs ago0x839bd174e10246b674e7573a5196c637e3992ca90xaa4c5d545417f06fcd13e0b70391218c46f0007b0 Ether
0x6e8622461795d1885d40919d62e3a67eaddf8680eb0f62829067792d0f6dd889397079314 days 14 hrs ago0x839bd174e10246b674e7573a5196c637e3992ca90x651fab6db5e3389cd6e85eb94356962049f2bca90 Ether
0x6e8622461795d1885d40919d62e3a67eaddf8680eb0f62829067792d0f6dd889397079314 days 14 hrs ago0x839bd174e10246b674e7573a5196c637e3992ca90xaa4c5d545417f06fcd13e0b70391218c46f0007b0 Ether
0x5e95234912116a67d7974e7eefeb23534042996e010df372e4b8fce94e6dcc2c397079214 days 14 hrs ago0x839bd174e10246b674e7573a5196c637e3992ca90x651fab6db5e3389cd6e85eb94356962049f2bca90 Ether
0x5e95234912116a67d7974e7eefeb23534042996e010df372e4b8fce94e6dcc2c397079214 days 14 hrs ago0x839bd174e10246b674e7573a5196c637e3992ca90xaa4c5d545417f06fcd13e0b70391218c46f0007b0 Ether
0x59f08e004f3dd7c61ada8462dfaca8a5369ea402487731ac5619e49e386c733f397052214 days 15 hrs ago0x839bd174e10246b674e7573a5196c637e3992ca90xaa4c5d545417f06fcd13e0b70391218c46f0007b0 Ether
0xad56bc287bb2d94029177f27f9d5f07bece3780e0f22c516aa2edb2751c56a1d397052014 days 15 hrs ago0x839bd174e10246b674e7573a5196c637e3992ca90xaa4c5d545417f06fcd13e0b70391218c46f0007b0 Ether
0xfefb976369e714417d745db2ff64fe7aeb1cb9877e77e7d2011e4a8d91bf0b97393940820 days 1 hr ago0x839bd174e10246b674e7573a5196c637e3992ca90xaa4c5d545417f06fcd13e0b70391218c46f0007b0 Ether
0x8a420debcdc8bb2f1806c33fae9b9fcfce59dac55e42af0b8ff70b33b8300ef0393940620 days 1 hr ago0x839bd174e10246b674e7573a5196c637e3992ca90xaa4c5d545417f06fcd13e0b70391218c46f0007b0 Ether
0x66f1800dc2c07d37a070be1fbc77828135755de652d51c33531389605de4e529393387521 days 3 mins ago0x839bd174e10246b674e7573a5196c637e3992ca90x519836d44b2b4a0a3b6d41759308f1227fdd3f4d0 Ether
0x66f1800dc2c07d37a070be1fbc77828135755de652d51c33531389605de4e529393387521 days 3 mins ago0x839bd174e10246b674e7573a5196c637e3992ca90x651fab6db5e3389cd6e85eb94356962049f2bca90 Ether
0x66f1800dc2c07d37a070be1fbc77828135755de652d51c33531389605de4e529393387521 days 3 mins ago0x839bd174e10246b674e7573a5196c637e3992ca90xaa4c5d545417f06fcd13e0b70391218c46f0007b0 Ether
0xdb3332dee3a1518cfc1bf3882cc1f8e8ba2ce0fbdcd291ce94ce534b184e1270393387421 days 4 mins ago0x839bd174e10246b674e7573a5196c637e3992ca90x519836d44b2b4a0a3b6d41759308f1227fdd3f4d0.8 Ether
0xdb3332dee3a1518cfc1bf3882cc1f8e8ba2ce0fbdcd291ce94ce534b184e1270393387421 days 4 mins ago0x839bd174e10246b674e7573a5196c637e3992ca90x651fab6db5e3389cd6e85eb94356962049f2bca90 Ether
0xdb3332dee3a1518cfc1bf3882cc1f8e8ba2ce0fbdcd291ce94ce534b184e1270393387421 days 4 mins ago0x839bd174e10246b674e7573a5196c637e3992ca90xaa4c5d545417f06fcd13e0b70391218c46f0007b0 Ether
0x6e6297918af34bb7c9f9e5ed7f6fdd342cfe1e44372590162dc690ea26def2c0393386721 days 5 mins ago0x839bd174e10246b674e7573a5196c637e3992ca90xaa4c5d545417f06fcd13e0b70391218c46f0007b0 Ether
0xe21417911ff9ddb569f79d137f5f5945f127c1e1b12b6a2f377b6a0c82c1818d393386621 days 6 mins ago0x839bd174e10246b674e7573a5196c637e3992ca90xaa4c5d545417f06fcd13e0b70391218c46f0007b0 Ether
0x6d11f774b2d44e2a0f683a4ade162f95e4b707878e6780ab5ff111bedbee27fc393381621 days 18 mins ago0x839bd174e10246b674e7573a5196c637e3992ca90xaa4c5d545417f06fcd13e0b70391218c46f0007b0 Ether
0xc1f26b6bb784a216ddf8a113378af44448f1606d488551e80dfedcb11baae92b393381421 days 19 mins ago0x839bd174e10246b674e7573a5196c637e3992ca90xaa4c5d545417f06fcd13e0b70391218c46f0007b0 Ether
0xb7f40fbf09666e79521f97aa4beb5bf90528cab07113324833b887d0b64a1f11393378021 days 27 mins ago0x839bd174e10246b674e7573a5196c637e3992ca90xaa4c5d545417f06fcd13e0b70391218c46f0007b0 Ether
0x2b6f9edc476cd20e40c69f3856f62ee2743fe5923565b7a13f69bcaf3734c535393377821 days 28 mins ago0x839bd174e10246b674e7573a5196c637e3992ca90xaa4c5d545417f06fcd13e0b70391218c46f0007b0 Ether
[ Download CSV Export 
Warning: The compiled contract might be susceptible to ExpExponentCleanup (medium/high-severity), EventStructWrongData (very low-severity) Solidity Compiler Bugs.

Contract Source Code Verified (Similar Match)
Note: This contract matches the deployed ByteCode of the Verified Source Code for Contract 0x848B9EDd363E3F4920Bb6F1AB4eBb62E56d50a91
Contract Name: PlasmaContract
Compiler Version: v0.4.24+commit.e67f0147
Optimization Enabled: No
Runs (Optimizer):  200


Contract Source Code
pragma solidity ^0.4.24;

// File: contracts/Verifier.sol

// from https://github.com/HarryR/ethsnarks/blob/master/contracts/Verifier.sol
pragma solidity ^0.4.24;


contract Verifier {

    function NegateY( uint256 Y )
        internal pure returns (uint256)
    {
        uint q = 21888242871839275222246405745257275088696311157297823662689037894645226208583;
        return q - (Y % q);
    }

    function Verify ( uint256[14] in_vk, uint256[] vk_gammaABC, uint256[8] in_proof, uint256[] proof_inputs )
        internal 
        view 
        returns (bool)
    {
        require( ((vk_gammaABC.length / 2) - 1) == proof_inputs.length, "Invalid number of public inputs" );

        // Compute the linear combination vk_x
        uint256[3] memory mul_input;
        uint256[4] memory add_input;
        bool success;
        uint m = 2;

        // First two fields are used as the sum
        add_input[0] = vk_gammaABC[0];
        add_input[1] = vk_gammaABC[1];

        // Performs a sum of gammaABC[0] + sum[ gammaABC[i+1]^proof_inputs[i] ]
        for (uint i = 0; i < proof_inputs.length; i++) {
            mul_input[0] = vk_gammaABC[m++];
            mul_input[1] = vk_gammaABC[m++];
            mul_input[2] = proof_inputs[i];

            assembly {
                // ECMUL, output to last 2 elements of `add_input`
                success := staticcall(sub(gas, 2000), 7, mul_input, 0x60, add(add_input, 0x40), 0x40)
            }
            require( success, "Failed to call ECMUL precompile" );

            assembly {
                // ECADD
                success := staticcall(sub(gas, 2000), 6, add_input, 0x80, add_input, 0x40)
            }
            require( success, "Failed to call ECADD precompile" );
        }

        uint[24] memory input = [
            // (proof.A, proof.B)
            in_proof[0], in_proof[1],                           // proof.A   (G1)
            in_proof[2], in_proof[3], in_proof[4], in_proof[5], // proof.B   (G2)

            // (-vk.alpha, vk.beta)
            in_vk[0], NegateY(in_vk[1]),                        // -vk.alpha (G1)
            in_vk[2], in_vk[3], in_vk[4], in_vk[5],             // vk.beta   (G2)

            // (-vk_x, vk.gamma)
            add_input[0], NegateY(add_input[1]),                // -vk_x     (G1)
            in_vk[6], in_vk[7], in_vk[8], in_vk[9],             // vk.gamma  (G2)

            // (-proof.C, vk.delta)
            in_proof[6], NegateY(in_proof[7]),                  // -proof.C  (G1)
            in_vk[10], in_vk[11], in_vk[12], in_vk[13]          // vk.delta  (G2)
        ];

        uint[1] memory out;
        assembly {
            success := staticcall(sub(gas, 2000), 8, input, 768, out, 0x20)
        }
        require(success, "Failed to call pairing precompile");
        return out[0] == 1;
    }
}

// File: contracts/DepositVerificationKey.sol

// This contract is generated programmatically

pragma solidity ^0.4.24;


// Hardcoded constants to avoid accessing store
contract DepositVerificationKey {

    function getVkDepositCircuit() internal pure returns (uint256[14] memory vk, uint256[] memory gammaABC) {

        
        vk[0] = 0x2806ceee6e1d1eb6f31ff675b92143dba13b3fbad614f843f5c3afd6568b205a;
        vk[1] = 0x122808a613a8f598c4b867f4b2ff0d43f0bb6d88eeb8ee75eb6f24d359bbf8e0;
        vk[2] = 0x22448ceb94acf3cd1d15bcaa5b0fea9b93517c5845177e084089d9ee6d79ff50;
        vk[3] = 0x031a214677d973a795d26219598bb0512ea0dc76e75dbce39cbc9d9b17a2cc8c;
        vk[4] = 0x0a9a3bef0fd1d79ae409f82733e8e462b75ff5f05bea6422066b95ca9e02c9dd;
        vk[5] = 0x0c6fa2f476a8f04a57dbcb68e2425440062630c908d6e198c875d875130025e9;
        vk[6] = 0x0ae5cc9692f99a91d35fe9abfd2e3786b3ad14b327d0fb9e51c514f0bd95959c;
        vk[7] = 0x1d3950dce5e030d612b1167e70c34ab4cf1d9c4320206047652747915ed67097;
        vk[8] = 0x0a9138320c05f4c5d26da0bc8d508398b027cabffd4dd36fb65f29d9fa3cc3dd;
        vk[9] = 0x2a5daa065c803df8f429e946f2c5700026c2d12dc172e192d270dc73fdc8cc39;
        vk[10] = 0x27863bde61126110d0d6f2f31947e2f63c3cdd6594caf3ec225babfa7afa4f23;
        vk[11] = 0x20fd57765a2d6a84f2bee03afefaf5bd42fb5804b8a5c0874762d19afafc1f41;
        vk[12] = 0x0b451a37fed071dd2ae876826a32f4fe0a58d990c624cfde92096cc2b3fd4a08;
        vk[13] = 0x2920445cbffbb49c761e20d864dccf560258c3cd7302773accaa7d78aa206ba9;

        gammaABC = new uint256[](8);
        gammaABC[0] = 0x2d8c931ff562a4d5a349685f6fdf2a30a0883e2cfcb8a27a642687a411895577;
        gammaABC[1] = 0x2530d4a3fcaea9d34725f2f02100be77a511c2a507e084e6e379e068d4cde559;
        gammaABC[2] = 0x01e3781d1f0a0f6beac8e3aa47a8c509d80406326c5c4594aa04f4c0f9b0138a;
        gammaABC[3] = 0x235683ea39dc02e4919b9f99e14c927399f26c3c24935caf3d7f745377fd7629;
        gammaABC[4] = 0x2fbf7af8adca023e9744087f7845cc19f2bdb9cbba20c57dc77edaa6115625fb;
        gammaABC[5] = 0x1c3ad616391a8022720659ceb30a65391117df3b0e501f0e19d99800fea0d662;
        gammaABC[6] = 0x1bc9897f50972e9924dfcc9dc9c9104c50588c168b7e137526f9ab8cfdc62482;
        gammaABC[7] = 0x04f9efe4f42e792c6abffbb1b5431a71f8b7712a3e65011f07c7bb348914d0d0;


    }

}

// File: contracts/TransferVerificationKey.sol

// This contract is generated programmatically

pragma solidity ^0.4.24;


// Hardcoded constants to avoid accessing store
contract TransferVerificationKey {

    function getVkTransferCircuit() internal pure returns (uint256[14] memory vk, uint256[] memory gammaABC) {

        
        vk[0] = 0x20fabca7a936d76e2de75f334d12408a85a3038b2c748e884a7d10b6c8e785ae;
        vk[1] = 0x05b7926cd85113320bdad329a22fa8a7bb13fee4e5ae784441c975f7be24b144;
        vk[2] = 0x17f95798ad37dc5d5842e0a25085bb7091525e5a19a4e664c4325d43996733bb;
        vk[3] = 0x02943aa487fcc67df949c6e2481e6a61b992ce4ad6f5d92372f59b93d15c0d30;
        vk[4] = 0x0131b8773666df90359fdbe663c451881a09b24df4564be75dd86ceb485bc16c;
        vk[5] = 0x091b92109b2c58ee59d43f1646b910e20203dcb95676b139509886a314e00806;
        vk[6] = 0x18d2e27fdde751997e5ac3146a828702404f47c56072d5fd9e628bd9d00b5aac;
        vk[7] = 0x0cf19a2bf4b4e09843df3cd201709e55ae3a5ff31d8b59cd89d7b6eb06b98703;
        vk[8] = 0x14eaf5b1216b2adc72b75a80df5c202eb16953605656165177035432a6f88b8f;
        vk[9] = 0x0f19e2b9bb71cab73500652d5728fe94843dcef2e73a2fd97739f6e8fd83369a;
        vk[10] = 0x0135e689579dbf14165032a60d35c70c95fc8fcf56f16a5335c62ef49e4fdfc4;
        vk[11] = 0x196c80c924953fae60eb1c57c03beed305ed22454b359ade4265a434f6aef114;
        vk[12] = 0x0a282bf79f6d625029d9746a596c33e286ec52ba4fd14c87577b39cdbc656dbc;
        vk[13] = 0x216dd1c95ba7a7408e093cb8010c09addcb31e54d9ac23493341660ce3b9d742;

        gammaABC = new uint256[](8);
        gammaABC[0] = 0x29c50e44a59741be3b553316fa0181329ec5275b046bb428eb3e041a1d6a4017;
        gammaABC[1] = 0x1f799ade5130abbb234abfaa536226b602cd2e2e77c3afb5c6c29bb7835117b1;
        gammaABC[2] = 0x20ca58d0e2b5c393272802f45e7fef3d27efa2696c0be7bd7f31435b3403acbd;
        gammaABC[3] = 0x2b7f914981d405bc613a0c2c3accb5ac825b900ddbef5b7689567e0ffdf84060;
        gammaABC[4] = 0x0be03143ab86092d0872260b1ed87202fd2816e0ddc15e4dda842688ff3f8bba;
        gammaABC[5] = 0x1c4900581b3dc146c77b6bf15ceffd90ca3d34fd69b393ee562e8cc614decf91;
        gammaABC[6] = 0x1261a3e53a4815cb7237aa39113f0dd33d7464e80a317a1a35ed33a217053584;
        gammaABC[7] = 0x17599c2506b56e759ba24bf30920525cfd12337392ed0cebc0b851a142802ca0;


    }

}

// File: contracts/ExitVerificationKey.sol

// This contract is generated programmatically

pragma solidity ^0.4.24;


// Hardcoded constants to avoid accessing store
contract ExitVerificationKey {

    function getVkExitCircuit() internal pure returns (uint256[14] memory vk, uint256[] memory gammaABC) {

        
        vk[0] = 0x08730c8e1cbb3eb57ea2c4d8d5c48fc56aa910d331ef8723e74c9e5750fb943a;
        vk[1] = 0x29d8dc5dd6f9b1a692a37c4982faa894119b98dbc35fe5b0e20363ffce6c5fea;
        vk[2] = 0x016411e5a45fa79352c47a455eeaddb12059d5bb5579487e8abb4ffd2f472c5a;
        vk[3] = 0x27084dc459b5dd6d1c60cccda8d78a80755ae23436dd44aca13d44962dea244a;
        vk[4] = 0x16c4a816a173596179da516fcc694c68878da66042afe8c35f098742482ab0a0;
        vk[5] = 0x02318a621109b9e543cc09e7bcde9cfe15386429572fb31d08c88a42b418fe8e;
        vk[6] = 0x0f10cfbdfaf1753d7214d6d0f2644458bddd10ab5619d19e7e41ac709b30b3ef;
        vk[7] = 0x21f68a12e4e0ce060910e1335703431d20ce5ac7109baa52e34423fdcc659c54;
        vk[8] = 0x2c505db2e660d4ea4e6f41e0f3b921c8358d6b3bcedaaf8349f01fbf56b03d4f;
        vk[9] = 0x0733f6edbaef053203c0654afd9eea4b8909c88473b1f1aa72afdd5a4cded36e;
        vk[10] = 0x1a4c2e2c731b7de65f7b0cad686b5c7964fe162741385a33c72b08c903791e29;
        vk[11] = 0x1efc25b88bfac326220c61f7ab065be1c77af7b74f67f63262c2e66613eebdac;
        vk[12] = 0x264f4171cfa70441d121f28ce3c8186fa9011a9a2611ce7c920cba0d8cb3f826;
        vk[13] = 0x126ba4be6253be58ceb3bb5bf94045b310baea07bc35d669283a10ffdf908530;

        gammaABC = new uint256[](8);
        gammaABC[0] = 0x01b0002b9d1ceb70fe45b66103672ab9500327509572c1701d3250b00c299e88;
        gammaABC[1] = 0x080c6552831b1c735ac286a537343522bd10083d3b3fed202ffae1e83ff87cc0;
        gammaABC[2] = 0x2e13eae69b931076d3e4ce5a0764aabf54030b14f53653627d13def87840df07;
        gammaABC[3] = 0x0b2032652364ded806919e92594a508eafae7eabb42bb6e731c1bfc0b3918b6c;
        gammaABC[4] = 0x024ba284020edb04f39d1eeeccc5f826826086f2bac64e0b233114cd523043e4;
        gammaABC[5] = 0x082cb9dada50204406112d784129e28ce9fea7d999f0540fe36131aee46ad632;
        gammaABC[6] = 0x2b661ab87456646811a53fbb055addc96eef2396827889305bf2ce7ab8c1ea44;
        gammaABC[7] = 0x118ee65eb15ec1db1b648d4c64e490977198de8a01580399d5a3835576d602b9;


    }

}

// File: contracts/VerificationKeys.sol

// This contract is generated programmatically

pragma solidity ^0.4.24;





// Hardcoded constants to avoid accessing store
contract VerificationKeys is TransferVerificationKey, DepositVerificationKey, ExitVerificationKey {
}

// File: contracts/PlasmaStorage.sol

// This contract is generated programmatically

pragma solidity ^0.4.24;

// storage variable to later use in delegates chain.
// Also defines all structures
contract PlasmaStorage {

    // For tree depth 24
    bytes32 constant EMPTY_TREE_ROOT = 0x003f7e15e4de3453fe13e11fb4b007f1fce6a5b0f0353b3b8208910143aaa2f7;

    // Plasma itself

    uint256 public constant DEADLINE = 3600;

    event BlockCommitted(uint32 indexed blockNumber);
    event BlockVerified(uint32 indexed blockNumber);

    enum Circuit {
        DEPOSIT,
        TRANSFER,
        EXIT
    }

    enum AccountState {
        NOT_REGISTERED,
        REGISTERED,
        PENDING_EXIT,
        UNCONFIRMED_EXIT
    }

    struct Block {
        uint8 circuit;
        uint64  deadline;
        uint128 totalFees;
        bytes32 newRoot;
        bytes32 publicDataCommitment;
        address prover;
    }

    // Key is block number
    mapping (uint32 => Block) public blocks;
    // Only some addresses can send proofs
    mapping (address => bool) public operators;
    // Fee collection accounting
    mapping (address => uint256) public balances;

    struct Account {
        uint8 state;
        uint32 exitBatchNumber;
        address owner;
        uint256 publicKey;
        uint32 exitListHead;
        uint32 exitListTail;
    }

    // one Ethereum address should have one account
    mapping (address => uint24) public ethereumAddressToAccountID;

    // Plasma account => general information
    mapping (uint24 => Account) public accounts;

    // Public information for users
    bool public stopped;
    uint32 public lastCommittedBlockNumber;
    uint32 public lastVerifiedBlockNumber;
    bytes32 public lastVerifiedRoot;
    uint64 public constant MAX_DELAY = 1 days;
    uint256 public constant DENOMINATOR = 1000000000000;

    // deposits

    uint256 public constant DEPOSIT_BATCH_SIZE = 1;
    uint256 public totalDepositRequests; // enumerates total number of deposit, starting from 0
    uint256 public lastCommittedDepositBatch;
    uint256 public lastVerifiedDepositBatch;
    uint128 public currentDepositBatchFee; // deposit request fee scaled units

    uint24 public constant SPECIAL_ACCOUNT_DEPOSITS = 1;

    uint24 public nextAccountToRegister;

    // some ideas for optimization of the deposit request information storage:
    // store in a mapping: 20k gas to add, 5k to update a record + 5k to update the global counter per batch
    // store in an array: 20k + 5k gas to add, 5k to update + up to DEPOSIT_BATCH_SIZE * SLOAD

    // batch number => (plasma address => deposit information)
    mapping (uint256 => mapping (uint24 => DepositRequest)) public depositRequests;
    mapping (uint256 => DepositBatch) public depositBatches;

    struct DepositRequest {
        uint128 amount;
    }

    enum DepositBatchState {
        CREATED,
        COMMITTED,
        VERIFIED
    }

    struct DepositBatch {
        uint8 state;
        uint24 numRequests;
        uint32 blockNumber;
        uint64 timestamp;
        uint128 batchFee;
    }

    event LogDepositRequest(uint256 indexed batchNumber, uint24 indexed accountID, uint256 indexed publicKey, uint128 amount);
    event LogCancelDepositRequest(uint256 indexed batchNumber, uint24 indexed accountID);

    // Transfers

    uint256 public constant TRANSFER_BLOCK_SIZE = 128;

    // Exits 

    uint256 constant EXIT_BATCH_SIZE = 1;
    uint256 public totalExitRequests; 
    uint256 public lastCommittedExitBatch;
    uint256 public lastVerifiedExitBatch;
    uint128 public currentExitBatchFee; 

    uint24 public constant SPECIAL_ACCOUNT_EXITS = 0;

    // batches for complete exits
    mapping (uint256 => ExitBatch) public exitBatches;

    enum ExitBatchState {
        CREATED,
        COMMITTED,
        VERIFIED
    }

    struct ExitBatch {
        uint8 state;
        uint32 blockNumber;
        uint64 timestamp;
        uint128 batchFee;
    }

    event LogExitRequest(uint256 indexed batchNumber, uint24 indexed accountID);
    event LogCancelExitRequest(uint256 indexed batchNumber, uint24 indexed accountID);

    event LogExit(address indexed ethereumAddress, uint32 indexed blockNumber);
    event LogCompleteExit(address indexed ethereumAddress, uint32 indexed blockNumber, uint24 accountID);

    struct ExitLeaf {
        uint32 nextID;
        uint128 amount;
    }

    mapping (address => mapping (uint32 => ExitLeaf)) public exitLeafs;

    // mapping ethereum address => block number => balance
    // mapping (address => mapping (uint32 => uint128)) public exitAmounts;
    // Delegates chain
    address public transactor;
    address public exitor;
}

// File: contracts/Plasma.sol

// Single operator mode

contract PlasmaStub is VerificationKeys, PlasmaStorage {

    modifier active_only() {
        require(!stopped, "contract should not be globally stopped");
        _;
    }

    modifier operator_only() {
        require(operators[msg.sender] == true, "sender should be one of the operators");
        _;
    }

    // unit normalization functions
    function scaleIntoPlasmaUnitsFromWei(uint256 value)
    public
    pure
    returns (uint128) {
        uint256 den = DENOMINATOR;
        require(value % den == 0, "amount has higher precision than possible");
        uint256 scaled = value / den;
        require(scaled < uint256(1) << 128, "deposit amount is too high");
        return uint128(scaled);
    }


    function scaleFromPlasmaUnitsIntoWei(uint128 value)
    public
    pure
    returns (uint256) {
        return uint256(value) * DENOMINATOR;
    }

    // stubs
    // verification
    function verifyProof(Circuit, uint256[8] memory, bytes32, bytes32, bytes32) internal view returns (bool valid);
}

contract Plasma is PlasmaStub, Verifier {
    // Implementation

    function verifyProof(Circuit circuitType, uint256[8] memory proof, bytes32 oldRoot, bytes32 newRoot, bytes32 finalHash)
        internal view returns (bool valid)
    {
        uint256 mask = (~uint256(0)) >> 3;
        uint256[14] memory vk;
        uint256[] memory gammaABC;
        if (circuitType == Circuit.DEPOSIT) {
            (vk, gammaABC) = getVkDepositCircuit();
        } else if (circuitType == Circuit.TRANSFER) {
            (vk, gammaABC) = getVkTransferCircuit();
        } else if (circuitType == Circuit.EXIT) {
            (vk, gammaABC) = getVkExitCircuit();
        } else {
            return false;
        }
        uint256[] memory inputs = new uint256[](3);
        inputs[0] = uint256(oldRoot);
        inputs[1] = uint256(newRoot);
        inputs[2] = uint256(finalHash) & mask;
        return Verify(vk, gammaABC, proof, inputs);
    }

}

// File: contracts/TwistedEdwards.sol

// This contract implements Twisted Edwards Curve arithmetics 
// for a SPECIFIC HARDCODED curve

// Since we don't use ABIv2, it's main purpose is to check that the point is
// in specific group

// If one wants external functionality - just wrap internal functions with
// Edwards Point represented as uint256[2]

// parameters: 
// a
// d
// prime field size 
// cofactor
// main group order


// TODO: should consider Montgommery ladder here
library TwistedEdwards {
    // EdwardsPoint public generator;

    struct EdwardsPoint {
        uint256 x;
        uint256 y;
    }

    // constructor (
    //     uint256[2] memory _generator
    // ) public {
    //     require(_generator[0] < getPrimeFieldSize(), "Generator X is not in the field");
    //     require(_generator[1] < getPrimeFieldSize(), "Generator Y is not in the field");
    //     // TODO: Check generator order
    //     generator = EdwardsPoint (_generator[0], _generator[1]);
    // }

    function getA()
    internal
    pure 
    returns (uint256) {
        return 21888242871839275222246405745257275088548364400416034343698204186575808495616;
    }

    function getD()
    internal
    pure 
    returns (uint256) {
        return 12181644023421730124874158521699555681764249180949974110617291017600649128846;
    }

    function getCofactor()
    internal
    pure 
    returns (uint256) {
        return 8;
    }

    function getMainGroupOrder()
    internal
    pure 
    returns (uint256) {
        return 2736030358979909402780800718157159386076813972158567259200215660948447373041;
    }

    function getPrimeFieldSize()
    internal
    pure 
    returns (uint256) {
        return 21888242871839275222246405745257275088548364400416034343698204186575808495617;
    }

    function fieldNegate(uint256 _x)
    internal
    pure
    returns (uint256) {
        return getPrimeFieldSize() - _x;
    }

    function negate(EdwardsPoint memory P)
    internal
    pure
    returns (EdwardsPoint memory S)
    {
        S = EdwardsPoint(fieldNegate(P.x), P.y);
    }

    function fieldInv(uint256 x) 
    internal 
    pure returns (uint256) {
        uint256 p = getPrimeFieldSize();
        uint256 a = x;
        if (a == 0)
            return 0;
        if (a > p)
            a = a % p;
        int256 t1;
        int256 t2 = 1;
        uint256 r1 = p;
        uint256 r2 = a;
        uint256 q;
        while (r2 != 0) {
            q = r1 / r2;
            (t1, t2, r1, r2) = (t2, t1 - int256(q) * t2, r2, r1 - q * r2);
        }
        if (t1 < 0)
            return (p - uint256(-t1));
        return uint256(t1);
    }

    // Infinity point is encoded as (0, 1)
    function isInfinity(EdwardsPoint memory P)
    internal
    pure
    returns (bool)
    {  
        return P.x == 0 && P.y == 1;
    }

    // group addition law
    // x3 = (x1*y2+y1*x2)/(1+d*x1*x2*y1*y2)
    // y3 = (y1*y2-a*x1*x2)/(1-d*x1*x2*y1*y2)

    // IMPORTANT! Take no assumption about a == -1 for now
    function add(EdwardsPoint memory P, EdwardsPoint memory Q)
    internal
    pure
    returns (EdwardsPoint memory S)
    {
        uint256 p = getPrimeFieldSize();
        uint256 a = getA();
        uint256 d = getD();

        // precompute and save x1*y2. x2*y1
        uint256 x1y2 = mulmod(P.x, Q.y, p);
        uint256 x2y1 = mulmod(Q.x, P.y, p);
        // calculate x1*x2 and y1*y2 for shortness
        uint256 x1x2 = mulmod(P.x, Q.x, p);
        uint256 y1y2 = mulmod(P.y, Q.y, p);

        uint256 x3_t = addmod(x1y2, x2y1, p);
        uint256 x3_b = fieldInv(addmod(1, mulmod( mulmod(d, x1y2, p), x2y1, p), p) );

        // manual negations here
        uint256 y3_t = addmod(y1y2, p - mulmod(a, x1x2, p), p);
        uint256 y3_b = fieldInv(addmod(1, p - mulmod( mulmod(d, x1y2, p), x2y1, p), p) );
        
        S = EdwardsPoint(mulmod(x3_t, x3_b, p), mulmod(y3_t, y3_b, p));
    }

    // group doubling law
    // x3 = (x1*y1+y1*x1)/(1+d*x1*x1*y1*y1)
    // y3 = (y1*y1-a*x1*x1)/(1-d*x1*x1*y1*y1)

    // IMPORTANT! Take no assumption about a == -1 for now
    function double(EdwardsPoint memory P)
    internal
    pure
    returns (EdwardsPoint memory S)
    {
        uint256 p = getPrimeFieldSize();
        uint256 a = getA();
        uint256 d = getD();

        // precompute and save x1*y2. x2*y1
        uint256 xx = mulmod(P.x, P.x, p);
        uint256 yy = mulmod(P.y, P.y, p);
        uint256 xy = mulmod(P.x, P.y, p);

        uint256 x3_t = addmod(xy, xy, p);
        uint256 x3_b = fieldInv(addmod(1, mulmod( mulmod(d, xy, p), xy, p), p) );

        // manual negations here
        uint256 y3_t = addmod(yy, p - mulmod(a, xx, p), p);
        uint256 y3_b = fieldInv(addmod(1, p - mulmod( mulmod(d, xx, p), yy, p), p) );
        
        S = EdwardsPoint(mulmod(x3_t, x3_b, p), mulmod(y3_t, y3_b, p));
    }

    
    function multiplyByScalar(
        uint256 d, 
        EdwardsPoint memory P
    ) 
    internal 
    pure
    returns (EdwardsPoint memory S)
    {
        
        S = EdwardsPoint(0,1);
        if (d == 0) {
            return S;
        }

        EdwardsPoint memory base = EdwardsPoint(P.x, P.y);

        // double and add
        uint256 remaining = d;
        while (remaining != 0) {
            if ((remaining & 1) != 0) {
                S = add(S, base);
            }
            remaining = remaining >> 1;
            base = double(base);
        }

    }

    // Check that a * x^2 + y^2 = 1 + d * x^2 * y^2
    function isOnCurve(
        EdwardsPoint memory P
    )
    internal
    pure
    returns (bool)
    {
        uint256 p = getPrimeFieldSize();
        uint256 a = getA();
        uint256 d = getD();

        uint256 xx = mulmod(P.x, P.x, p);
        uint256 yy = mulmod(P.y, P.y, p);

        uint256 lhs = addmod(mulmod(a, xx,p), yy, p);
        uint256 rhs = addmod(1, mulmod(d, mulmod(xx, yy, p), p), p);

        return lhs == rhs;
    }

    function isInCorrectGroup(
        EdwardsPoint memory P
    ) 
    internal 
    pure
    returns (bool)
    {
        uint256 order = getMainGroupOrder();
        return isInfinity(multiplyByScalar(order, P));
    }

    function isCorrectGroup(
        uint256[2] memory point
    )
    internal
    pure
    returns (bool)
    {
        EdwardsPoint memory P = EdwardsPoint(point[0], point[1]);
        return isInCorrectGroup(P);
    }

    function multiply(
        uint256 d,
        uint256[2] memory point
    )
    internal
    pure
    returns (uint256[2] memory result)
    {
        EdwardsPoint memory P = EdwardsPoint(point[0], point[1]);
        EdwardsPoint memory S = multiplyByScalar(d, P);
        result[0] = S.x;
        result[1] = S.y;
    }

    function checkOnCurve(
        uint256[2] memory point
    )
    internal
    pure
    returns (bool) {
        EdwardsPoint memory P = EdwardsPoint(point[0], point[1]);
        return isOnCurve(P);
    }

    // // Multiplication dP. P affine, wNAF: w=5
    // // Params: d, Px, Py
    // // Output: Jacobian Q
    // function _wnafMul(
    //     uint256 d, 
    //     EdwardsPoint memory P
    // ) 
    // internal 
    // pure 
    // returns (EdwardsPoint memory S)
    // {
    //     uint p = getPrimeFieldSize();
    //     if (d == 0) {
    //         return pointOfInfinity;
    //     }
    //     uint dwPtr; // points to array of NAF coefficients.
    //     uint i;

    //     // wNAF
    //     assembly
    //     {
    //         let dm := 0
    //         dwPtr := mload(0x40)
    //         mstore(0x40, add(dwPtr, 512)) // Should lower this.
    //     loop:
    //         jumpi(loop_end, iszero(d))
    //         jumpi(even, iszero(and(d, 1)))
    //         dm := mod(d, 32)
    //         mstore8(add(dwPtr, i), dm) // Don't store as signed - convert when reading.
    //         d := add(sub(d, dm), mul(gt(dm, 16), 32))
    //     even:
    //         d := div(d, 2)
    //         i := add(i, 1)
    //         jump(loop)
    //     loop_end:
    //     }

    //     // Pre calculation
    //     uint[3][8] memory PREC; // P, 3P, 5P, 7P, 9P, 11P, 13P, 15P
    //     PREC[0] = [P[0], P[1], 1];
    //     uint[3] memory X = _double(PREC[0]);
    //     PREC[1] = _addMixed(X, P);
    //     PREC[2] = _add(X, PREC[1]);
    //     PREC[3] = _add(X, PREC[2]);
    //     PREC[4] = _add(X, PREC[3]);
    //     PREC[5] = _add(X, PREC[4]);
    //     PREC[6] = _add(X, PREC[5]);
    //     PREC[7] = _add(X, PREC[6]);

    //     // Mult loop
    //     while(i > 0) {
    //         uint dj;
    //         uint pIdx;
    //         i--;
    //         assembly {
    //             dj := byte(0, mload(add(dwPtr, i)))
    //         }
    //         Q = _double(Q);
    //         if (dj > 16) {
    //             pIdx = (31 - dj) / 2; // These are the "negative ones", so invert y.
    //             Q = _add(Q, [PREC[pIdx][0], p - PREC[pIdx][1], PREC[pIdx][2] ]);
    //         }
    //         else if (dj > 0) {
    //             pIdx = (dj - 1) / 2;
    //             Q = _add(Q, [PREC[pIdx][0], PREC[pIdx][1], PREC[pIdx][2] ]);
    //         }
    //         if (Q[0] == pointOfInfinity[0] && Q[1] == pointOfInfinity[1] && Q[2] == pointOfInfinity[2]) {
    //             return Q;
    //         }
    //     }
    //     return Q;
    // }







}

// File: contracts/PlasmaDepositor.sol

contract PlasmaDepositor is Plasma {
    
    function deposit(uint256[2] memory publicKey, uint128 maxFee) 
    public 
    payable 
    active_only()
    {
        // only registed an account or do the lookup
        uint24 accountID = ethereumAddressToAccountID[msg.sender];
        if (accountID == 0) {
            // register new account
            uint256 packedKey = packAndValidatePublicKey(publicKey);
            ethereumAddressToAccountID[msg.sender] = nextAccountToRegister;
            Account memory freshAccount = Account(
                uint8(AccountState.REGISTERED),
                uint32(0),
                msg.sender,
                packedKey,
                uint32(0),
                uint32(0)
            );
            accountID = nextAccountToRegister;
            accounts[accountID] = freshAccount;
            // bump accounts counter
            nextAccountToRegister += 1;
        }
        depositInto(accountID, maxFee);
    }

    function depositInto(uint24 accountID, uint128 maxFee) 
    public 
    payable 
    active_only()
    {
        // this comparison is to avoid frontrunning between user
        // and the operator
        require(maxFee >= currentDepositBatchFee, "deposit fee is less than required");
        uint128 scaledValue = scaleIntoPlasmaUnitsFromWei(msg.value);
        require(scaledValue > currentDepositBatchFee, "deposit amount should cover the fee");
        require(accountID < nextAccountToRegister, "for now only allow to deposit into non-empty accounts");
        // read account info
        Account memory accountInformation = accounts[accountID];
        require(accountInformation.state == uint8(AccountState.REGISTERED), "can only deposit into registered account");

        // work with a deposit
        uint256 currentBatch = totalDepositRequests / DEPOSIT_BATCH_SIZE;
        // write aux info about the batch
        DepositBatch storage batch = depositBatches[currentBatch];
        // amount of time for an operator to process a batch is counted
        // from the first deposit in the batch
        if (batch.timestamp == 0) {
            batch.state = uint8(DepositBatchState.CREATED);
            batch.numRequests = uint24(0);
            batch.timestamp = uint64(block.timestamp);
            batch.batchFee = currentDepositBatchFee;
        }
        scaledValue -= currentDepositBatchFee;
        // get request in this batch for this account
        DepositRequest storage request = depositRequests[currentBatch][accountID];
        
        if (request.amount == 0) {
            // this is a new request in this batch
            batch.numRequests++;
            totalDepositRequests++;
        }
        request.amount += scaledValue;
        
        emit LogDepositRequest(currentBatch, accountID, accountInformation.publicKey, request.amount);
    }

    // allow users to cancel a deposit if the work on the next proof is not yet started
    function cancelDeposit()
    public
    {
        uint24 accountID = ethereumAddressToAccountID[msg.sender];
        require(accountID != 0, "trying to cancel a deposit for non-existing account");
        uint256 currentBatch = totalDepositRequests/DEPOSIT_BATCH_SIZE;
        uint256 requestsInThisBatch = totalDepositRequests % DEPOSIT_BATCH_SIZE;
        DepositBatch storage batch = depositBatches[currentBatch];
        // this check is most likely excessive, 
        require(batch.state == uint8(DepositBatchState.CREATED), "canceling is only allowed for batches that are not yet committed");
    
        DepositRequest storage request = depositRequests[currentBatch][accountID];
        uint128 depositAmount = request.amount;
        require(depositAmount > 0, "trying to cancel an empty deposit");

        // add a batch fee that was previously subtracted
        depositAmount += batch.batchFee;
        // log and clear the storage
        emit LogCancelDepositRequest(currentBatch, accountID);
        // if the first request in a batch is canceled - clear it to stop the countdown
        if (requestsInThisBatch == 0) { 
            delete depositBatches[currentBatch];
        }
        delete depositRequests[currentBatch][accountID];
        totalDepositRequests--;
        batch.numRequests--;

        msg.sender.transfer(scaleFromPlasmaUnitsIntoWei(depositAmount));
    }

    function startNextDepositBatch()
    public
    active_only()
    operator_only()
    {
        uint256 currentBatch = totalDepositRequests/DEPOSIT_BATCH_SIZE;
        uint256 inTheCurrentBatch = totalDepositRequests % DEPOSIT_BATCH_SIZE;
        if (inTheCurrentBatch != 0) {
            totalDepositRequests = (currentBatch + 1) * DEPOSIT_BATCH_SIZE;
        } else {
            revert("it's not necessary to bump the batch number");
        }
 
    }

    function changeDepositBatchFee(uint128 newBatchFee)
    public
    active_only()
    operator_only()
    {
        if (currentDepositBatchFee != newBatchFee) {
            currentDepositBatchFee = newBatchFee;
        } else {
            revert("fee adjustment makes no sense");
        } 
    }

    // pure function to calculate commitment formats
    function createPublicDataCommitmentForDeposit(uint32 blockNumber, bytes memory txDataPacked)
    public 
    pure
    returns (bytes32 h) {

        bytes32 initialHash = sha256(abi.encodePacked(uint256(blockNumber)));
        bytes32 finalHash = sha256(abi.encodePacked(initialHash, txDataPacked));
        
        return finalHash;
    }

    // on commitment to some block we just commit to SOME public data, that will be parsed 
    // ONLY when proof is presented
    
    function commitDepositBlock(
        uint256 batchNumber,
        uint24[DEPOSIT_BATCH_SIZE] memory accoundIDs,
        uint32 blockNumber, 
        bytes32 newRoot
    ) 
    public
    active_only()
    operator_only()
    {
        require(blockNumber == lastCommittedBlockNumber + 1, "may only commit next block");
        require(batchNumber == lastCommittedDepositBatch, "trying to commit batch out of order");
        
        DepositBatch storage batch = depositBatches[batchNumber];
        batch.state = uint8(DepositBatchState.COMMITTED);
        batch.blockNumber = blockNumber;
        batch.timestamp = uint64(block.timestamp);

        // pack the public data using information that it's already on-chain
        bytes memory txDataPacked = processDepositBlockData(batchNumber, accoundIDs);
        
        // create now commitments and write to storage
        bytes32 publicDataCommitment = createPublicDataCommitmentForDeposit(blockNumber, txDataPacked);

        blocks[blockNumber] = Block(
            uint8(Circuit.DEPOSIT), 
            uint64(block.timestamp + MAX_DELAY), 
            0, 
            newRoot, 
            publicDataCommitment, 
            msg.sender
        );
        emit BlockCommitted(blockNumber);
        lastCommittedBlockNumber++;
        lastCommittedDepositBatch++;
    }

    function verifyDepositBlock(
        uint256 batchNumber, 
        uint24[DEPOSIT_BATCH_SIZE] memory accoundIDs, 
        uint32 blockNumber, 
        uint256[8] memory proof
    ) 
    public 
    active_only()
    operator_only()
    {
        require(lastVerifiedBlockNumber < lastCommittedBlockNumber, "no committed block to verify");
        require(blockNumber == lastVerifiedBlockNumber + 1, "may only verify next block");
        require(batchNumber == lastVerifiedDepositBatch, "must verify batches in order");

        Block storage committed = blocks[blockNumber];
        require(committed.circuit == uint8(Circuit.DEPOSIT), "trying to prove the invalid circuit for this block number");

        DepositBatch storage batch = depositBatches[batchNumber];
        require(batch.blockNumber == blockNumber, "block number in referencing invalid batch number");
        batch.state = uint8(DepositBatchState.VERIFIED);
        batch.timestamp = uint64(block.timestamp);

        // do actual verification
        bool verification_success = verifyProof(
            Circuit.DEPOSIT,
            proof, 
            lastVerifiedRoot, 
            committed.newRoot, 
            committed.publicDataCommitment
        );
        require(verification_success, "invalid proof");

        emit BlockVerified(blockNumber);
        lastVerifiedBlockNumber++;
        lastVerifiedDepositBatch++;
        lastVerifiedRoot = committed.newRoot;

        uint128 totalFees = clearDepositBatch(batchNumber, accoundIDs);
        committed.totalFees = totalFees;
        balances[committed.prover] += totalFees;
        // process the block information
    }

    // transaction data is trivial: 3 bytes of in-plasma address, 16 bytes of amount and 32 bytes of public key
    function processDepositBlockData(uint256 batchNumber, uint24[DEPOSIT_BATCH_SIZE] memory accountIDs) 
    internal 
    view
    returns (bytes memory txData)
    {
        txData = new bytes(DEPOSIT_BATCH_SIZE * 51);
        uint256 chunk;
        uint128 requestAmount;
        uint256 publicKey;
        uint256 pointer = 32;
        uint24 specialAccountID = SPECIAL_ACCOUNT_DEPOSITS;
        uint256 numRequestsInBatch = uint256(depositBatches[batchNumber].numRequests);
        uint24 id;
        for (uint256 i = 0; i < numRequestsInBatch; i++) { 
            // this is a cheap way to ensure that all requests are unique, without O(n) MSTORE
            // it also automatically guarantees that all requests requests from the batch have been executed
            require(i == 0 || accountIDs[i] > accountIDs[i-1], "accountID are not properly ordered");
            id = accountIDs[i];
            require(id != specialAccountID, "batch should contain non-padding accounts first");
            requestAmount = depositRequests[batchNumber][id].amount;
            publicKey = accounts[id].publicKey;
            // put address and amount into the top bits of the chunk
            // address || amount || 0000...0000
            chunk = ((uint256(id) << 128) + uint256(requestAmount)) << 104;
            // and store it into place
            assembly {
                mstore(add(txData, pointer), chunk)
            }
            pointer += 19;
            assembly {
                mstore(add(txData, pointer), publicKey)
            }
            pointer += 32;
        }
        chunk = uint256(specialAccountID) << 232;
        publicKey = accounts[specialAccountID].publicKey;

        for (i = numRequestsInBatch; i < DEPOSIT_BATCH_SIZE; i++) { 
            id = accountIDs[i];
            require(id == specialAccountID, "padding should be done with special account number");
            assembly {
                mstore(add(txData, pointer), chunk)
            }
            pointer += 19;
            assembly {
                mstore(add(txData, pointer), publicKey)
            }
            pointer += 32;
        }

        return txData;
    }

    // transaction data is trivial: 3 bytes of in-plasma address and 16 bytes of amount
    function clearDepositBatch(uint256 batchNumber, uint24[DEPOSIT_BATCH_SIZE] memory accountIDs) 
    internal 
    returns (uint128 totalFees)
    {
        uint128 batchFee = depositBatches[batchNumber].batchFee;
        for (uint256 i = 0; i < DEPOSIT_BATCH_SIZE; i++) { 
            if (accountIDs[i] == 0) {
                // this was just a padding
                continue;
            }
            require(i == 0 || accountIDs[i] > accountIDs[i-1], "accountID are not properly ordered");
            DepositRequest storage request = depositRequests[batchNumber][accountIDs[i]];
            require(request.amount != 0, "trying to process an empty request and collect fees");
            delete depositRequests[batchNumber][accountIDs[i]];
            totalFees += batchFee;
        }
        return totalFees;
    }

    function packAndValidatePublicKey(uint256[2] memory publicKey)
    public
    pure
    returns(uint256 packed) {
        require(TwistedEdwards.checkOnCurve(publicKey), "public key must be on the curve");
        // group check + packing
        packed = publicKey[1] + ((publicKey[0] & 1) << 255);
        return packed;
    }

    function () external payable {
        address callee = transactor;
        assembly {
            let memoryPointer := mload(0x40)
            calldatacopy(memoryPointer, 0, calldatasize)
            let newFreeMemoryPointer := add(memoryPointer, calldatasize)
            mstore(0x40, newFreeMemoryPointer)
            let retVal := delegatecall(sub(gas, 2000), callee, memoryPointer, calldatasize, newFreeMemoryPointer, 0x40)
            let retDataSize := returndatasize
            returndatacopy(newFreeMemoryPointer, 0, retDataSize)
            switch retVal case 0 { revert(0,0) } default { return(newFreeMemoryPointer, retDataSize) }
        }
    }

}

// File: contracts/PlasmaContract.sol

contract PlasmaContract is PlasmaDepositor {
    // uint24 constant operatorsAccounts = 4;
    // uint24 public nextAccountToRegister = operatorsAccounts;

    // // create technological accounts for an operator. 
    // constructor(uint256[operatorsAccounts - 1] memory defaultPublicKeys, address _transactor, address _exitor) public {
    //     lastVerifiedRoot = EMPTY_TREE_ROOT;
    //     operators[msg.sender] = true;
    //     // account number 0 is NEVER registered
    //     Account memory freshAccount;
    //     for (uint24 i = 1; i < operatorsAccounts; i++) {
    //         freshAccount = Account(
    //             uint8(AccountState.REGISTERED),
    //             0,
    //             msg.sender,
    //             defaultPublicKeys[i-1]
    //         );
    //         accounts[i] = freshAccount;
    //     }
    //     transactor = _transactor;
    //     exitor = _exitor;
    // }

    constructor(address _transactor, address _exitor) public {
        nextAccountToRegister = 2;
        lastVerifiedRoot = EMPTY_TREE_ROOT;
        operators[msg.sender] = true;
        transactor = _transactor;
        exitor = _exitor;
    }
}

Contract ABI
[{"constant":true,"inputs":[],"name":"lastVerifiedRoot","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"operators","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"startNextDepositBatch","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"SPECIAL_ACCOUNT_EXITS","outputs":[{"name":"","type":"uint24"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalDepositRequests","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"exitor","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"balances","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalExitRequests","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"},{"name":"","type":"uint32"}],"name":"exitLeafs","outputs":[{"name":"nextID","type":"uint32"},{"name":"amount","type":"uint128"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"value","type":"uint256"}],"name":"scaleIntoPlasmaUnitsFromWei","outputs":[{"name":"","type":"uint128"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"DEPOSIT_BATCH_SIZE","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"cancelDeposit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"MAX_DELAY","outputs":[{"name":"","type":"uint64"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"lastCommittedExitBatch","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"},{"name":"","type":"uint24"}],"name":"depositRequests","outputs":[{"name":"amount","type":"uint128"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"batchNumber","type":"uint256"},{"name":"accoundIDs","type":"uint24[1]"},{"name":"blockNumber","type":"uint32"},{"name":"newRoot","type":"bytes32"}],"name":"commitDepositBlock","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"currentExitBatchFee","outputs":[{"name":"","type":"uint128"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint32"}],"name":"blocks","outputs":[{"name":"circuit","type":"uint8"},{"name":"deadline","type":"uint64"},{"name":"totalFees","type":"uint128"},{"name":"newRoot","type":"bytes32"},{"name":"publicDataCommitment","type":"bytes32"},{"name":"prover","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"accountID","type":"uint24"},{"name":"maxFee","type":"uint128"}],"name":"depositInto","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[{"name":"blockNumber","type":"uint32"},{"name":"txDataPacked","type":"bytes"}],"name":"createPublicDataCommitmentForDeposit","outputs":[{"name":"h","type":"bytes32"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"lastVerifiedDepositBatch","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"TRANSFER_BLOCK_SIZE","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"stopped","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint24"}],"name":"accounts","outputs":[{"name":"state","type":"uint8"},{"name":"exitBatchNumber","type":"uint32"},{"name":"owner","type":"address"},{"name":"publicKey","type":"uint256"},{"name":"exitListHead","type":"uint32"},{"name":"exitListTail","type":"uint32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"lastCommittedBlockNumber","outputs":[{"name":"","type":"uint32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"ethereumAddressToAccountID","outputs":[{"name":"","type":"uint24"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"publicKey","type":"uint256[2]"},{"name":"maxFee","type":"uint128"}],"name":"deposit","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[],"name":"transactor","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"DENOMINATOR","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"batchNumber","type":"uint256"},{"name":"accoundIDs","type":"uint24[1]"},{"name":"blockNumber","type":"uint32"},{"name":"proof","type":"uint256[8]"}],"name":"verifyDepositBlock","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"exitBatches","outputs":[{"name":"state","type":"uint8"},{"name":"blockNumber","type":"uint32"},{"name":"timestamp","type":"uint64"},{"name":"batchFee","type":"uint128"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"DEADLINE","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"currentDepositBatchFee","outputs":[{"name":"","type":"uint128"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"value","type":"uint128"}],"name":"scaleFromPlasmaUnitsIntoWei","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"name":"publicKey","type":"uint256[2]"}],"name":"packAndValidatePublicKey","outputs":[{"name":"packed","type":"uint256"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"SPECIAL_ACCOUNT_DEPOSITS","outputs":[{"name":"","type":"uint24"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"lastVerifiedExitBatch","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"nextAccountToRegister","outputs":[{"name":"","type":"uint24"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"lastVerifiedBlockNumber","outputs":[{"name":"","type":"uint32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"newBatchFee","type":"uint128"}],"name":"changeDepositBatchFee","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"depositBatches","outputs":[{"name":"state","type":"uint8"},{"name":"numRequests","type":"uint24"},{"name":"blockNumber","type":"uint32"},{"name":"timestamp","type":"uint64"},{"name":"batchFee","type":"uint128"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"lastCommittedDepositBatch","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"_transactor","type":"address"},{"name":"_exitor","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"anonymous":false,"inputs":[{"indexed":true,"name":"blockNumber","type":"uint32"}],"name":"BlockCommitted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"blockNumber","type":"uint32"}],"name":"BlockVerified","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"batchNumber","type":"uint256"},{"indexed":true,"name":"accountID","type":"uint24"},{"indexed":true,"name":"publicKey","type":"uint256"},{"indexed":false,"name":"amount","type":"uint128"}],"name":"LogDepositRequest","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"batchNumber","type":"uint256"},{"indexed":true,"name":"accountID","type":"uint24"}],"name":"LogCancelDepositRequest","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"batchNumber","type":"uint256"},{"indexed":true,"name":"accountID","type":"uint24"}],"name":"LogExitRequest","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"batchNumber","type":"uint256"},{"indexed":true,"name":"accountID","type":"uint24"}],"name":"LogCancelExitRequest","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"ethereumAddress","type":"address"},{"indexed":true,"name":"blockNumber","type":"uint32"}],"name":"LogExit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"ethereumAddress","type":"address"},{"indexed":true,"name":"blockNumber","type":"uint32"},{"indexed":false,"name":"accountID","type":"uint24"}],"name":"LogCompleteExit","type":"event"}]

Contract Creation Code
608060405234801561001057600080fd5b5060405160408062005db783398101806040528101908080519060200190929190805190602001909291905050506002600a60106101000a81548162ffffff021916908362ffffff1602179055507e3f7e15e4de3453fe13e11fb4b007f1fce6a5b0f0353b3b8208910143aaa2f76001026006816000191690555060018060003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555081601360006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555080601460006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055505050615c4180620001766000396000f300608060405260043610610204576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806309b7f4971461025e57806313e7c9d81461029157806318a63d9c146102ec5780631e8072a214610303578063254e88e2146103385780632713ad691461036357806327e235e3146103ba57806329a081ac146104115780632ad67a961461043c5780632c87c6c9146104da578063351eb7511461053f5780633d5616021461056a5780634125ff90146105815780634c5ff682146105c05780635300e410146105eb578063533de30a1461065f57806357d2ae24146106d95780635cd0783e146107285780635df1b4331461080c578063609293b71461084d57806363d078aa146108e257806369935b691461090d57806375f12b21146109385780637dc38ab914610967578063838e204914610a265780638512153f14610a5d57806385611d2614610abe5780638ecb72d114610b1f578063918f867414610b7657806395b5d61714610ba15780639d9c941914610c3d578063a082c86e14610cdd578063a15ff0c314610d08578063a315c91b14610d57578063c47ba19d14610daa578063cd7543c014610e10578063ed03f56314610e45578063f47932ad14610e70578063f4c163a414610ea5578063f648a6c714610edc578063fb0cd20f14610f1b578063fb1d501014610fcc575b6000601360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1690506040513660008237368101806040526040813684866107d05a03f43d806000843e8160008114610259578184f35b600080fd5b34801561026a57600080fd5b50610273610ff7565b60405180826000191660001916815260200191505060405180910390f35b34801561029d57600080fd5b506102d2600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610ffd565b604051808215151515815260200191505060405180910390f35b3480156102f857600080fd5b5061030161101d565b005b34801561030f57600080fd5b5061031861128e565b604051808262ffffff1662ffffff16815260200191505060405180910390f35b34801561034457600080fd5b5061034d611293565b6040518082815260200191505060405180910390f35b34801561036f57600080fd5b50610378611299565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156103c657600080fd5b506103fb600480360381019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506112bf565b6040518082815260200191505060405180910390f35b34801561041d57600080fd5b506104266112d7565b6040518082815260200191505060405180910390f35b34801561044857600080fd5b5061048d600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803563ffffffff1690602001909291905050506112dd565b604051808363ffffffff1663ffffffff168152602001826fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff1681526020019250505060405180910390f35b3480156104e657600080fd5b506105056004803603810190808035906020019092919050505061133a565b60405180826fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561054b57600080fd5b50610554611487565b6040518082815260200191505060405180910390f35b34801561057657600080fd5b5061057f61148c565b005b34801561058d57600080fd5b50610596611974565b604051808267ffffffffffffffff1667ffffffffffffffff16815260200191505060405180910390f35b3480156105cc57600080fd5b506105d561197b565b6040518082815260200191505060405180910390f35b3480156105f757600080fd5b5061062560048036038101908080359060200190929190803562ffffff169060200190929190505050611981565b60405180826fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561066b57600080fd5b506106d7600480360381019080803590602001909291908060200190600180602002604051908101604052809291908260016020028082843782019150505050509192919290803563ffffffff16906020019092919080356000191690602001909291905050506119c8565b005b3480156106e557600080fd5b506106ee611f69565b60405180826fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561073457600080fd5b50610759600480360381019080803563ffffffff169060200190929190505050611f8b565b604051808760ff1660ff1681526020018667ffffffffffffffff1667ffffffffffffffff168152602001856fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff168152602001846000191660001916815260200183600019166000191681526020018273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001965050505050505060405180910390f35b61084b600480360381019080803562ffffff16906020019092919080356fffffffffffffffffffffffffffffffff169060200190929190505050612024565b005b34801561085957600080fd5b506108c4600480360381019080803563ffffffff169060200190929190803590602001908201803590602001908080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050509192919290505050612815565b60405180826000191660001916815260200191505060405180910390f35b3480156108ee57600080fd5b506108f7612a0e565b6040518082815260200191505060405180910390f35b34801561091957600080fd5b50610922612a14565b6040518082815260200191505060405180910390f35b34801561094457600080fd5b5061094d612a19565b604051808215151515815260200191505060405180910390f35b34801561097357600080fd5b50610997600480360381019080803562ffffff169060200190929190505050612a2c565b604051808760ff1660ff1681526020018663ffffffff1663ffffffff1681526020018573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018481526020018363ffffffff1663ffffffff1681526020018263ffffffff1663ffffffff168152602001965050505050505060405180910390f35b348015610a3257600080fd5b50610a3b612ac5565b604051808263ffffffff1663ffffffff16815260200191505060405180910390f35b348015610a6957600080fd5b50610a9e600480360381019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612adb565b604051808262ffffff1662ffffff16815260200191505060405180910390f35b610b1d600480360381019080806040019060028060200260405190810160405280929190826002602002808284378201915050505050919291929080356fffffffffffffffffffffffffffffffff169060200190929190505050612afd565b005b348015610b2b57600080fd5b50610b34612e56565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b348015610b8257600080fd5b50610b8b612e7c565b6040518082815260200191505060405180910390f35b348015610bad57600080fd5b50610c3b600480360381019080803590602001909291908060200190600180602002604051908101604052809291908260016020028082843782019150505050509192919290803563ffffffff169060200190929190806101000190600880602002604051908101604052809291908260086020028082843782019150505050509192919290505050612e85565b005b348015610c4957600080fd5b50610c68600480360381019080803590602001909291905050506135d0565b604051808560ff1660ff1681526020018463ffffffff1663ffffffff1681526020018367ffffffffffffffff1667ffffffffffffffff168152602001826fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff16815260200194505050505060405180910390f35b348015610ce957600080fd5b50610cf261364d565b6040518082815260200191505060405180910390f35b348015610d1457600080fd5b50610d1d613653565b60405180826fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b348015610d6357600080fd5b50610d9460048036038101908080356fffffffffffffffffffffffffffffffff169060200190929190505050613675565b6040518082815260200191505060405180910390f35b348015610db657600080fd5b50610dfa6004803603810190808060400190600280602002604051908101604052809291908260026020028082843782019150505050509192919290505050613698565b6040518082815260200191505060405180910390f35b348015610e1c57600080fd5b50610e25613754565b604051808262ffffff1662ffffff16815260200191505060405180910390f35b348015610e5157600080fd5b50610e5a613759565b6040518082815260200191505060405180910390f35b348015610e7c57600080fd5b50610e8561375f565b604051808262ffffff1662ffffff16815260200191505060405180910390f35b348015610eb157600080fd5b50610eba613774565b604051808263ffffffff1663ffffffff16815260200191505060405180910390f35b348015610ee857600080fd5b50610f1960048036038101908080356fffffffffffffffffffffffffffffffff169060200190929190505050613789565b005b348015610f2757600080fd5b50610f4660048036038101908080359060200190929190505050613a1c565b604051808660ff1660ff1681526020018562ffffff1662ffffff1681526020018463ffffffff1663ffffffff1681526020018367ffffffffffffffff1667ffffffffffffffff168152602001826fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff1681526020019550505050505060405180910390f35b348015610fd857600080fd5b50610fe1613aae565b6040518082815260200191505060405180910390f35b60065481565b60016020528060005260406000206000915054906101000a900460ff1681565b600080600560009054906101000a900460ff161515156110cb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260278152602001807f636f6e74726163742073686f756c64206e6f7420626520676c6f62616c6c792081526020017f73746f707065640000000000000000000000000000000000000000000000000081525060400191505060405180910390fd5b60011515600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615151415156111b9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001807f73656e6465722073686f756c64206265206f6e65206f6620746865206f70657281526020017f61746f727300000000000000000000000000000000000000000000000000000081525060400191505060405180910390fd5b60016007548115156111c757fe5b04915060016007548115156111d857fe5b0690506000811415156111f65760018083010260078190555061128a565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602b8152602001807f69742773206e6f74206e656365737361727920746f2062756d7020746865206281526020017f61746368206e756d62657200000000000000000000000000000000000000000081525060400191505060405180910390fd5b5050565b600081565b60075481565b601460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60026020528060005260406000206000915090505481565b600d5481565b6012602052816000526040600020602052806000526040600020600091509150508060000160009054906101000a900463ffffffff16908060000160049054906101000a90046fffffffffffffffffffffffffffffffff16905082565b600080600064e8d4a5100091506000828581151561135457fe5b061415156113f0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260298152602001807f616d6f756e74206861732068696768657220707265636973696f6e207468616e81526020017f20706f737369626c65000000000000000000000000000000000000000000000081525060400191505060405180910390fd5b81848115156113fb57fe5b049050608060019060020a028110151561147d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f6465706f73697420616d6f756e7420697320746f6f206869676800000000000081525060200191505060405180910390fd5b8092505050919050565b600181565b600080600080600080600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900462ffffff16955060008662ffffff161415151561158a576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260338152602001807f747279696e6720746f2063616e63656c2061206465706f73697420666f72206e81526020017f6f6e2d6578697374696e67206163636f756e740000000000000000000000000081525060400191505060405180910390fd5b600160075481151561159857fe5b04945060016007548115156115a957fe5b069350600c60008681526020019081526020016000209250600060028111156115ce57fe5b60ff168360000160009054906101000a900460ff1660ff16141515611681576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260408152602001807f63616e63656c696e67206973206f6e6c7920616c6c6f77656420666f7220626181526020017f7463686573207468617420617265206e6f742079657420636f6d6d697474656481525060400191505060405180910390fd5b600b600086815260200190815260200160002060008762ffffff1662ffffff16815260200190815260200160002091508160000160009054906101000a90046fffffffffffffffffffffffffffffffff1690506000816fffffffffffffffffffffffffffffffff16111515611784576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260218152602001807f747279696e6720746f2063616e63656c20616e20656d707479206465706f736981526020017f740000000000000000000000000000000000000000000000000000000000000081525060400191505060405180910390fd5b8260000160109054906101000a90046fffffffffffffffffffffffffffffffff16810190508562ffffff16857fd99f8eb80f2e84189fe41fb9bed3506f73da9be70a0df39e2b4a997e92dbd61a60405160405180910390a3600084141561187b57600c6000868152602001908152602001600020600080820160006101000a81549060ff02191690556000820160016101000a81549062ffffff02191690556000820160046101000a81549063ffffffff02191690556000820160086101000a81549067ffffffffffffffff02191690556000820160106101000a8154906fffffffffffffffffffffffffffffffff021916905550505b600b600086815260200190815260200160002060008762ffffff1662ffffff168152602001908152602001600020600080820160006101000a8154906fffffffffffffffffffffffffffffffff021916905550506007600081548092919060019003919050555082600001600181819054906101000a900462ffffff16809291906001900391906101000a81548162ffffff021916908362ffffff160217905550503373ffffffffffffffffffffffffffffffffffffffff166108fc61194083613675565b9081150290604051600060405180830381858888f1935050505015801561196b573d6000803e3d6000fd5b50505050505050565b6201518081565b600e5481565b600b602052816000526040600020602052806000526040600020600091509150508060000160009054906101000a90046fffffffffffffffffffffffffffffffff16905081565b600060606000600560009054906101000a900460ff16151515611a79576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260278152602001807f636f6e74726163742073686f756c64206e6f7420626520676c6f62616c6c792081526020017f73746f707065640000000000000000000000000000000000000000000000000081525060400191505060405180910390fd5b60011515600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515141515611b67576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001807f73656e6465722073686f756c64206265206f6e65206f6620746865206f70657281526020017f61746f727300000000000000000000000000000000000000000000000000000081525060400191505060405180910390fd5b6001600560019054906101000a900463ffffffff160163ffffffff168563ffffffff16141515611bff576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f6d6179206f6e6c7920636f6d6d6974206e65787420626c6f636b00000000000081525060200191505060405180910390fd5b60085487141515611c9e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260238152602001807f747279696e6720746f20636f6d6d6974206261746368206f7574206f66206f7281526020017f646572000000000000000000000000000000000000000000000000000000000081525060400191505060405180910390fd5b600c6000888152602001908152602001600020925060016002811115611cc057fe5b8360000160006101000a81548160ff021916908360ff160217905550848360000160046101000a81548163ffffffff021916908363ffffffff160217905550428360000160086101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550611d348787613ab4565b9150611d408583612815565b905060c06040519081016040528060006002811115611d5b57fe5b60ff1681526020016201518067ffffffffffffffff16420167ffffffffffffffff16815260200160006fffffffffffffffffffffffffffffffff16815260200185600019168152602001826000191681526020013373ffffffffffffffffffffffffffffffffffffffff168152506000808763ffffffff1663ffffffff16815260200190815260200160002060008201518160000160006101000a81548160ff021916908360ff16021790555060208201518160000160016101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555060408201518160000160096101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550606082015181600101906000191690556080820151816002019060001916905560a08201518160030160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055509050508463ffffffff167fdf39762be389bd636a9efb2e4f3b26ac7d22eda4f0840f389209987a09e50fc960405160405180910390a26005600181819054906101000a900463ffffffff168092919060010191906101000a81548163ffffffff021916908363ffffffff1602179055505060086000815480929190600101919050555050505050505050565b601060009054906101000a90046fffffffffffffffffffffffffffffffff1681565b60006020528060005260406000206000915090508060000160009054906101000a900460ff16908060000160019054906101000a900467ffffffffffffffff16908060000160099054906101000a90046fffffffffffffffffffffffffffffffff16908060010154908060020154908060030160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905086565b600061202e615ae8565b6000806000600560009054906101000a900460ff161515156120de576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260278152602001807f636f6e74726163742073686f756c64206e6f7420626520676c6f62616c6c792081526020017f73746f707065640000000000000000000000000000000000000000000000000081525060400191505060405180910390fd5b600a60009054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff16866fffffffffffffffffffffffffffffffff16101515156121be576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260218152602001807f6465706f73697420666565206973206c657373207468616e207265717569726581526020017f640000000000000000000000000000000000000000000000000000000000000081525060400191505060405180910390fd5b6121c73461133a565b9450600a60009054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff16856fffffffffffffffffffffffffffffffff161115156122a8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260238152602001807f6465706f73697420616d6f756e742073686f756c6420636f766572207468652081526020017f666565000000000000000000000000000000000000000000000000000000000081525060400191505060405180910390fd5b600a60109054906101000a900462ffffff1662ffffff168762ffffff16101515612360576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260358152602001807f666f72206e6f77206f6e6c7920616c6c6f7720746f206465706f73697420696e81526020017f746f206e6f6e2d656d707479206163636f756e7473000000000000000000000081525060400191505060405180910390fd5b600460008862ffffff1662ffffff16815260200190815260200160002060c060405190810160405290816000820160009054906101000a900460ff1660ff1660ff1681526020016000820160019054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160059054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600182015481526020016002820160009054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016002820160049054906101000a900463ffffffff1663ffffffff1663ffffffff168152505093506001600381111561248757fe5b60ff16846000015160ff1614151561252d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260288152602001807f63616e206f6e6c79206465706f73697420696e746f207265676973746572656481526020017f206163636f756e7400000000000000000000000000000000000000000000000081525060400191505060405180910390fd5b600160075481151561253b57fe5b049250600c6000848152602001908152602001600020915060008260000160089054906101000a900467ffffffffffffffff1667ffffffffffffffff16141561264e576000600281111561258b57fe5b8260000160006101000a81548160ff021916908360ff16021790555060008260000160016101000a81548162ffffff021916908362ffffff160217905550428260000160086101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550600a60009054906101000a90046fffffffffffffffffffffffffffffffff168260000160106101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055505b600a60009054906101000a90046fffffffffffffffffffffffffffffffff1685039450600b600084815260200190815260200160002060008862ffffff1662ffffff168152602001908152602001600020905060008160000160009054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff1614156127295781600001600181819054906101000a900462ffffff168092919060010191906101000a81548162ffffff021916908362ffffff160217905550506007600081548092919060010191905055505b848160000160008282829054906101000a90046fffffffffffffffffffffffffffffffff160192506101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff16021790555083606001518762ffffff16847f77576c82d939ce0a49902463e0dd51c0257e560ff4f55a51a702af4ed76912668460000160009054906101000a90046fffffffffffffffffffffffffffffffff1660405180826fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff16815260200191505060405180910390a450505050505050565b600080600060028563ffffffff16604051602001808281526020019150506040516020818303038152906040526040518082805190602001908083835b6020831015156128775780518252602082019150602081019050602083039250612852565b6001836020036101000a0380198251168184511680821785525050505050509050019150506020604051808303816000865af11580156128bb573d6000803e3d6000fd5b5050506040513d60208110156128d057600080fd5b810190808051906020019092919050505091506002828560405160200180836000191660001916815260200182805190602001908083835b60208310151561292d5780518252602082019150602081019050602083039250612908565b6001836020036101000a038019825116818451168082178552505050505050905001925050506040516020818303038152906040526040518082805190602001908083835b6020831015156129975780518252602082019150602081019050602083039250612972565b6001836020036101000a0380198251168184511680821785525050505050509050019150506020604051808303816000865af11580156129db573d6000803e3d6000fd5b5050506040513d60208110156129f057600080fd5b81019080805190602001909291905050509050809250505092915050565b60095481565b608081565b600560009054906101000a900460ff1681565b60046020528060005260406000206000915090508060000160009054906101000a900460ff16908060000160019054906101000a900463ffffffff16908060000160059054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060010154908060020160009054906101000a900463ffffffff16908060020160049054906101000a900463ffffffff16905086565b600560019054906101000a900463ffffffff1681565b60036020528060005260406000206000915054906101000a900462ffffff1681565b600080612b08615ae8565b600560009054906101000a900460ff16151515612bb3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260278152602001807f636f6e74726163742073686f756c64206e6f7420626520676c6f62616c6c792081526020017f73746f707065640000000000000000000000000000000000000000000000000081525060400191505060405180910390fd5b600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900462ffffff16925060008362ffffff161415612e4557612c1b85613698565b9150600a60109054906101000a900462ffffff16600360003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548162ffffff021916908362ffffff16021790555060c06040519081016040528060016003811115612ca357fe5b60ff168152602001600063ffffffff1681526020013373ffffffffffffffffffffffffffffffffffffffff168152602001838152602001600063ffffffff168152602001600063ffffffff168152509050600a60109054906101000a900462ffffff16925080600460008562ffffff1662ffffff16815260200190815260200160002060008201518160000160006101000a81548160ff021916908360ff16021790555060208201518160000160016101000a81548163ffffffff021916908363ffffffff16021790555060408201518160000160056101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506060820151816001015560808201518160020160006101000a81548163ffffffff021916908363ffffffff16021790555060a08201518160020160046101000a81548163ffffffff021916908363ffffffff1602179055509050506001600a60108282829054906101000a900462ffffff160192506101000a81548162ffffff021916908362ffffff1602179055505b612e4f8385612024565b5050505050565b601360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b64e8d4a5100081565b600080600080600560009054906101000a900460ff16151515612f36576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260278152602001807f636f6e74726163742073686f756c64206e6f7420626520676c6f62616c6c792081526020017f73746f707065640000000000000000000000000000000000000000000000000081525060400191505060405180910390fd5b60011515600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515141515613024576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001807f73656e6465722073686f756c64206265206f6e65206f6620746865206f70657281526020017f61746f727300000000000000000000000000000000000000000000000000000081525060400191505060405180910390fd5b600560019054906101000a900463ffffffff1663ffffffff166005809054906101000a900463ffffffff1663ffffffff161015156130ca576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601c8152602001807f6e6f20636f6d6d697474656420626c6f636b20746f207665726966790000000081525060200191505060405180910390fd5b60016005809054906101000a900463ffffffff160163ffffffff168663ffffffff16141515613161576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601a8152602001807f6d6179206f6e6c7920766572696679206e65787420626c6f636b00000000000081525060200191505060405180910390fd5b600954881415156131da576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601c8152602001807f6d75737420766572696679206261746368657320696e206f726465720000000081525060200191505060405180910390fd5b6000808763ffffffff1663ffffffff16815260200190815260200160002093506000600281111561320757fe5b60ff168460000160009054906101000a900460ff1660ff161415156132ba576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260398152602001807f747279696e6720746f2070726f76652074686520696e76616c6964206369726381526020017f75697420666f72207468697320626c6f636b206e756d6265720000000000000081525060400191505060405180910390fd5b600c600089815260200190815260200160002092508563ffffffff168360000160049054906101000a900463ffffffff1663ffffffff1614151561338c576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260308152602001807f626c6f636b206e756d62657220696e207265666572656e63696e6720696e766181526020017f6c6964206261746368206e756d6265720000000000000000000000000000000081525060400191505060405180910390fd5b60028081111561339857fe5b8360000160006101000a81548160ff021916908360ff160217905550428360000160086101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506133f760008660065487600101548860020154613ec3565b915081151561346e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252600d8152602001807f696e76616c69642070726f6f660000000000000000000000000000000000000081525060200191505060405180910390fd5b8563ffffffff167fca558d7524956f89ce1ec833efe8a265ed2b1e92b20ff4fe2fb87fb1a042e52460405160405180910390a260058081819054906101000a900463ffffffff168092919060010191906101000a81548163ffffffff021916908363ffffffff16021790555050600960008154809291906001019190505550836001015460068160001916905550613506888861403b565b9050808460000160096101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550806fffffffffffffffffffffffffffffffff16600260008660030160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825401925050819055505050505050505050565b60116020528060005260406000206000915090508060000160009054906101000a900460ff16908060000160019054906101000a900463ffffffff16908060000160059054906101000a900467ffffffffffffffff169080600001600d9054906101000a90046fffffffffffffffffffffffffffffffff16905084565b610e1081565b600a60009054906101000a90046fffffffffffffffffffffffffffffffff1681565b600064e8d4a51000826fffffffffffffffffffffffffffffffff16029050919050565b60006136a38261431a565b1515613717576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f7075626c6963206b6579206d757374206265206f6e207468652063757276650081525060200191505060405180910390fd5b60ff600183600060028110151561372a57fe5b6020020151169060020a0282600160028110151561374457fe5b6020020151019050809050919050565b600181565b600f5481565b600a60109054906101000a900462ffffff1681565b6005809054906101000a900463ffffffff1681565b600560009054906101000a900460ff16151515613834576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260278152602001807f636f6e74726163742073686f756c64206e6f7420626520676c6f62616c6c792081526020017f73746f707065640000000000000000000000000000000000000000000000000081525060400191505060405180910390fd5b60011515600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161515141515613922576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260258152602001807f73656e6465722073686f756c64206265206f6e65206f6620746865206f70657281526020017f61746f727300000000000000000000000000000000000000000000000000000081525060400191505060405180910390fd5b806fffffffffffffffffffffffffffffffff16600a60009054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff161415156139ab5780600a60006101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550613a19565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f6665652061646a7573746d656e74206d616b6573206e6f2073656e736500000081525060200191505060405180910390fd5b50565b600c6020528060005260406000206000915090508060000160009054906101000a900460ff16908060000160019054906101000a900462ffffff16908060000160049054906101000a900463ffffffff16908060000160089054906101000a900467ffffffffffffffff16908060000160109054906101000a90046fffffffffffffffffffffffffffffffff16905085565b60085481565b606060008060008060008060008060336001026040519080825280601f01601f191660200182016040528015613af95781602001602082028038833980820191505090505b5098506020945060019350600c60008c815260200190815260200160002060000160019054906101000a900462ffffff1662ffffff169250600090505b82811015613d94576000811480613b7d57508960018203600181101515613b5957fe5b602002015162ffffff168a82600181101515613b7157fe5b602002015162ffffff16115b1515613c17576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260228152602001807f6163636f756e74494420617265206e6f742070726f7065726c79206f7264657281526020017f656400000000000000000000000000000000000000000000000000000000000081525060400191505060405180910390fd5b8981600181101515613c2557fe5b602002015191508362ffffff168262ffffff1614151515613cd4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602f8152602001807f62617463682073686f756c6420636f6e7461696e206e6f6e2d70616464696e6781526020017f206163636f756e7473206669727374000000000000000000000000000000000081525060400191505060405180910390fd5b600b60008c815260200190815260200160002060008362ffffff1662ffffff16815260200190815260200160002060000160009054906101000a90046fffffffffffffffffffffffffffffffff169650600460008362ffffff1662ffffff1681526020019081526020016000206001015495506068876fffffffffffffffffffffffffffffffff1660808462ffffff169060020a02019060020a02975087858a015260138501945085858a01526020850194508080600101915050613b36565b60e88462ffffff169060020a029750600460008562ffffff1662ffffff1681526020019081526020016000206001015495508290505b6001811015613eb2578981600181101515613de157fe5b602002015191508362ffffff168262ffffff16141515613e8f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260328152602001807f70616464696e672073686f756c6420626520646f6e652077697468207370656381526020017f69616c206163636f756e74206e756d626572000000000000000000000000000081525060400191505060405180910390fd5b87858a015260138501945085858a01526020850194508080600101915050613dca565b889850505050505050505092915050565b600080613ece615b4a565b60608060036000199060020a9004935060006002811115613eeb57fe5b8a6002811115613ef757fe5b1415613f1257613f05614372565b8093508194505050613f84565b60016002811115613f1f57fe5b8a6002811115613f2b57fe5b1415613f4657613f396148c1565b8093508194505050613f83565b600280811115613f5257fe5b8a6002811115613f5e57fe5b1415613f7957613f6c614e10565b8093508194505050613f82565b6000945061402e565b5b5b6003604051908082528060200260200182016040528015613fb45781602001602082028038833980820191505090505b5090508760019004816000815181101515613fcb57fe5b90602001906020020181815250508660019004816001815181101515613fed57fe5b90602001906020020181815250508386600190041681600281518110151561401157fe5b906020019060200201818152505061402b83838b8461535f565b94505b5050505095945050505050565b600080600080600c600087815260200190815260200160002060000160109054906101000a90046fffffffffffffffffffffffffffffffff169250600091505b600182101561430e576000858360018110151561409457fe5b602002015162ffffff1614156140a957614301565b60008214806140e8575084600183036001811015156140c457fe5b602002015162ffffff1685836001811015156140dc57fe5b602002015162ffffff16115b1515614182576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260228152602001807f6163636f756e74494420617265206e6f742070726f7065726c79206f7264657281526020017f656400000000000000000000000000000000000000000000000000000000000081525060400191505060405180910390fd5b600b6000878152602001908152602001600020600086846001811015156141a557fe5b602002015162ffffff1662ffffff168152602001908152602001600020905060008160000160009054906101000a90046fffffffffffffffffffffffffffffffff166fffffffffffffffffffffffffffffffff1614151515614295576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260338152602001807f747279696e6720746f2070726f6365737320616e20656d70747920726571756581526020017f737420616e6420636f6c6c65637420666565730000000000000000000000000081525060400191505060405180910390fd5b600b6000878152602001908152602001600020600086846001811015156142b857fe5b602002015162ffffff1662ffffff168152602001908152602001600020600080820160006101000a8154906fffffffffffffffffffffffffffffffff0219169055505082840193505b818060010192505061407b565b83935050505092915050565b6000614324615b6e565b604080519081016040528084600060028110151561433e57fe5b6020020151815260200184600160028110151561435757fe5b6020020151815250905061436a81615988565b915050919050565b61437a615b4a565b60607f2806ceee6e1d1eb6f31ff675b92143dba13b3fbad614f843f5c3afd6568b205a826000600e811015156143ac57fe5b6020020181815250507f122808a613a8f598c4b867f4b2ff0d43f0bb6d88eeb8ee75eb6f24d359bbf8e0826001600e811015156143e557fe5b6020020181815250507f22448ceb94acf3cd1d15bcaa5b0fea9b93517c5845177e084089d9ee6d79ff50826002600e8110151561441e57fe5b6020020181815250507f031a214677d973a795d26219598bb0512ea0dc76e75dbce39cbc9d9b17a2cc8c826003600e8110151561445757fe5b6020020181815250507f0a9a3bef0fd1d79ae409f82733e8e462b75ff5f05bea6422066b95ca9e02c9dd826004600e8110151561449057fe5b6020020181815250507f0c6fa2f476a8f04a57dbcb68e2425440062630c908d6e198c875d875130025e9826005600e811015156144c957fe5b6020020181815250507f0ae5cc9692f99a91d35fe9abfd2e3786b3ad14b327d0fb9e51c514f0bd95959c826006600e8110151561450257fe5b6020020181815250507f1d3950dce5e030d612b1167e70c34ab4cf1d9c4320206047652747915ed67097826007600e8110151561453b57fe5b6020020181815250507f0a9138320c05f4c5d26da0bc8d508398b027cabffd4dd36fb65f29d9fa3cc3dd826008600e8110151561457457fe5b6020020181815250507f2a5daa065c803df8f429e946f2c5700026c2d12dc172e192d270dc73fdc8cc39826009600e811015156145ad57fe5b6020020181815250507f27863bde61126110d0d6f2f31947e2f63c3cdd6594caf3ec225babfa7afa4f2382600a600e811015156145e657fe5b6020020181815250507f20fd57765a2d6a84f2bee03afefaf5bd42fb5804b8a5c0874762d19afafc1f4182600b600e8110151561461f57fe5b6020020181815250507f0b451a37fed071dd2ae876826a32f4fe0a58d990c624cfde92096cc2b3fd4a0882600c600e8110151561465857fe5b6020020181815250507f2920445cbffbb49c761e20d864dccf560258c3cd7302773accaa7d78aa206ba982600d600e8110151561469157fe5b60200201818152505060086040519080825280602002602001820160405280156146ca5781602001602082028038833980820191505090505b5090507f2d8c931ff562a4d5a349685f6fdf2a30a0883e2cfcb8a27a642687a4118955778160008151811015156146fd57fe5b90602001906020020181815250507f2530d4a3fcaea9d34725f2f02100be77a511c2a507e084e6e379e068d4cde55981600181518110151561473b57fe5b90602001906020020181815250507f01e3781d1f0a0f6beac8e3aa47a8c509d80406326c5c4594aa04f4c0f9b0138a81600281518110151561477957fe5b90602001906020020181815250507f235683ea39dc02e4919b9f99e14c927399f26c3c24935caf3d7f745377fd76298160038151811015156147b757fe5b90602001906020020181815250507f2fbf7af8adca023e9744087f7845cc19f2bdb9cbba20c57dc77edaa6115625fb8160048151811015156147f557fe5b90602001906020020181815250507f1c3ad616391a8022720659ceb30a65391117df3b0e501f0e19d99800fea0d66281600581518110151561483357fe5b90602001906020020181815250507f1bc9897f50972e9924dfcc9dc9c9104c50588c168b7e137526f9ab8cfdc6248281600681518110151561487157fe5b90602001906020020181815250507f04f9efe4f42e792c6abffbb1b5431a71f8b7712a3e65011f07c7bb348914d0d08160078151811015156148af57fe5b90602001906020020181815250509091565b6148c9615b4a565b60607f20fabca7a936d76e2de75f334d12408a85a3038b2c748e884a7d10b6c8e785ae826000600e811015156148fb57fe5b6020020181815250507f05b7926cd85113320bdad329a22fa8a7bb13fee4e5ae784441c975f7be24b144826001600e8110151561493457fe5b6020020181815250507f17f95798ad37dc5d5842e0a25085bb7091525e5a19a4e664c4325d43996733bb826002600e8110151561496d57fe5b6020020181815250507f02943aa487fcc67df949c6e2481e6a61b992ce4ad6f5d92372f59b93d15c0d30826003600e811015156149a657fe5b6020020181815250507f0131b8773666df90359fdbe663c451881a09b24df4564be75dd86ceb485bc16c826004600e811015156149df57fe5b6020020181815250507f091b92109b2c58ee59d43f1646b910e20203dcb95676b139509886a314e00806826005600e81101515614a1857fe5b6020020181815250507f18d2e27fdde751997e5ac3146a828702404f47c56072d5fd9e628bd9d00b5aac826006600e81101515614a5157fe5b6020020181815250507f0cf19a2bf4b4e09843df3cd201709e55ae3a5ff31d8b59cd89d7b6eb06b98703826007600e81101515614a8a57fe5b6020020181815250507f14eaf5b1216b2adc72b75a80df5c202eb16953605656165177035432a6f88b8f826008600e81101515614ac357fe5b6020020181815250507f0f19e2b9bb71cab73500652d5728fe94843dcef2e73a2fd97739f6e8fd83369a826009600e81101515614afc57fe5b6020020181815250507f0135e689579dbf14165032a60d35c70c95fc8fcf56f16a5335c62ef49e4fdfc482600a600e81101515614b3557fe5b6020020181815250507f196c80c924953fae60eb1c57c03beed305ed22454b359ade4265a434f6aef11482600b600e81101515614b6e57fe5b6020020181815250507f0a282bf79f6d625029d9746a596c33e286ec52ba4fd14c87577b39cdbc656dbc82600c600e81101515614ba757fe5b6020020181815250507f216dd1c95ba7a7408e093cb8010c09addcb31e54d9ac23493341660ce3b9d74282600d600e81101515614be057fe5b6020020181815250506008604051908082528060200260200182016040528015614c195781602001602082028038833980820191505090505b5090507f29c50e44a59741be3b553316fa0181329ec5275b046bb428eb3e041a1d6a4017816000815181101515614c4c57fe5b90602001906020020181815250507f1f799ade5130abbb234abfaa536226b602cd2e2e77c3afb5c6c29bb7835117b1816001815181101515614c8a57fe5b90602001906020020181815250507f20ca58d0e2b5c393272802f45e7fef3d27efa2696c0be7bd7f31435b3403acbd816002815181101515614cc857fe5b90602001906020020181815250507f2b7f914981d405bc613a0c2c3accb5ac825b900ddbef5b7689567e0ffdf84060816003815181101515614d0657fe5b90602001906020020181815250507f0be03143ab86092d0872260b1ed87202fd2816e0ddc15e4dda842688ff3f8bba816004815181101515614d4457fe5b90602001906020020181815250507f1c4900581b3dc146c77b6bf15ceffd90ca3d34fd69b393ee562e8cc614decf91816005815181101515614d8257fe5b90602001906020020181815250507f1261a3e53a4815cb7237aa39113f0dd33d7464e80a317a1a35ed33a217053584816006815181101515614dc057fe5b90602001906020020181815250507f17599c2506b56e759ba24bf30920525cfd12337392ed0cebc0b851a142802ca0816007815181101515614dfe57fe5b90602001906020020181815250509091565b614e18615b4a565b60607f08730c8e1cbb3eb57ea2c4d8d5c48fc56aa910d331ef8723e74c9e5750fb943a826000600e81101515614e4a57fe5b6020020181815250507f29d8dc5dd6f9b1a692a37c4982faa894119b98dbc35fe5b0e20363ffce6c5fea826001600e81101515614e8357fe5b6020020181815250507f016411e5a45fa79352c47a455eeaddb12059d5bb5579487e8abb4ffd2f472c5a826002600e81101515614ebc57fe5b6020020181815250507f27084dc459b5dd6d1c60cccda8d78a80755ae23436dd44aca13d44962dea244a826003600e81101515614ef557fe5b6020020181815250507f16c4a816a173596179da516fcc694c68878da66042afe8c35f098742482ab0a0826004600e81101515614f2e57fe5b6020020181815250507f02318a621109b9e543cc09e7bcde9cfe15386429572fb31d08c88a42b418fe8e826005600e81101515614f6757fe5b6020020181815250507f0f10cfbdfaf1753d7214d6d0f2644458bddd10ab5619d19e7e41ac709b30b3ef826006600e81101515614fa057fe5b6020020181815250507f21f68a12e4e0ce060910e1335703431d20ce5ac7109baa52e34423fdcc659c54826007600e81101515614fd957fe5b6020020181815250507f2c505db2e660d4ea4e6f41e0f3b921c8358d6b3bcedaaf8349f01fbf56b03d4f826008600e8110151561501257fe5b6020020181815250507f0733f6edbaef053203c0654afd9eea4b8909c88473b1f1aa72afdd5a4cded36e826009600e8110151561504b57fe5b6020020181815250507f1a4c2e2c731b7de65f7b0cad686b5c7964fe162741385a33c72b08c903791e2982600a600e8110151561508457fe5b6020020181815250507f1efc25b88bfac326220c61f7ab065be1c77af7b74f67f63262c2e66613eebdac82600b600e811015156150bd57fe5b6020020181815250507f264f4171cfa70441d121f28ce3c8186fa9011a9a2611ce7c920cba0d8cb3f82682600c600e811015156150f657fe5b6020020181815250507f126ba4be6253be58ceb3bb5bf94045b310baea07bc35d669283a10ffdf90853082600d600e8110151561512f57fe5b60200201818152505060086040519080825280602002602001820160405280156151685781602001602082028038833980820191505090505b5090507f01b0002b9d1ceb70fe45b66103672ab9500327509572c1701d3250b00c299e8881600081518110151561519b57fe5b90602001906020020181815250507f080c6552831b1c735ac286a537343522bd10083d3b3fed202ffae1e83ff87cc08160018151811015156151d957fe5b90602001906020020181815250507f2e13eae69b931076d3e4ce5a0764aabf54030b14f53653627d13def87840df0781600281518110151561521757fe5b90602001906020020181815250507f0b2032652364ded806919e92594a508eafae7eabb42bb6e731c1bfc0b3918b6c81600381518110151561525557fe5b90602001906020020181815250507f024ba284020edb04f39d1eeeccc5f826826086f2bac64e0b233114cd523043e481600481518110151561529357fe5b90602001906020020181815250507f082cb9dada50204406112d784129e28ce9fea7d999f0540fe36131aee46ad6328160058151811015156152d157fe5b90602001906020020181815250507f2b661ab87456646811a53fbb055addc96eef2396827889305bf2ce7ab8c1ea4481600681518110151561530f57fe5b90602001906020020181815250507f118ee65eb15ec1db1b648d4c64e490977198de8a01580399d5a3835576d602b981600781518110151561534d57fe5b90602001906020020181815250509091565b6000615369615b88565b615371615bab565b600080600061537e615bce565b615386615bf2565b8851600160028d5181151561539757fe5b040314151561540e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f496e76616c6964206e756d626572206f66207075626c696320696e707574730081525060200191505060405180910390fd5b600293508a600081518110151561542157fe5b9060200190602002015186600060048110151561543a57fe5b6020020181815250508a600181518110151561545257fe5b9060200190602002015186600160048110151561546b57fe5b602002018181525050600092505b8851831015615637578a8480600101955081518110151561549657fe5b906020019060200201518760006003811015156154af57fe5b6020020181815250508a848060010195508151811015156154cc57fe5b906020019060200201518760016003811015156154e557fe5b60200201818152505088838151811015156154fc57fe5b9060200190602002015187600260038110151561551557fe5b602002018181525050604080870160608960076107d05a03fa94508415156155a5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f4661696c656420746f2063616c6c2045434d554c20707265636f6d70696c650081525060200191505060405180910390fd5b60408660808860066107d05a03fa945084151561562a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f4661696c656420746f2063616c6c20454341444420707265636f6d70696c650081525060200191505060405180910390fd5b8280600101935050615479565b610300604051908101604052808b600060088110151561565357fe5b602002015181526020018b600160088110151561566c57fe5b602002015181526020018b600260088110151561568557fe5b602002015181526020018b600360088110151561569e57fe5b602002015181526020018b60046008811015156156b757fe5b602002015181526020018b60056008811015156156d057fe5b602002015181526020018d6000600e811015156156e957fe5b6020020151815260200161570f8e6001600e8110151561570557fe5b6020020151615a34565b81526020018d6002600e8110151561572357fe5b602002015181526020018d6003600e8110151561573c57fe5b602002015181526020018d6004600e8110151561575557fe5b602002015181526020018d6005600e8110151561576e57fe5b6020020151815260200187600060048110151561578757fe5b602002015181526020016157ad8860016004811015156157a357fe5b6020020151615a34565b81526020018d6006600e811015156157c157fe5b602002015181526020018d6007600e811015156157da57fe5b602002015181526020018d6008600e811015156157f357fe5b602002015181526020018d6009600e8110151561580c57fe5b602002015181526020018b600660088110151561582557fe5b6020020151815260200161584b8c600760088110151561584157fe5b6020020151615a34565b81526020018d600a600e8110151561585f57fe5b602002015181526020018d600b600e8110151561587857fe5b602002015181526020018d600c600e8110151561589157fe5b602002015181526020018d600d600e811015156158aa57fe5b602002015181525091506020816103008460086107d05a03fa9450841515615960576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260218152602001807f4661696c656420746f2063616c6c2070616972696e6720707265636f6d70696c81526020017f650000000000000000000000000000000000000000000000000000000000000081525060400191505060405180910390fd5b600181600060018110151561597157fe5b602002015114975050505050505050949350505050565b60008060008060008060008061599c615a70565b96506159a6615a98565b95506159b0615ac0565b9450868015156159bc57fe5b89600001518a60000151099350868015156159d357fe5b89602001518a60200151099250868015156159ea57fe5b83888015156159f557fe5b86890908915086801515615a0557fe5b87801515615a0f57fe5b88801515615a1957fe5b85870987096001089050808214975050505050505050919050565b6000807f30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd4790508083811515615a6557fe5b068103915050919050565b60007f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001905090565b60007f30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000000905090565b60007f1aee90f15f2189693df072d799fd11fc039b2959ebb7c867d075ca8cf4d7eb8e905090565b60c060405190810160405280600060ff168152602001600063ffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff16815260200160008152602001600063ffffffff168152602001600063ffffffff1681525090565b6101c060405190810160405280600e90602082028038833980820191505090505090565b604080519081016040528060008152602001600081525090565b606060405190810160405280600390602082028038833980820191505090505090565b608060405190810160405280600490602082028038833980820191505090505090565b61030060405190810160405280601890602082028038833980820191505090505090565b6020604051908101604052806001906020820280388339808201915050905050905600a165627a7a723058200b1f375c2a2b7446cbec90a1b0d113f5ea881cb46c9bb3fa8352ac197f5519530029000000000000000000000000777c90f6530446ebc256c8af6aa3a0bda021b452000000000000000000000000fcf77c7da26169455d6ea69a203ed36248665a50


   Swarm Source:
bzzr://0b1f375c2a2b7446cbec90a1b0d113f5ea881cb46c9bb3fa8352ac197f551953
Block Age Transaction Difficulty GasUsed Reward
Block Age Uncle Number Difficulty GasUsed Reward