Sponsored:   Ubex.com - Additional 17% of tokens are available for purchase! Trading on exchanges already started.
 Latest 25 txns from a total Of 1496 transactions

TxHash Age From To Value [TxFee]
0x3b698235e3b26150b404b44fb422429fbcad7eaa32ab1c3ecfd536bf269f4dff189 days 13 hrs ago0x9e8a581f2f9e3a1c0159b41daa80e9ab0d0dcbdb  IN   0xfc668ae14b0f7702c04b105448fe733d96c558df0 Ether0.00099828
0x4c46d158acf7258f2b43868cd9e1e2a82b36948bccc7f7112ba7125e38c18cd6207 days 5 hrs ago0x9e8a581f2f9e3a1c0159b41daa80e9ab0d0dcbdb  IN   0xfc668ae14b0f7702c04b105448fe733d96c558df0 Ether0.000637944
0xedeb336a2c878502a5d9895266a21f199a8851db0042554a1e1e3919733d7e17207 days 5 hrs ago0x9e8a581f2f9e3a1c0159b41daa80e9ab0d0dcbdb  IN   0xfc668ae14b0f7702c04b105448fe733d96c558df0 Ether0.000515576
0x08ad1b1801d72aa98d6abe02fa2162d1ddf7215959516a506833bb551889343c216 days 18 hrs ago0x9e8a581f2f9e3a1c0159b41daa80e9ab0d0dcbdb  IN   0xfc668ae14b0f7702c04b105448fe733d96c558df0 Ether0.000115996
0xd9d6e0c0af2b022f95cf5dd29800ff89b4c82180c68d3954b1d2d30a6be6e0fe238 days 23 hrs ago0x9e8a581f2f9e3a1c0159b41daa80e9ab0d0dcbdb  IN   0xfc668ae14b0f7702c04b105448fe733d96c558df0 Ether0.000115996
0x03ad4f4d46fed54d13fa0beee0face2c6e3d0ff05b49ca9c2d1cc823d8889348275 days 23 hrs ago0x9e8a581f2f9e3a1c0159b41daa80e9ab0d0dcbdb  IN   0xfc668ae14b0f7702c04b105448fe733d96c558df0 Ether0.000115996
0x1ceec0d71d4e4f5b57f19a84f3043a3766c83136201f1353d778e334ea8d9d2d286 days 16 hrs ago0x9e8a581f2f9e3a1c0159b41daa80e9ab0d0dcbdb  IN   0xfc668ae14b0f7702c04b105448fe733d96c558df0 Ether0.000115996
0x55cdc350ab885f9c47f85e56b657d5f5ecbc64bc083aba42f163db64ed79117b296 days 8 hrs ago0x9e8a581f2f9e3a1c0159b41daa80e9ab0d0dcbdb  IN   0xfc668ae14b0f7702c04b105448fe733d96c558df0 Ether0.000115996
0x59da7401f063eb231a1ef8560ab293d5f53f1ef35cbab500c4ec6ff3c30ff7d2304 days 23 hrs ago0x9e8a581f2f9e3a1c0159b41daa80e9ab0d0dcbdb  IN   0xfc668ae14b0f7702c04b105448fe733d96c558df0 Ether0.000116252
0xb405ea8792c9c1aeea414d30695b27298505b6efc3c5ae094f0f91e81627a279313 days 12 hrs ago0x2ff4d83d13fb20b88614fbe38aaceaadad9d53fc  IN   0xfc668ae14b0f7702c04b105448fe733d96c558df0 Ether0.000332436
0xec1a5b1b89e05e36db657c3f14f2c93656e3616f20d8babbe173fe4bf134ec1b314 days 12 hrs ago0x9e8a581f2f9e3a1c0159b41daa80e9ab0d0dcbdb  IN   0xfc668ae14b0f7702c04b105448fe733d96c558df0 Ether0.000116252
0xbb4798c9c98a472a4e5208a7ddbffcde4d8ad5122dc8838d462f469117f4d796318 days 16 hrs ago0x9e8a581f2f9e3a1c0159b41daa80e9ab0d0dcbdb  IN   0xfc668ae14b0f7702c04b105448fe733d96c558df0 Ether0.000618932
0x37fcf5d42c9a915664fd38ae38707a82cf426365e48695163effb54440a9c429325 days 2 hrs ago0x077904eb39fdfee17679356987beb89c7b26e5b8  IN   0xfc668ae14b0f7702c04b105448fe733d96c558df0 Ether0.000257788
0xcf5a515a7b844e83e9baa826d1e11595a9d686873513a245ac5658947d7df156325 days 2 hrs ago0x077904eb39fdfee17679356987beb89c7b26e5b8  IN   0xfc668ae14b0f7702c04b105448fe733d96c558df0 Ether0.000159678
0x4023e2d892688c92a2fef1602de7403ce7d238e3d8e2a6d7bb525d7cc0237e9d326 days 5 hrs ago0x077904eb39fdfee17679356987beb89c7b26e5b8  IN   0xfc668ae14b0f7702c04b105448fe733d96c558df0 Ether0.000159698
0x3dac3341815b103ef875e80d414f98d1dd30f7adeac4d5f026fcd57c9606cbdd337 days 1 hr ago0x077904eb39fdfee17679356987beb89c7b26e5b8  IN   0xfc668ae14b0f7702c04b105448fe733d96c558df0 Ether0.00015957
0xbabd900305964385808b28ae2c7e586c310267a141803d5416e3bfb141f29e39343 days 10 hrs ago0x0086cd5aaa071f029acb08ecf4ab37b13d57e1dd  IN   0xfc668ae14b0f7702c04b105448fe733d96c558df0 Ether0.000079849
0x1b5fbdbb51eefc48989ed55287a2c4991b0ccda0aac712a4bf0e390678500ff7348 days 2 hrs ago0x077904eb39fdfee17679356987beb89c7b26e5b8  IN   0xfc668ae14b0f7702c04b105448fe733d96c558df0 Ether0.000159486
0x291a805b746e242af6fae7d33e46e4d1f2a8dfbb5db3eb3b5340c534cb7856cf348 days 2 hrs ago0x077904eb39fdfee17679356987beb89c7b26e5b8  IN   0xfc668ae14b0f7702c04b105448fe733d96c558df0 Ether0.000128894
0x93614e1ebd7977c3c35532d3acc283937f775d92942858c32ab4d1737fdf3589348 days 9 hrs ago0x0086cd5aaa071f029acb08ecf4ab37b13d57e1dd  IN   0xfc668ae14b0f7702c04b105448fe733d96c558df0 Ether0.000079849
0xab2392ed574bbe5f518f69d5b5b8bc02047faeb92b1c006f37cf729870767a4c349 days 9 hrs ago0x0086cd5aaa071f029acb08ecf4ab37b13d57e1dd  IN   0xfc668ae14b0f7702c04b105448fe733d96c558df0 Ether0.000079849
0xf0bd9a957986e6c4e5bf189aa2c473643f1be77050d295b1bb55a2642c90b5b6350 days 12 hrs ago0x0086cd5aaa071f029acb08ecf4ab37b13d57e1dd  IN   0xfc668ae14b0f7702c04b105448fe733d96c558df0 Ether0.000079849
0x09d2a7c5f167246834dd3cede7ca26360e349b63873fcd925c4e713a607a2108351 days 11 hrs ago0x0086cd5aaa071f029acb08ecf4ab37b13d57e1dd  IN   0xfc668ae14b0f7702c04b105448fe733d96c558df0 Ether0.0000878339
0x8f8d00ec8368fca5e0e5063ba56f696f5a09b3752bf8461ef4a807fcb15d85a4351 days 20 hrs ago0x00a6bb3f4123f5017a8be692c239ee3d07a97bad  IN   0xfc668ae14b0f7702c04b105448fe733d96c558df0 Ether0.0000233016
0xf984b33e4e97656c0e5fbf5322355f8ca80a9d1856fa7efa5c6aa4f0d2b858a8352 days 11 hrs ago0x0086cd5aaa071f029acb08ecf4ab37b13d57e1dd  IN   0xfc668ae14b0f7702c04b105448fe733d96c558df0 Ether0.000079849
[ Download CSV Export  ] 
 Internal Transactions as a result of Contract Execution
 Latest 25 Internal Txns, Click here to View More View All
ParentTxHash Block Age From To Value
0xc2e3238660f7a149f53870eff519740e74254ea7185ee35cd914f57747e19b204175058364 days 8 hrs ago0xfc668ae14b0f7702c04b105448fe733d96c558df0x0086cd5aaa071f029acb08ecf4ab37b13d57e1dd0.966179078649313769 Ether
0xd13a52f563865b17cbab873ffa0c4ea54a1b46297d2d722cbe36733f386a094c4132191374 days 17 hrs ago0xfc668ae14b0f7702c04b105448fe733d96c558df0xa837c07c0fa74df46e3759e14cb7647480e84ec01.318846821181981842 Ether
0x4e0225b3b9ab1261050af0c2df353d3de87f17407f150bdfe6ad91f9641471774129189375 days 11 hrs ago0xfc668ae14b0f7702c04b105448fe733d96c558df0xa837c07c0fa74df46e3759e14cb7647480e84ec01.296124035210928661 Ether
0xb8ceea95b2b36b4ea2b9f9489a274d4a3ae7a8c327d7a78c41eca2cfd5529f204122253377 days 4 hrs ago0xfc668ae14b0f7702c04b105448fe733d96c558df0xa837c07c0fa74df46e3759e14cb7647480e84ec01.343154100384702064 Ether
0xa26bc33bcff2c135e35e79faa59b864f90175e84f0ec65b363e5bd5b5668830f4120517377 days 14 hrs ago0xfc668ae14b0f7702c04b105448fe733d96c558df0xa837c07c0fa74df46e3759e14cb7647480e84ec01.341490968133539172 Ether
0x6850d117bb2c606627f7f30f415f7079da83e1f6b9f1338fc613eb91b2a7c3c54117069378 days 11 hrs ago0xfc668ae14b0f7702c04b105448fe733d96c558df0xa837c07c0fa74df46e3759e14cb7647480e84ec01.343970636250478998 Ether
0xac22af68b1b877595191d2eee852a3f9b5b92d28e9986b079e512f2b2c1c22cf4115886378 days 18 hrs ago0xfc668ae14b0f7702c04b105448fe733d96c558df0xa837c07c0fa74df46e3759e14cb7647480e84ec01.342236053565003822 Ether
0xe32b7eea36e1b859a34e73125921fd09affef7118354d843edf80fd5565706f84114013379 days 5 hrs ago0xfc668ae14b0f7702c04b105448fe733d96c558df0xa837c07c0fa74df46e3759e14cb7647480e84ec01.369526401720357597 Ether
0x7162a1acfc1eabc510a2fe019161d4a598f862f2bbca5dee44637148bf51f6c74112938379 days 11 hrs ago0xaf766478aa284bb69b85a344ca0072e86dc700250xfc668ae14b0f7702c04b105448fe733d96c558df10 Ether
0xa2e1071a81790890f98ebd873d199d768d348a694c14087c53298d12cc609db54112817379 days 12 hrs ago0xfc668ae14b0f7702c04b105448fe733d96c558df0xa837c07c0fa74df46e3759e14cb7647480e84ec01.375897905659600492 Ether
0xc2746fbdb91d4393ef3440feeb9e460bcf8cf362b1b036fe69225c0f23b99a2f4111906379 days 17 hrs ago0xfc668ae14b0f7702c04b105448fe733d96c558df0xa837c07c0fa74df46e3759e14cb7647480e84ec01.397537086502668184 Ether
0x2961c515ce9ffdc7037ee800f0159a46a7e29239cf27ea8073472176dacc09f44110907379 days 23 hrs ago0xfc668ae14b0f7702c04b105448fe733d96c558df0xa837c07c0fa74df46e3759e14cb7647480e84ec01.385244219705313883 Ether
0x8e1070bb5532953ccdb9318a451e34d90f8049eeab6fe3ba6f26a4957ccf967d4110028380 days 5 hrs ago0xfc668ae14b0f7702c04b105448fe733d96c558df0xa837c07c0fa74df46e3759e14cb7647480e84ec01.314804997506684332 Ether
0xadf53a92c28b4c1d1b2790e4557c3b2e12f4dce05dea95541aa2072e173f7af14108995380 days 11 hrs ago0xfc668ae14b0f7702c04b105448fe733d96c558df0xa837c07c0fa74df46e3759e14cb7647480e84ec01.327033016457113217 Ether
0xb86b3b7e052d0f9bcc1458601af88661492ce16058fe33a9a35ed19dc5b4bf374108242380 days 15 hrs ago0xfc668ae14b0f7702c04b105448fe733d96c558df0xa837c07c0fa74df46e3759e14cb7647480e84ec01.355260295474152063 Ether
0xf1bb2bfa31d22b5444662309c1e32eb7dad93bd19871013712ba2743c908117e4107486380 days 20 hrs ago0xfc668ae14b0f7702c04b105448fe733d96c558df0xa837c07c0fa74df46e3759e14cb7647480e84ec01.351730471988100285 Ether
0xa1e1efae21f4fb0191e4c39a69dc9523a3d0a2c54a64c9b5a6c450d07056fded4106520381 days 2 hrs ago0xfc668ae14b0f7702c04b105448fe733d96c558df0xa837c07c0fa74df46e3759e14cb7647480e84ec01.338649536147863249 Ether
0xa59124f940fcdd14e0c4e2568dc7645c41dc7b2caafcce52d86e7a5f71b0a4bb4105742381 days 7 hrs ago0xfc668ae14b0f7702c04b105448fe733d96c558df0xa837c07c0fa74df46e3759e14cb7647480e84ec01.306909242192266412 Ether
0x441bbe3f5307a8cd2ac8df97b5de2e64a09454aa1e8060b657fc5110ccc2164d4104924381 days 11 hrs ago0xfc668ae14b0f7702c04b105448fe733d96c558df0xa837c07c0fa74df46e3759e14cb7647480e84ec01.316203864438752337 Ether
0x47bded6709d6ccb762a0a48bda02d778a589373fa3d9e10533b20ed8e435dcbe4104159381 days 16 hrs ago0xfc668ae14b0f7702c04b105448fe733d96c558df0xa837c07c0fa74df46e3759e14cb7647480e84ec01.329520834233595523 Ether
0x6b77e6308e2bf445f86c05b02aef14d992248ea649c9e786f01df95f5449d7cd4103304381 days 21 hrs ago0xfc668ae14b0f7702c04b105448fe733d96c558df0xa837c07c0fa74df46e3759e14cb7647480e84ec01.374676970560232656 Ether
0xfddac73a6e878402fb649bd34958bf2205937fc06a19beb86b20409e5c54ee874102521382 days 1 hr ago0xfc668ae14b0f7702c04b105448fe733d96c558df0xa837c07c0fa74df46e3759e14cb7647480e84ec01.377385157199123452 Ether
0x8e771b2c46f1f505f9301c6d3598f08b910c62bba553bd2f253a30069e47fd624101783382 days 6 hrs ago0xfc668ae14b0f7702c04b105448fe733d96c558df0xa837c07c0fa74df46e3759e14cb7647480e84ec01.360579954796087999 Ether
0xddf4007948362dbcf2f97b1e8ff44af37fe8112ad952af6b5d1bd9694696fc234100977382 days 10 hrs ago0xfc668ae14b0f7702c04b105448fe733d96c558df0xa837c07c0fa74df46e3759e14cb7647480e84ec01.427921321796652787 Ether
0x3ae4079e8aba15025978d88fabef2524d0ec7e3ee27c11a3ad3cd87e785ad9c74100214382 days 15 hrs ago0xfc668ae14b0f7702c04b105448fe733d96c558df0xa837c07c0fa74df46e3759e14cb7647480e84ec01.526178316820507808 Ether
[ Download CSV Export  ] 
Contract Name: SmartPool
Compiler Version: v0.4.11+commit.68ef5810
Optimization Enabled: Yes
Runs (Optimiser):  200



  Contract Source Code   Find Similiar Contracts

pragma solidity ^0.4.8;

//solc --bin --abi --optimize  --optimize-runs 20000 -o . Testpool.sol 

contract SHA3_512 {
    function SHA3_512() {}
    
    function keccak_f(uint[25] A) constant internal returns(uint[25]) {
        uint[5] memory C;
        uint[5] memory D;
        uint x;
        uint y;
        //uint D_0; uint D_1; uint D_2; uint D_3; uint D_4;
        uint[25] memory B;
        
        uint[24] memory RC= [
                   uint(0x0000000000000001),
                   0x0000000000008082,
                   0x800000000000808A,
                   0x8000000080008000,
                   0x000000000000808B,
                   0x0000000080000001,
                   0x8000000080008081,
                   0x8000000000008009,
                   0x000000000000008A,
                   0x0000000000000088,
                   0x0000000080008009,
                   0x000000008000000A,
                   0x000000008000808B,
                   0x800000000000008B,
                   0x8000000000008089,
                   0x8000000000008003,
                   0x8000000000008002,
                   0x8000000000000080,
                   0x000000000000800A,
                   0x800000008000000A,
                   0x8000000080008081,
                   0x8000000000008080,
                   0x0000000080000001,
                   0x8000000080008008 ];
        
        for( uint i = 0 ; i < 24 ; i++ ) {
            /*
            for( x = 0 ; x < 5 ; x++ ) {
                C[x] = A[5*x]^A[5*x+1]^A[5*x+2]^A[5*x+3]^A[5*x+4];                
            }*/
                       
            C[0]=A[0]^A[1]^A[2]^A[3]^A[4];
            C[1]=A[5]^A[6]^A[7]^A[8]^A[9];
            C[2]=A[10]^A[11]^A[12]^A[13]^A[14];
            C[3]=A[15]^A[16]^A[17]^A[18]^A[19];
            C[4]=A[20]^A[21]^A[22]^A[23]^A[24];

            /*
            for( x = 0 ; x < 5 ; x++ ) {
                D[x] = C[(x+4)%5]^((C[(x+1)%5] * 2)&0xffffffffffffffff | (C[(x+1)%5]/(2**63)));
            }*/
                        
            
            D[0]=C[4] ^ ((C[1] * 2)&0xffffffffffffffff | (C[1] / (2 ** 63)));
            D[1]=C[0] ^ ((C[2] * 2)&0xffffffffffffffff | (C[2] / (2 ** 63)));
            D[2]=C[1] ^ ((C[3] * 2)&0xffffffffffffffff | (C[3] / (2 ** 63)));
            D[3]=C[2] ^ ((C[4] * 2)&0xffffffffffffffff | (C[4] / (2 ** 63)));
            D[4]=C[3] ^ ((C[0] * 2)&0xffffffffffffffff | (C[0] / (2 ** 63)));

            /*
            for( x = 0 ; x < 5 ; x++ ) {
                for( y = 0 ; y < 5 ; y++ ) {
                    A[5*x+y] = A[5*x+y] ^ D[x];
                }            
            }*/
            

            
            A[0]=A[0] ^ D[0];
            A[1]=A[1] ^ D[0];
            A[2]=A[2] ^ D[0];
            A[3]=A[3] ^ D[0];
            A[4]=A[4] ^ D[0];
            A[5]=A[5] ^ D[1];
            A[6]=A[6] ^ D[1];
            A[7]=A[7] ^ D[1];
            A[8]=A[8] ^ D[1];
            A[9]=A[9] ^ D[1];
            A[10]=A[10] ^ D[2];
            A[11]=A[11] ^ D[2];
            A[12]=A[12] ^ D[2];
            A[13]=A[13] ^ D[2];
            A[14]=A[14] ^ D[2];
            A[15]=A[15] ^ D[3];
            A[16]=A[16] ^ D[3];
            A[17]=A[17] ^ D[3];
            A[18]=A[18] ^ D[3];
            A[19]=A[19] ^ D[3];
            A[20]=A[20] ^ D[4];
            A[21]=A[21] ^ D[4];
            A[22]=A[22] ^ D[4];
            A[23]=A[23] ^ D[4];
            A[24]=A[24] ^ D[4];

            /*Rho and pi steps*/            
            B[0]=A[0];
            B[8]=((A[1] * (2 ** 36))&0xffffffffffffffff | (A[1] / (2 ** 28)));
            B[11]=((A[2] * (2 ** 3))&0xffffffffffffffff | (A[2] / (2 ** 61)));
            B[19]=((A[3] * (2 ** 41))&0xffffffffffffffff | (A[3] / (2 ** 23)));
            B[22]=((A[4] * (2 ** 18))&0xffffffffffffffff | (A[4] / (2 ** 46)));
            B[2]=((A[5] * (2 ** 1))&0xffffffffffffffff | (A[5] / (2 ** 63)));
            B[5]=((A[6] * (2 ** 44))&0xffffffffffffffff | (A[6] / (2 ** 20)));
            B[13]=((A[7] * (2 ** 10))&0xffffffffffffffff | (A[7] / (2 ** 54)));
            B[16]=((A[8] * (2 ** 45))&0xffffffffffffffff | (A[8] / (2 ** 19)));
            B[24]=((A[9] * (2 ** 2))&0xffffffffffffffff | (A[9] / (2 ** 62)));
            B[4]=((A[10] * (2 ** 62))&0xffffffffffffffff | (A[10] / (2 ** 2)));
            B[7]=((A[11] * (2 ** 6))&0xffffffffffffffff | (A[11] / (2 ** 58)));
            B[10]=((A[12] * (2 ** 43))&0xffffffffffffffff | (A[12] / (2 ** 21)));
            B[18]=((A[13] * (2 ** 15))&0xffffffffffffffff | (A[13] / (2 ** 49)));
            B[21]=((A[14] * (2 ** 61))&0xffffffffffffffff | (A[14] / (2 ** 3)));
            B[1]=((A[15] * (2 ** 28))&0xffffffffffffffff | (A[15] / (2 ** 36)));
            B[9]=((A[16] * (2 ** 55))&0xffffffffffffffff | (A[16] / (2 ** 9)));
            B[12]=((A[17] * (2 ** 25))&0xffffffffffffffff | (A[17] / (2 ** 39)));
            B[15]=((A[18] * (2 ** 21))&0xffffffffffffffff | (A[18] / (2 ** 43)));
            B[23]=((A[19] * (2 ** 56))&0xffffffffffffffff | (A[19] / (2 ** 8)));
            B[3]=((A[20] * (2 ** 27))&0xffffffffffffffff | (A[20] / (2 ** 37)));
            B[6]=((A[21] * (2 ** 20))&0xffffffffffffffff | (A[21] / (2 ** 44)));
            B[14]=((A[22] * (2 ** 39))&0xffffffffffffffff | (A[22] / (2 ** 25)));
            B[17]=((A[23] * (2 ** 8))&0xffffffffffffffff | (A[23] / (2 ** 56)));
            B[20]=((A[24] * (2 ** 14))&0xffffffffffffffff | (A[24] / (2 ** 50)));

            /*Xi state*/
            /*
            for( x = 0 ; x < 5 ; x++ ) {
                for( y = 0 ; y < 5 ; y++ ) {
                    A[5*x+y] = B[5*x+y]^((~B[5*((x+1)%5)+y]) & B[5*((x+2)%5)+y]);
                }
            }*/
            
            
            A[0]=B[0]^((~B[5]) & B[10]);
            A[1]=B[1]^((~B[6]) & B[11]);
            A[2]=B[2]^((~B[7]) & B[12]);
            A[3]=B[3]^((~B[8]) & B[13]);
            A[4]=B[4]^((~B[9]) & B[14]);
            A[5]=B[5]^((~B[10]) & B[15]);
            A[6]=B[6]^((~B[11]) & B[16]);
            A[7]=B[7]^((~B[12]) & B[17]);
            A[8]=B[8]^((~B[13]) & B[18]);
            A[9]=B[9]^((~B[14]) & B[19]);
            A[10]=B[10]^((~B[15]) & B[20]);
            A[11]=B[11]^((~B[16]) & B[21]);
            A[12]=B[12]^((~B[17]) & B[22]);
            A[13]=B[13]^((~B[18]) & B[23]);
            A[14]=B[14]^((~B[19]) & B[24]);
            A[15]=B[15]^((~B[20]) & B[0]);
            A[16]=B[16]^((~B[21]) & B[1]);
            A[17]=B[17]^((~B[22]) & B[2]);
            A[18]=B[18]^((~B[23]) & B[3]);
            A[19]=B[19]^((~B[24]) & B[4]);
            A[20]=B[20]^((~B[0]) & B[5]);
            A[21]=B[21]^((~B[1]) & B[6]);
            A[22]=B[22]^((~B[2]) & B[7]);
            A[23]=B[23]^((~B[3]) & B[8]);
            A[24]=B[24]^((~B[4]) & B[9]);

            /*Last step*/
            A[0]=A[0]^RC[i];            
        }

        
        return A;
    }
 
    
    function sponge(uint[9] M) constant internal returns(uint[16]) {
        if( (M.length * 8) != 72 ) throw;
        M[5] = 0x01;
        M[8] = 0x8000000000000000;
        
        uint r = 72;
        uint w = 8;
        uint size = M.length * 8;
        
        uint[25] memory S;
        uint i; uint y; uint x;
        /*Absorbing Phase*/
        for( i = 0 ; i < size/r ; i++ ) {
            for( y = 0 ; y < 5 ; y++ ) {
                for( x = 0 ; x < 5 ; x++ ) {
                    if( (x+5*y) < (r/w) ) {
                        S[5*x+y] = S[5*x+y] ^ M[i*9 + x + 5*y];
                    }
                }
            }
            S = keccak_f(S);
        }

        /*Squeezing phase*/
        uint[16] memory result;
        uint b = 0;
        while( b < 16 ) {
            for( y = 0 ; y < 5 ; y++ ) {
                for( x = 0 ; x < 5 ; x++ ) {
                    if( (x+5*y)<(r/w) && (b<16) ) {
                        result[b] = S[5*x+y] & 0xFFFFFFFF; 
                        result[b+1] = S[5*x+y] / 0x100000000;
                        b+=2;
                    }
                }
            }
        }
         
        return result;
   }

}

////////////////////////////////////////////////////////////////////////////////

contract Ethash is SHA3_512 {
    
    mapping(address=>bool) public owners;
    
    function Ethash(address[3] _owners) {
        owners[_owners[0]] = true;
        owners[_owners[1]] = true;
        owners[_owners[2]] = true;                
    }
     
    function fnv( uint v1, uint v2 ) constant internal returns(uint) {
        return ((v1*0x01000193) ^ v2) & 0xFFFFFFFF;
    }



    function computeCacheRoot( uint index,
                               uint indexInElementsArray,
                               uint[] elements,
                               uint[] witness,
                               uint branchSize ) constant private returns(uint) {
 
                       
        uint leaf = computeLeaf(elements, indexInElementsArray) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;

        uint left;
        uint right;
        uint node;
        bool oddBranchSize = (branchSize % 2) > 0;
         
        assembly {
            branchSize := div(branchSize,2)
            //branchSize /= 2;
        }
        uint witnessIndex = indexInElementsArray * branchSize;
        if( oddBranchSize ) witnessIndex += indexInElementsArray;  

        for( uint depth = 0 ; depth < branchSize ; depth++ ) {
            assembly {
                node := mload(add(add(witness,0x20),mul(add(depth,witnessIndex),0x20)))
            }
            //node  = witness[witnessIndex + depth] & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
            if( index & 0x1 == 0 ) {
                left = leaf;
                assembly{
                    //right = node & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;                
                    right := and(node,0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)
                }
                
            }
            else {
                assembly{
                    //left = node & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
                    left := and(node,0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)
                }
                right = leaf;
            }
            
            leaf = uint(sha3(left,right)) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
            assembly {
                index := div(index,2) 
            }
            //index = index / 2;

            //node  = witness[witnessIndex + depth] / (2**128);
            if( index & 0x1 == 0 ) {
                left = leaf;
                assembly{
                    right := div(node,0x100000000000000000000000000000000)
                    //right = node / 0x100000000000000000000000000000000;
                }
            }
            else {
                assembly {
                    //left = node / 0x100000000000000000000000000000000;
                    left := div(node,0x100000000000000000000000000000000)
                }
                right = leaf;
            }
            
            leaf = uint(sha3(left,right)) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
            assembly {
                index := div(index,2) 
            }
            //index = index / 2;
        }
        
        if( oddBranchSize ) {
            assembly {
                node := mload(add(add(witness,0x20),mul(add(depth,witnessIndex),0x20)))
            }
        
            //node  = witness[witnessIndex + depth] & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
            if( index & 0x1 == 0 ) {
                left = leaf;
                assembly{
                    //right = node & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;                
                    right := and(node,0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)
                }                
            }
            else {
                assembly{
                    //left = node & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;                
                    left := and(node,0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)
                }
            
                right = leaf;
            }
            
            leaf = uint(sha3(left,right)) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;        
        }
        
        
        return leaf;
    }

    
    function toBE( uint x ) constant internal returns(uint) {
        uint y = 0;
        for( uint i = 0 ; i < 32 ; i++ ) {
            y = y * 256;
            y += (x & 0xFF);
            x = x / 256;            
        }
        
        return y;
        
    }
    
    function computeSha3( uint[16] s, uint[8] cmix ) constant internal returns(uint) {
        uint s0 = s[0] + s[1] * (2**32) + s[2] * (2**64) + s[3] * (2**96) +
                  (s[4] + s[5] * (2**32) + s[6] * (2**64) + s[7] * (2**96))*(2**128);

        uint s1 = s[8] + s[9] * (2**32) + s[10] * (2**64) + s[11] * (2**96) +
                  (s[12] + s[13] * (2**32) + s[14] * (2**64) + s[15] * (2**96))*(2**128);
                  
        uint c = cmix[0] + cmix[1] * (2**32) + cmix[2] * (2**64) + cmix[3] * (2**96) +
                  (cmix[4] + cmix[5] * (2**32) + cmix[6] * (2**64) + cmix[7] * (2**96))*(2**128);

        
        /* god knows why need to convert to big endian */
        return uint( sha3(toBE(s0),toBE(s1),toBE(c)) );
    }
 
 
    function computeLeaf( uint[] dataSetLookup, uint index ) constant internal returns(uint) {
        return uint( sha3(dataSetLookup[4*index],
                          dataSetLookup[4*index + 1],
                          dataSetLookup[4*index + 2],
                          dataSetLookup[4*index + 3]) );
                                    
    }
 
    function computeS( uint header, uint nonceLe ) constant internal returns(uint[16]) {
        uint[9]  memory M;
        
        header = reverseBytes(header);
        
        M[0] = uint(header) & 0xFFFFFFFFFFFFFFFF;
        header = header / 2**64;
        M[1] = uint(header) & 0xFFFFFFFFFFFFFFFF;
        header = header / 2**64;
        M[2] = uint(header) & 0xFFFFFFFFFFFFFFFF;
        header = header / 2**64;
        M[3] = uint(header) & 0xFFFFFFFFFFFFFFFF;

        // make little endian nonce
        M[4] = nonceLe;
        return sponge(M);
    }
    
    function reverseBytes( uint input ) constant internal returns(uint) {
        uint result = 0;
        for(uint i = 0 ; i < 32 ; i++ ) {
            result = result * 256;
            result += input & 0xff;
            
            input /= 256;
        }
        
        return result;
    }
    
    struct EthashCacheOptData {
        uint[512]    merkleNodes;
        uint         fullSizeIn128Resultion;
        uint         branchDepth;
    }
    
    mapping(uint=>EthashCacheOptData) epochData;
    
    function getEpochData( uint epochIndex, uint nodeIndex ) constant returns(uint[3]) {
        return [epochData[epochIndex].merkleNodes[nodeIndex],
                epochData[epochIndex].fullSizeIn128Resultion,
                epochData[epochIndex].branchDepth];
    }
    
    function isEpochDataSet( uint epochIndex ) constant returns(bool) {
        return epochData[epochIndex].fullSizeIn128Resultion != 0;
    
    }
        
    event SetEpochData( address indexed sender, uint error, uint errorInfo );    
    function setEpochData( uint epoch,
                           uint fullSizeIn128Resultion,
                           uint branchDepth,
                           uint[] merkleNodes,
                           uint start,
                           uint numElems ) {

        if( ! owners[msg.sender] ) {
            //ErrorLog( "setEpochData: only owner can set data", uint(msg.sender) );
            SetEpochData( msg.sender, 0x82000000, uint(msg.sender) );
            return;        
        }                           
                           
        for( uint i = 0 ; i < numElems ; i++ ) {
            if( epochData[epoch].merkleNodes[start+i] > 0 ) {
                //ErrorLog("epoch already set", epoch[i]);
                SetEpochData( msg.sender, 0x82000001, epoch * (2**128) + start + i );
                return;            

            } 
            epochData[epoch].merkleNodes[start+i] = merkleNodes[i];
        }
        epochData[epoch].fullSizeIn128Resultion = fullSizeIn128Resultion;
        epochData[epoch].branchDepth = branchDepth;
        
        SetEpochData( msg.sender, 0 , 0 );        
    }

    function getMerkleLeave( uint epochIndex, uint p ) constant internal returns(uint) {        
        uint rootIndex = p >> epochData[epochIndex].branchDepth;
        uint expectedRoot = epochData[epochIndex].merkleNodes[(rootIndex/2)];
        if( (rootIndex % 2) == 0 ) expectedRoot = expectedRoot & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
        else expectedRoot = expectedRoot / (2**128);
        
        return expectedRoot;
    }


    function hashimoto( bytes32      header,
                        bytes8       nonceLe,
                        uint[]       dataSetLookup,
                        uint[]       witnessForLookup,
                        uint         epochIndex ) constant returns(uint) {
         
        uint[16] memory s;
        uint[32] memory mix;
        uint[8]  memory cmix;
        
        uint[2]  memory depthAndFullSize = [epochData[epochIndex].branchDepth, 
                                            epochData[epochIndex].fullSizeIn128Resultion];
                
        uint i;
        uint j;
        
        if( ! isEpochDataSet( epochIndex ) ) return 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE;
        
        if( depthAndFullSize[1] == 0 ) {
            return 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
        }

        
        s = computeS(uint(header), uint(nonceLe));
        for( i = 0 ; i < 16 ; i++ ) {            
            assembly {
                let offset := mul(i,0x20)
                
                //mix[i] = s[i];
                mstore(add(mix,offset),mload(add(s,offset)))
                
                // mix[i+16] = s[i];
                mstore(add(mix,add(0x200,offset)),mload(add(s,offset)))    
            }
        }

        for( i = 0 ; i < 64 ; i++ ) {
            uint p = fnv( i ^ s[0], mix[i % 32]) % depthAndFullSize[1];
            
            
            if( computeCacheRoot( p, i, dataSetLookup,  witnessForLookup, depthAndFullSize[0] )  != getMerkleLeave( epochIndex, p ) ) {
            
                // PoW failed
                return 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
            }       

            for( j = 0 ; j < 8 ; j++ ) {

                assembly{
                    //mix[j] = fnv(mix[j], dataSetLookup[4*i] & varFFFFFFFF );
                    let dataOffset := add(mul(0x80,i),add(dataSetLookup,0x20))
                    let dataValue   := and(mload(dataOffset),0xFFFFFFFF)
                    
                    let mixOffset := add(mix,mul(0x20,j))
                    let mixValue  := mload(mixOffset)
                    
                    // fnv = return ((v1*0x01000193) ^ v2) & 0xFFFFFFFF;
                    let fnvValue := and(xor(mul(mixValue,0x01000193),dataValue),0xFFFFFFFF)                    
                    mstore(mixOffset,fnvValue)
                    
                    //mix[j+8] = fnv(mix[j+8], dataSetLookup[4*i + 1] & 0xFFFFFFFF );
                    dataOffset := add(dataOffset,0x20)
                    dataValue   := and(mload(dataOffset),0xFFFFFFFF)
                    
                    mixOffset := add(mixOffset,0x100)
                    mixValue  := mload(mixOffset)
                    
                    // fnv = return ((v1*0x01000193) ^ v2) & 0xFFFFFFFF;
                    fnvValue := and(xor(mul(mixValue,0x01000193),dataValue),0xFFFFFFFF)                    
                    mstore(mixOffset,fnvValue)

                    //mix[j+16] = fnv(mix[j+16], dataSetLookup[4*i + 2] & 0xFFFFFFFF );
                    dataOffset := add(dataOffset,0x20)
                    dataValue   := and(mload(dataOffset),0xFFFFFFFF)
                    
                    mixOffset := add(mixOffset,0x100)
                    mixValue  := mload(mixOffset)
                    
                    // fnv = return ((v1*0x01000193) ^ v2) & 0xFFFFFFFF;
                    fnvValue := and(xor(mul(mixValue,0x01000193),dataValue),0xFFFFFFFF)                    
                    mstore(mixOffset,fnvValue)

                    //mix[j+24] = fnv(mix[j+24], dataSetLookup[4*i + 3] & 0xFFFFFFFF );
                    dataOffset := add(dataOffset,0x20)
                    dataValue   := and(mload(dataOffset),0xFFFFFFFF)
                    
                    mixOffset := add(mixOffset,0x100)
                    mixValue  := mload(mixOffset)
                    
                    // fnv = return ((v1*0x01000193) ^ v2) & 0xFFFFFFFF;
                    fnvValue := and(xor(mul(mixValue,0x01000193),dataValue),0xFFFFFFFF)                    
                    mstore(mixOffset,fnvValue)                    
                                        
                }

                
                //mix[j] = fnv(mix[j], dataSetLookup[4*i] & 0xFFFFFFFF );
                //mix[j+8] = fnv(mix[j+8], dataSetLookup[4*i + 1] & 0xFFFFFFFF );
                //mix[j+16] = fnv(mix[j+16], dataSetLookup[4*i + 2] & 0xFFFFFFFF );                
                //mix[j+24] = fnv(mix[j+24], dataSetLookup[4*i + 3] & 0xFFFFFFFF );
                
                
                //dataSetLookup[4*i    ] = dataSetLookup[4*i    ]/(2**32);
                //dataSetLookup[4*i + 1] = dataSetLookup[4*i + 1]/(2**32);
                //dataSetLookup[4*i + 2] = dataSetLookup[4*i + 2]/(2**32);
                //dataSetLookup[4*i + 3] = dataSetLookup[4*i + 3]/(2**32);                
                
                assembly{
                    let offset := add(add(dataSetLookup,0x20),mul(i,0x80))
                    let value  := div(mload(offset),0x100000000)
                    mstore(offset,value)
                                       
                    offset := add(offset,0x20)
                    value  := div(mload(offset),0x100000000)
                    mstore(offset,value)
                    
                    offset := add(offset,0x20)
                    value  := div(mload(offset),0x100000000)
                    mstore(offset,value)                    
                    
                    offset := add(offset,0x20)
                    value  := div(mload(offset),0x100000000)
                    mstore(offset,value)                                                                                
                }                
            }
        }
        
        
        for( i = 0 ; i < 32 ; i += 4) {
            cmix[i/4] = (fnv(fnv(fnv(mix[i], mix[i+1]), mix[i+2]), mix[i+3]));
        }
        

        uint result = computeSha3(s,cmix); 

        return result;
        
    }
}

/**
* @title RLPReader
*
* RLPReader is used to read and parse RLP encoded data in memory.
*
* @author Andreas Olofsson ([email protected])
*/
library RLP {

 uint constant DATA_SHORT_START = 0x80;
 uint constant DATA_LONG_START = 0xB8;
 uint constant LIST_SHORT_START = 0xC0;
 uint constant LIST_LONG_START = 0xF8;

 uint constant DATA_LONG_OFFSET = 0xB7;
 uint constant LIST_LONG_OFFSET = 0xF7;


 struct RLPItem {
     uint _unsafe_memPtr;    // Pointer to the RLP-encoded bytes.
     uint _unsafe_length;    // Number of bytes. This is the full length of the string.
 }

 struct Iterator {
     RLPItem _unsafe_item;   // Item that's being iterated over.
     uint _unsafe_nextPtr;   // Position of the next item in the list.
 }

 /* Iterator */

 function next(Iterator memory self) internal constant returns (RLPItem memory subItem) {
     if(hasNext(self)) {
         var ptr = self._unsafe_nextPtr;
         var itemLength = _itemLength(ptr);
         subItem._unsafe_memPtr = ptr;
         subItem._unsafe_length = itemLength;
         self._unsafe_nextPtr = ptr + itemLength;
     }
     else
         throw;
 }

 function next(Iterator memory self, bool strict) internal constant returns (RLPItem memory subItem) {
     subItem = next(self);
     if(strict && !_validate(subItem))
         throw;
     return;
 }

 function hasNext(Iterator memory self) internal constant returns (bool) {
     var item = self._unsafe_item;
     return self._unsafe_nextPtr < item._unsafe_memPtr + item._unsafe_length;
 }

 /* RLPItem */

 /// @dev Creates an RLPItem from an array of RLP encoded bytes.
 /// @param self The RLP encoded bytes.
 /// @return An RLPItem
 function toRLPItem(bytes memory self) internal constant returns (RLPItem memory) {
     uint len = self.length;
     if (len == 0) {
         return RLPItem(0, 0);
     }
     uint memPtr;
     assembly {
         memPtr := add(self, 0x20)
     }
     return RLPItem(memPtr, len);
 }

 /// @dev Creates an RLPItem from an array of RLP encoded bytes.
 /// @param self The RLP encoded bytes.
 /// @param strict Will throw if the data is not RLP encoded.
 /// @return An RLPItem
 function toRLPItem(bytes memory self, bool strict) internal constant returns (RLPItem memory) {
     var item = toRLPItem(self);
     if(strict) {
         uint len = self.length;
         if(_payloadOffset(item) > len)
             throw;
         if(_itemLength(item._unsafe_memPtr) != len)
             throw;
         if(!_validate(item))
             throw;
     }
     return item;
 }

 /// @dev Check if the RLP item is null.
 /// @param self The RLP item.
 /// @return 'true' if the item is null.
 function isNull(RLPItem memory self) internal constant returns (bool ret) {
     return self._unsafe_length == 0;
 }

 /// @dev Check if the RLP item is a list.
 /// @param self The RLP item.
 /// @return 'true' if the item is a list.
 function isList(RLPItem memory self) internal constant returns (bool ret) {
     if (self._unsafe_length == 0)
         return false;
     uint memPtr = self._unsafe_memPtr;
     assembly {
         ret := iszero(lt(byte(0, mload(memPtr)), 0xC0))
     }
 }

 /// @dev Check if the RLP item is data.
 /// @param self The RLP item.
 /// @return 'true' if the item is data.
 function isData(RLPItem memory self) internal constant returns (bool ret) {
     if (self._unsafe_length == 0)
         return false;
     uint memPtr = self._unsafe_memPtr;
     assembly {
         ret := lt(byte(0, mload(memPtr)), 0xC0)
     }
 }

 /// @dev Check if the RLP item is empty (string or list).
 /// @param self The RLP item.
 /// @return 'true' if the item is null.
 function isEmpty(RLPItem memory self) internal constant returns (bool ret) {
     if(isNull(self))
         return false;
     uint b0;
     uint memPtr = self._unsafe_memPtr;
     assembly {
         b0 := byte(0, mload(memPtr))
     }
     return (b0 == DATA_SHORT_START || b0 == LIST_SHORT_START);
 }

 /// @dev Get the number of items in an RLP encoded list.
 /// @param self The RLP item.
 /// @return The number of items.
 function items(RLPItem memory self) internal constant returns (uint) {
     if (!isList(self))
         return 0;
     uint b0;
     uint memPtr = self._unsafe_memPtr;
     assembly {
         b0 := byte(0, mload(memPtr))
     }
     uint pos = memPtr + _payloadOffset(self);
     uint last = memPtr + self._unsafe_length - 1;
     uint itms;
     while(pos <= last) {
         pos += _itemLength(pos);
         itms++;
     }
     return itms;
 }

 /// @dev Create an iterator.
 /// @param self The RLP item.
 /// @return An 'Iterator' over the item.
 function iterator(RLPItem memory self) internal constant returns (Iterator memory it) {
     if (!isList(self))
         throw;
     uint ptr = self._unsafe_memPtr + _payloadOffset(self);
     it._unsafe_item = self;
     it._unsafe_nextPtr = ptr;
 }

 /// @dev Return the RLP encoded bytes.
 /// @param self The RLPItem.
 /// @return The bytes.
 function toBytes(RLPItem memory self) internal constant returns (bytes memory bts) {
     var len = self._unsafe_length;
     if (len == 0)
         return;
     bts = new bytes(len);
     _copyToBytes(self._unsafe_memPtr, bts, len);
 }

 /// @dev Decode an RLPItem into bytes. This will not work if the
 /// RLPItem is a list.
 /// @param self The RLPItem.
 /// @return The decoded string.
 function toData(RLPItem memory self) internal constant returns (bytes memory bts) {
     if(!isData(self))
         throw;
     var (rStartPos, len) = _decode(self);
     bts = new bytes(len);
     _copyToBytes(rStartPos, bts, len);
 }

 /// @dev Get the list of sub-items from an RLP encoded list.
 /// Warning: This is inefficient, as it requires that the list is read twice.
 /// @param self The RLP item.
 /// @return Array of RLPItems.
 function toList(RLPItem memory self) internal constant returns (RLPItem[] memory list) {
     if(!isList(self))
         throw;
     var numItems = items(self);
     list = new RLPItem[](numItems);
     var it = iterator(self);
     uint idx;
     while(hasNext(it)) {
         list[idx] = next(it);
         idx++;
     }
 }

 /// @dev Decode an RLPItem into an ascii string. This will not work if the
 /// RLPItem is a list.
 /// @param self The RLPItem.
 /// @return The decoded string.
 function toAscii(RLPItem memory self) internal constant returns (string memory str) {
     if(!isData(self))
         throw;
     var (rStartPos, len) = _decode(self);
     bytes memory bts = new bytes(len);
     _copyToBytes(rStartPos, bts, len);
     str = string(bts);
 }

 /// @dev Decode an RLPItem into a uint. This will not work if the
 /// RLPItem is a list.
 /// @param self The RLPItem.
 /// @return The decoded string.
 function toUint(RLPItem memory self) internal constant returns (uint data) {
     if(!isData(self))
         throw;
     var (rStartPos, len) = _decode(self);
     if (len > 32 || len == 0)
         throw;
     assembly {
         data := div(mload(rStartPos), exp(256, sub(32, len)))
     }
 }

 /// @dev Decode an RLPItem into a boolean. This will not work if the
 /// RLPItem is a list.
 /// @param self The RLPItem.
 /// @return The decoded string.
 function toBool(RLPItem memory self) internal constant returns (bool data) {
     if(!isData(self))
         throw;
     var (rStartPos, len) = _decode(self);
     if (len != 1)
         throw;
     uint temp;
     assembly {
         temp := byte(0, mload(rStartPos))
     }
     if (temp > 1)
         throw;
     return temp == 1 ? true : false;
 }

 /// @dev Decode an RLPItem into a byte. This will not work if the
 /// RLPItem is a list.
 /// @param self The RLPItem.
 /// @return The decoded string.
 function toByte(RLPItem memory self) internal constant returns (byte data) {
     if(!isData(self))
         throw;
     var (rStartPos, len) = _decode(self);
     if (len != 1)
         throw;
     uint temp;
     assembly {
         temp := byte(0, mload(rStartPos))
     }
     return byte(temp);
 }

 /// @dev Decode an RLPItem into an int. This will not work if the
 /// RLPItem is a list.
 /// @param self The RLPItem.
 /// @return The decoded string.
 function toInt(RLPItem memory self) internal constant returns (int data) {
     return int(toUint(self));
 }

 /// @dev Decode an RLPItem into a bytes32. This will not work if the
 /// RLPItem is a list.
 /// @param self The RLPItem.
 /// @return The decoded string.
 function toBytes32(RLPItem memory self) internal constant returns (bytes32 data) {
     return bytes32(toUint(self));
 }

 /// @dev Decode an RLPItem into an address. This will not work if the
 /// RLPItem is a list.
 /// @param self The RLPItem.
 /// @return The decoded string.
 function toAddress(RLPItem memory self) internal constant returns (address data) {
     if(!isData(self))
         throw;
     var (rStartPos, len) = _decode(self);
     if (len != 20)
         throw;
     assembly {
         data := div(mload(rStartPos), exp(256, 12))
     }
 }

 // Get the payload offset.
 function _payloadOffset(RLPItem memory self) private constant returns (uint) {
     if(self._unsafe_length == 0)
         return 0;
     uint b0;
     uint memPtr = self._unsafe_memPtr;
     assembly {
         b0 := byte(0, mload(memPtr))
     }
     if(b0 < DATA_SHORT_START)
         return 0;
     if(b0 < DATA_LONG_START || (b0 >= LIST_SHORT_START && b0 < LIST_LONG_START))
         return 1;
     if(b0 < LIST_SHORT_START)
         return b0 - DATA_LONG_OFFSET + 1;
     return b0 - LIST_LONG_OFFSET + 1;
 }

 // Get the full length of an RLP item.
 function _itemLength(uint memPtr) private constant returns (uint len) {
     uint b0;
     assembly {
         b0 := byte(0, mload(memPtr))
     }
     if (b0 < DATA_SHORT_START)
         len = 1;
     else if (b0 < DATA_LONG_START)
         len = b0 - DATA_SHORT_START + 1;
     else if (b0 < LIST_SHORT_START) {
         assembly {
             let bLen := sub(b0, 0xB7) // bytes length (DATA_LONG_OFFSET)
             let dLen := div(mload(add(memPtr, 1)), exp(256, sub(32, bLen))) // data length
             len := add(1, add(bLen, dLen)) // total length
         }
     }
     else if (b0 < LIST_LONG_START)
         len = b0 - LIST_SHORT_START + 1;
     else {
         assembly {
             let bLen := sub(b0, 0xF7) // bytes length (LIST_LONG_OFFSET)
             let dLen := div(mload(add(memPtr, 1)), exp(256, sub(32, bLen))) // data length
             len := add(1, add(bLen, dLen)) // total length
         }
     }
 }

 // Get start position and length of the data.
 function _decode(RLPItem memory self) private constant returns (uint memPtr, uint len) {
     if(!isData(self))
         throw;
     uint b0;
     uint start = self._unsafe_memPtr;
     assembly {
         b0 := byte(0, mload(start))
     }
     if (b0 < DATA_SHORT_START) {
         memPtr = start;
         len = 1;
         return;
     }
     if (b0 < DATA_LONG_START) {
         len = self._unsafe_length - 1;
         memPtr = start + 1;
     } else {
         uint bLen;
         assembly {
             bLen := sub(b0, 0xB7) // DATA_LONG_OFFSET
         }
         len = self._unsafe_length - 1 - bLen;
         memPtr = start + bLen + 1;
     }
     return;
 }

 // Assumes that enough memory has been allocated to store in target.
 function _copyToBytes(uint btsPtr, bytes memory tgt, uint btsLen) private constant {
     // Exploiting the fact that 'tgt' was the last thing to be allocated,
     // we can write entire words, and just overwrite any excess.
     assembly {
         {
                 let i := 0 // Start at arr + 0x20
                 let words := div(add(btsLen, 31), 32)
                 let rOffset := btsPtr
                 let wOffset := add(tgt, 0x20)
             tag_loop:
                 jumpi(end, eq(i, words))
                 {
                     let offset := mul(i, 0x20)
                     mstore(add(wOffset, offset), mload(add(rOffset, offset)))
                     i := add(i, 1)
                 }
                 jump(tag_loop)
             end:
                 mstore(add(tgt, add(0x20, mload(tgt))), 0)
         }
     }
 }

     // Check that an RLP item is valid.
     function _validate(RLPItem memory self) private constant returns (bool ret) {
         // Check that RLP is well-formed.
         uint b0;
         uint b1;
         uint memPtr = self._unsafe_memPtr;
         assembly {
             b0 := byte(0, mload(memPtr))
             b1 := byte(1, mload(memPtr))
         }
         if(b0 == DATA_SHORT_START + 1 && b1 < DATA_SHORT_START)
             return false;
         return true;
     }
}




contract Agt {
    using RLP for RLP.RLPItem;
    using RLP for RLP.Iterator;
    using RLP for bytes;
 
    struct BlockHeader {
        uint       prevBlockHash; // 0
        uint       coinbase;      // 1
        uint       blockNumber;   // 8
        //uint       gasUsed;       // 10
        uint       timestamp;     // 11
        bytes32    extraData;     // 12
    }
 
    function Agt() {}
     
    function parseBlockHeader( bytes rlpHeader ) constant internal returns(BlockHeader) {
        BlockHeader memory header;
        
        var it = rlpHeader.toRLPItem().iterator();        
        uint idx;
        while(it.hasNext()) {
            if( idx == 0 ) header.prevBlockHash = it.next().toUint();
            else if ( idx == 2 ) header.coinbase = it.next().toUint();
            else if ( idx == 8 ) header.blockNumber = it.next().toUint();
            else if ( idx == 11 ) header.timestamp = it.next().toUint();
            else if ( idx == 12 ) header.extraData = bytes32(it.next().toUint());
            else it.next();
            
            idx++;
        }
 
        return header;        
    }
            
    //event VerifyAgt( string msg, uint index );
    event VerifyAgt( uint error, uint index );    
    
    struct VerifyAgtData {
        uint rootHash;
        uint rootMin;
        uint rootMax;
        
        uint leafHash;
        uint leafCounter;        
    }

    function verifyAgt( VerifyAgtData data,
                        uint   branchIndex,
                        uint[] countersBranch,
                        uint[] hashesBranch ) constant internal returns(bool) {
                        
        uint currentHash = data.leafHash & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
        
        uint leftCounterMin;
        uint leftCounterMax;        
        uint leftHash;
        
        uint rightCounterMin;
        uint rightCounterMax;        
        uint rightHash;
        
        uint min = data.leafCounter;
        uint max = data.leafCounter;
        
        for( uint i = 0 ; i < countersBranch.length ; i++ ) {
            if( branchIndex & 0x1 > 0 ) {
                leftCounterMin = countersBranch[i] & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
                leftCounterMax = countersBranch[i] >> 128;                
                leftHash    = hashesBranch[i];
                
                rightCounterMin = min;
                rightCounterMax = max;
                rightHash    = currentHash;                
            }
            else {                
                leftCounterMin = min;
                leftCounterMax = max;
                leftHash    = currentHash;
                
                rightCounterMin = countersBranch[i] & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
                rightCounterMax = countersBranch[i] >> 128;                
                rightHash    = hashesBranch[i];                                            
            }
            
            currentHash = uint(sha3(leftCounterMin + (leftCounterMax << 128),
                                    leftHash,
                                    rightCounterMin + (rightCounterMax << 128),
                                    rightHash)) & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
            
            if( (leftCounterMin >= leftCounterMax) || (rightCounterMin >= rightCounterMax) ) {
                if( i > 0 ) {
                    //VerifyAgt( "counters mismatch",i);
                    VerifyAgt( 0x80000000, i );
                    return false;
                }
                if( leftCounterMin > leftCounterMax ) {
                    //VerifyAgt( "counters mismatch",i);
                    VerifyAgt( 0x80000001, i );                
                    return false;
                }
                if( rightCounterMin > rightCounterMax ) {
                    //VerifyAgt( "counters mismatch",i);
                    VerifyAgt( 0x80000002, i );                
                    return false;
                }                
            }
            
            if( leftCounterMax >= rightCounterMin ) {
                VerifyAgt( 0x80000009, i );            
                return false;
            }

            min = leftCounterMin;
            max = rightCounterMax;
            
            branchIndex = branchIndex / 2;
        }

        if( min != data.rootMin ) {
            //VerifyAgt( "min does not match root min",min);
            VerifyAgt( 0x80000003, min );                        
            return false;
        }
        if( max != data.rootMax ) {
            //VerifyAgt( "max does not match root max",max);
            VerifyAgt( 0x80000004, max );                    
            return false;
        }
        
        if( currentHash != data.rootHash ) {
            //VerifyAgt( "hash does not match root hash",currentHash);        
            VerifyAgt( 0x80000005, currentHash );
            return false;
        }
        
        return true;
    }
    
    function verifyAgtDebugForTesting( uint rootHash,
                                       uint rootMin,
                                       uint rootMax,
                                       uint leafHash,
                                       uint leafCounter,
                                       uint branchIndex,
                                       uint[] countersBranch,
                                       uint[] hashesBranch ) returns(bool) {
                                       
        VerifyAgtData memory data;
        data.rootHash = rootHash;
        data.rootMin = rootMin;
        data.rootMax = rootMax;
        data.leafHash = leafHash;
        data.leafCounter = leafCounter;
        
        return verifyAgt( data, branchIndex, countersBranch, hashesBranch );
    }         
}

contract WeightedSubmission {
    function WeightedSubmission(){}
    
    struct SingleSubmissionData {
        uint128 numShares;
        uint128 submissionValue;
        uint128 totalPreviousSubmissionValue;
        uint128 min;
        uint128 max;
        uint128 augRoot;
    }
    
    struct SubmissionMetaData {
        uint64  numPendingSubmissions;
        uint32  readyForVerification; // suppose to be bool
        uint32  lastSubmissionBlockNumber;
        uint128 totalSubmissionValue;
        uint128 difficulty;
        uint128 lastCounter;
        
        uint    submissionSeed;
        
    }
    
    mapping(address=>SubmissionMetaData) submissionsMetaData;
    
    // (user, submission number)=>data
    mapping(address=>mapping(uint=>SingleSubmissionData)) submissionsData;
    
    event SubmitClaim( address indexed sender, uint error, uint errorInfo );
    function submitClaim( uint numShares, uint difficulty, uint min, uint max, uint augRoot, bool lastClaimBeforeVerification ) {
        SubmissionMetaData memory metaData = submissionsMetaData[msg.sender];
        
        if( metaData.lastCounter >= min ) {
            // miner cheated. min counter is too low
            SubmitClaim( msg.sender, 0x81000001, metaData.lastCounter ); 
            return;        
        }
        
        if( metaData.readyForVerification > 0 ) {
            // miner cheated - should go verification first
            SubmitClaim( msg.sender, 0x81000002, 0 ); 
            return;
        }
        
        if( metaData.numPendingSubmissions > 0 ) {
            if( metaData.difficulty != difficulty ) {
                // could not change difficulty before verification
                SubmitClaim( msg.sender, 0x81000003, metaData.difficulty ); 
                return;            
            }
        }
        
        SingleSubmissionData memory submissionData;
        
        submissionData.numShares = uint64(numShares);
        uint blockDifficulty;
        if( block.difficulty == 0 ) {
            // testrpc - fake increasing difficulty
            blockDifficulty = (900000000 * (metaData.numPendingSubmissions+1)); 
        }
        else {
            blockDifficulty = block.difficulty;
        }
        
        submissionData.submissionValue = uint128((uint(numShares * difficulty) * (5 ether)) / blockDifficulty);
        
        submissionData.totalPreviousSubmissionValue = metaData.totalSubmissionValue;
        submissionData.min = uint128(min);
        submissionData.max = uint128(max);
        submissionData.augRoot = uint128(augRoot);
        
        (submissionsData[msg.sender])[metaData.numPendingSubmissions] = submissionData;
        
        // update meta data
        metaData.numPendingSubmissions++;
        metaData.lastSubmissionBlockNumber = uint32(block.number);
        metaData.difficulty = uint128(difficulty);
        metaData.lastCounter = uint128(max);
        metaData.readyForVerification = lastClaimBeforeVerification ? uint32(1) : uint32(0);

        uint128 temp128;
        
        
        temp128 = metaData.totalSubmissionValue; 

        metaData.totalSubmissionValue += submissionData.submissionValue;
        
        if( temp128 > metaData.totalSubmissionValue ) {
            // overflow in calculation
            // note that this code is reachable if user is dishonest and give false
            // report on his submission. but even without
            // this validation, user cannot benifit from the overflow
            SubmitClaim( msg.sender, 0x81000005, 0 ); 
            return;                                
        }
                
        
        submissionsMetaData[msg.sender] = metaData;
        
        // everything is ok
        SubmitClaim( msg.sender, 0, numShares * difficulty );
    }

    function getClaimSeed(address sender) constant returns(uint){
        SubmissionMetaData memory metaData = submissionsMetaData[sender];
        if( metaData.readyForVerification == 0 ) return 0;
        
        if( metaData.submissionSeed != 0 ) return metaData.submissionSeed; 
        
        uint lastBlockNumber = uint(metaData.lastSubmissionBlockNumber);
        
        if( block.number > lastBlockNumber + 200 ) return 0;
        if( block.number <= lastBlockNumber + 15 ) return 0;
                
        return uint(block.blockhash(lastBlockNumber + 10));
    }
    
    event StoreClaimSeed( address indexed sender, uint error, uint errorInfo );
    function storeClaimSeed( address miner ) {
        // anyone who is willing to pay gas fees can call this function
        uint seed = getClaimSeed( miner );
        if( seed != 0 ) {
            submissionsMetaData[miner].submissionSeed = seed;
            StoreClaimSeed( msg.sender, 0, uint(miner) );
            return;
        }
        
        // else
        SubmissionMetaData memory metaData = submissionsMetaData[miner];
        uint lastBlockNumber = uint(metaData.lastSubmissionBlockNumber);
                
        if( metaData.readyForVerification == 0 ) {
            // submission is not ready for verification
            StoreClaimSeed( msg.sender, 0x8000000, uint(miner) );
        }
        else if( block.number > lastBlockNumber + 200 ) {
            // submission is not ready for verification
            StoreClaimSeed( msg.sender, 0x8000001, uint(miner) );
        }
        else if( block.number <= lastBlockNumber + 15 ) {
            // it is too late to call store function
            StoreClaimSeed( msg.sender, 0x8000002, uint(miner) );
        }
        else {
            // unknown error
            StoreClaimSeed( msg.sender, 0x8000003, uint(miner) );
        }
    }

    function verifySubmissionIndex( address sender, uint seed, uint submissionNumber, uint shareIndex ) constant returns(bool) {
        if( seed == 0 ) return false;
    
        uint totalValue = uint(submissionsMetaData[sender].totalSubmissionValue);
        uint numPendingSubmissions = uint(submissionsMetaData[sender].numPendingSubmissions);

        SingleSubmissionData memory submissionData = (submissionsData[sender])[submissionNumber];        
        
        if( submissionNumber >= numPendingSubmissions ) return false;
        
        uint seed1 = seed & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
        uint seed2 = seed / (2**128);
        
        uint selectedValue = seed1 % totalValue;
        if( uint(submissionData.totalPreviousSubmissionValue) >= selectedValue ) return false;
        if( uint(submissionData.totalPreviousSubmissionValue + submissionData.submissionValue) < selectedValue ) return false;  

        uint expectedShareshareIndex = (seed2 % uint(submissionData.numShares));
        if( expectedShareshareIndex != shareIndex ) return false;
        
        return true;
    }
    
    function calculateSubmissionIndex( address sender, uint seed ) constant returns(uint[2]) {
        // this function should be executed off chain - hene, it is not optimized
        uint seed1 = seed & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
        uint seed2 = seed / (2**128);

        uint totalValue = uint(submissionsMetaData[sender].totalSubmissionValue);
        uint numPendingSubmissions = uint(submissionsMetaData[sender].numPendingSubmissions);

        uint selectedValue = seed1 % totalValue;
        
        SingleSubmissionData memory submissionData;        
        
        for( uint submissionInd = 0 ; submissionInd < numPendingSubmissions ; submissionInd++ ) {
            submissionData = (submissionsData[sender])[submissionInd];        
            if( uint(submissionData.totalPreviousSubmissionValue + submissionData.submissionValue) >= selectedValue ) break;  
        }
        
        // unexpected error
        if( submissionInd == numPendingSubmissions ) return [uint(0xFFFFFFFFFFFFFFFF),0xFFFFFFFFFFFFFFFF];

        uint shareIndex = seed2 % uint(submissionData.numShares); 
        
        return [submissionInd, shareIndex];
    }
    
    // should be called only from verify claim
    function closeSubmission( address sender ) internal {
        SubmissionMetaData memory metaData = submissionsMetaData[sender];
        metaData.numPendingSubmissions = 0;
        metaData.totalSubmissionValue = 0;
        metaData.readyForVerification = 0;
        metaData.submissionSeed = 0;
        
        // last counter must not be reset
        // last submission block number and difficulty are also kept, but it is not a must
        // only to save some gas        
        
        submissionsMetaData[sender] = metaData;
    }
    
    struct SubmissionDataForClaimVerification {
        uint lastCounter;
        uint shareDifficulty;
        uint totalSubmissionValue;
        uint min;
        uint max;
        uint augMerkle;
        
        bool indicesAreValid;
        bool readyForVerification;
    }
    
    function getClaimData( address sender, uint submissionIndex, uint shareIndex, uint seed )
                           constant internal returns(SubmissionDataForClaimVerification){
                           
        SubmissionDataForClaimVerification memory output;

        SubmissionMetaData memory metaData = submissionsMetaData[sender];
        
        output.lastCounter = uint(metaData.lastCounter);
        output.shareDifficulty = uint(metaData.difficulty);
        output.totalSubmissionValue = metaData.totalSubmissionValue;
        

        SingleSubmissionData memory submissionData = (submissionsData[sender])[submissionIndex];
        
        output.min = uint(submissionData.min);
        output.max = uint(submissionData.max);
        output.augMerkle = uint(submissionData.augRoot);
        
        output.indicesAreValid = verifySubmissionIndex( sender, seed, submissionIndex, shareIndex );
        output.readyForVerification = (metaData.readyForVerification > 0);
        
        return output; 
    }
    
    function debugGetNumPendingSubmissions( address sender ) constant returns(uint) {
        return uint(submissionsMetaData[sender].numPendingSubmissions);
    }
    
    event DebugResetSubmissions( address indexed sender, uint error, uint errorInfo );
    function debugResetSubmissions( ) {
        // should be called only in emergency
        // msg.sender will loose all its pending shares
        closeSubmission(msg.sender);
        DebugResetSubmissions( msg.sender, 0, 0 );
    }    
}


contract SmartPool is Agt, WeightedSubmission {    
    string  public version = "0.1.1";
    
    Ethash  public ethashContract; 
    address public withdrawalAddress;
    mapping(address=>bool) public owners; 
    
    bool public newVersionReleased = false;
        
    struct MinerData {
        bytes32        minerId;
        address        paymentAddress;
    }

    mapping(address=>MinerData) minersData;
    mapping(bytes32=>bool)      public existingIds;        
    
    bool public whiteListEnabled;
    bool public blackListEnabled;
    mapping(address=>bool) whiteList;
    mapping(address=>bool) blackList;    
    
    function SmartPool( address[] _owners,
                        Ethash _ethashContract,
                        address _withdrawalAddress,
                        bool _whiteListEnabeled,
                        bool _blackListEnabled ) payable {
                        
        for( uint i = 0 ; i < _owners.length ; i++ ) {
            owners[_owners[0]] = true; 
            owners[_owners[1]] = true;
            owners[_owners[2]] = true;
        }
        
        ethashContract = _ethashContract;
        withdrawalAddress = _withdrawalAddress;
        
        whiteListEnabled = _whiteListEnabeled;
        blackListEnabled = _blackListEnabled;               
    }
    
    function declareNewerVersion() {
        if( ! owners[msg.sender] ) throw;
        
        newVersionReleased = true;
        
        //if( ! msg.sender.send(this.balance) ) throw;
    }
    
    event Withdraw( address indexed sender, uint error, uint errorInfo );
    function withdraw( uint amount ) {
        if( ! owners[msg.sender] ) {
            // only ownder can withdraw
            Withdraw( msg.sender, 0x80000000, amount );
            return;
        }
        
        if( ! withdrawalAddress.send( amount ) ) throw;
        
        Withdraw( msg.sender, 0, amount );            
    }
    
    function to62Encoding( uint id, uint numChars ) constant returns(bytes32) {
        if( id >= (26+26+10)**numChars ) throw;
        uint result = 0;
        for( uint i = 0 ; i < numChars ; i++ ) {
            uint b = id % (26+26+10);
            uint8 char;
            if( b < 10 ) {
                char = uint8(b + 0x30); // 0x30 = '0' 
            }
            else if( b < 26 + 10 ) {
                char = uint8(b + 0x61 - 10); //0x61 = 'a'
            }
            else {
                char = uint8(b + 0x41 - 26 - 10); // 0x41 = 'A'         
            }
            
            result = (result * 256) + char;
            id /= (26+26+10);
        }

        return bytes32(result);
    }
        
    event Register( address indexed sender, uint error, uint errorInfo );    
    function register( address paymentAddress ) {
        address minerAddress = msg.sender;
        
        // build id
        uint id = uint(minerAddress) % (26+26+10)**11;        
        bytes32 minerId = to62Encoding(id,11);
        
        if( existingIds[minersData[minerAddress].minerId] ) {
            // miner id is already in use
            Register( msg.sender, 0x80000000, uint(minerId) ); 
            return;
        }
        
        if( paymentAddress == address(0) ) {
            // payment address is 0
            Register( msg.sender, 0x80000001, uint(paymentAddress) ); 
            return;
        }
        
        if( whiteListEnabled ) {
            if( ! whiteList[ msg.sender ] ) {
                // miner not in white list
                Register( msg.sender, 0x80000002, uint(minerId) );
                return;                 
            }
        }
        
        if( blackListEnabled ) {
            if( blackList[ msg.sender ] ) {
                // miner on black list
                Register( msg.sender, 0x80000003, uint(minerId) );
                return;                 
            }        
        }
        
        
        
        // last counter is set to 0. 
        // It might be safer to change it to now.
        //minersData[minerAddress].lastCounter = now * (2**64);
        minersData[minerAddress].paymentAddress = paymentAddress;        
        minersData[minerAddress].minerId = minerId;
        existingIds[minersData[minerAddress].minerId] = true;
        
        // succesful registration
        Register( msg.sender, 0, 0 ); 
    }

    function canRegister(address sender) constant returns(bool) {
        uint id = uint(sender) % (26+26+10)**11;
        bytes32 expectedId = to62Encoding(id,11);
        
        if( whiteListEnabled ) {
            if( ! whiteList[ sender ] ) return false; 
        }
        if( blackListEnabled ) {
            if( blackList[ sender ] ) return false;        
        }
        
        return ! existingIds[expectedId];
    }
    
    function isRegistered(address sender) constant returns(bool) {
        return minersData[sender].paymentAddress != address(0);
    }
    
    function getMinerId(address sender) constant returns(bytes32) {
        return minersData[sender].minerId;
    }

    event UpdateWhiteList( address indexed miner, uint error, uint errorInfo, bool add );
    event UpdateBlackList( address indexed miner, uint error, uint errorInfo, bool add );    

    function unRegister( address miner ) internal {
        minersData[miner].paymentAddress = address(0);
        existingIds[minersData[miner].minerId] = false;            
    }
    
    function updateWhiteList( address miner, bool add ) {
        if( ! owners[ msg.sender ] ) {
            // only owner can update list
            UpdateWhiteList( msg.sender, 0x80000000, 0, add );
            return;
        }
        if( ! whiteListEnabled ) {
            // white list is not enabeled
            UpdateWhiteList( msg.sender, 0x80000001, 0, add );        
            return;
        }
        
        whiteList[ miner ] = add;
        if( ! add && isRegistered( miner ) ) {
            // unregister
            unRegister( miner );
        }
        
        UpdateWhiteList( msg.sender, 0, uint(miner), add );
    }

    function updateBlackList( address miner, bool add ) {
        if( ! owners[ msg.sender ] ) {
            // only owner can update list
            UpdateBlackList( msg.sender, 0x80000000, 0, add );
            return;
        }
        if( ! blackListEnabled ) {
            // white list is not enabeled
            UpdateBlackList( msg.sender, 0x80000001, 0, add );        
            return;
        }
        
        blackList[ miner ] = add;
        if( add && isRegistered( miner ) ) {
            // unregister
            unRegister( miner );
        }
        
        UpdateBlackList( msg.sender, 0, uint(miner), add );
    }
    
    event DisableBlackListForever( address indexed sender, uint error, uint errorInfo );    
    function disableBlackListForever() {
        if( ! owners[ msg.sender ] ) {
            // only owner can update list
            DisableBlackListForever( msg.sender, 0x80000000, 0 );
            return;
        }
        
        blackListEnabled = false;
        
        DisableBlackListForever( msg.sender, 0, 0 );        
    }

    event DisableWhiteListForever( address indexed sender, uint error, uint errorInfo );
    function disableWhiteListForever() {
        if( ! owners[ msg.sender ] ) {
            // only owner can update list
            DisableWhiteListForever( msg.sender, 0x80000000, 0 );
            return;
        }
        
        whiteListEnabled = false;
        
        DisableWhiteListForever( msg.sender, 0, 0 );            
    }
    
    event VerifyExtraData( address indexed sender, uint error, uint errorInfo );    
    function verifyExtraData( bytes32 extraData, bytes32 minerId, uint difficulty ) constant internal returns(bool) {
        uint i;
        // compare id
        for( i = 0 ; i < 11 ; i++ ) {
            if( extraData[10+i] != minerId[21+i] ) {
                //ErrorLog( "verifyExtraData: miner id not as expected", 0 );
                VerifyExtraData( msg.sender, 0x83000000, uint(minerId) );         
                return false;            
            }
        }
        
        // compare difficulty
        bytes32 encodedDiff = to62Encoding(difficulty,11);
        for( i = 0 ; i < 11 ; i++ ) {
            if(extraData[i+21] != encodedDiff[21+i]) {
                //ErrorLog( "verifyExtraData: difficulty is not as expected", uint(encodedDiff) );
                VerifyExtraData( msg.sender, 0x83000001, uint(encodedDiff) );
                return false;            
            }  
        }
                
        return true;            
    }    
    
    event VerifyClaim( address indexed sender, uint error, uint errorInfo );
    
        
    function verifyClaim( bytes rlpHeader,
                          uint  nonce,
                          uint  submissionIndex,
                          uint  shareIndex,
                          uint[] dataSetLookup,
                          uint[] witnessForLookup,
                          uint[] augCountersBranch,
                          uint[] augHashesBranch ) {

        if( ! isRegistered(msg.sender) ) {
            // miner is not registered
            VerifyClaim( msg.sender, 0x8400000c, 0 );
            return;         
        }

        SubmissionDataForClaimVerification memory submissionData = getClaimData( msg.sender,
            submissionIndex, shareIndex, getClaimSeed( msg.sender ) ); 
                              
        if( ! submissionData.readyForVerification ) {
            //ErrorLog( "there are no pending claims", 0 );
            VerifyClaim( msg.sender, 0x84000003, 0 );            
            return;
        }
        
        BlockHeader memory header = parseBlockHeader(rlpHeader);

        // check extra data
        if( ! verifyExtraData( header.extraData,
                               minersData[ msg.sender ].minerId,
                               submissionData.shareDifficulty ) ) {
            //ErrorLog( "extra data not as expected", uint(header.extraData) );
            VerifyClaim( msg.sender, 0x84000004, uint(header.extraData) );            
            return;                               
        }
        
        // check coinbase data
        if( header.coinbase != uint(this) ) {
            //ErrorLog( "coinbase not as expected", uint(header.coinbase) );
            VerifyClaim( msg.sender, 0x84000005, uint(header.coinbase) );            
            return;
        }
         
        
        // check counter
        uint counter = header.timestamp * (2 ** 64) + nonce;
        if( counter < submissionData.min ) {
            //ErrorLog( "counter is smaller than min",counter);
            VerifyClaim( msg.sender, 0x84000007, counter );            
            return;                         
        }
        if( counter > submissionData.max ) {
            //ErrorLog( "counter is smaller than max",counter);
            VerifyClaim( msg.sender, 0x84000008, counter );            
            return;                         
        }
        
        // verify agt
        uint leafHash = uint(sha3(rlpHeader));
        VerifyAgtData memory agtData;
        agtData.rootHash = submissionData.augMerkle;
        agtData.rootMin = submissionData.min;
        agtData.rootMax = submissionData.max;
        agtData.leafHash = leafHash;
        agtData.leafCounter = counter;
                

        if( ! verifyAgt( agtData,
                         shareIndex,
                         augCountersBranch,
                         augHashesBranch ) ) {
            //ErrorLog( "verifyAgt failed",0);
            VerifyClaim( msg.sender, 0x84000009, 0 );            
            return;
        }
                          
        
        /*
        // check epoch data - done inside hashimoto
        if( ! ethashContract.isEpochDataSet( header.blockNumber / 30000 ) ) {
            //ErrorLog( "epoch data was not set",header.blockNumber / 30000);
            VerifyClaim( msg.sender, 0x8400000a, header.blockNumber / 30000 );                        
            return;        
        }*/


        // verify ethash
        uint ethash = ethashContract.hashimoto( bytes32(leafHash),
                                                bytes8(nonce),
                                                dataSetLookup,
                                                witnessForLookup,
                                                header.blockNumber / 30000 );
        if( ethash > ((2**256-1)/submissionData.shareDifficulty )) {
            if( ethash == 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE ) {
                //ErrorLog( "epoch data was not set",header.blockNumber / 30000);
                VerifyClaim( msg.sender, 0x8400000a, header.blockNumber / 30000 );                                        
            }
            else {
                //ErrorLog( "ethash difficulty too low",ethash);
                VerifyClaim( msg.sender, 0x8400000b, ethash );
            }            
            return;        
        }
        
        if( getClaimSeed(msg.sender) == 0 ) {
            //ErrorLog( "claim seed is 0", 0 );
            VerifyClaim( msg.sender, 0x84000001, 0 );
            return;        
        }
        
        if( ! submissionData.indicesAreValid ) {
            //ErrorLog( "share index or submission are not as expected. should be:", getShareIndex() );
            VerifyClaim( msg.sender, 0x84000002, 0 );
            return;                
        } 
        
        // recrusive attack is not possible as doPayment is using send and not call.
        if( ! doPayment(submissionData.totalSubmissionValue,
                        minersData[ msg.sender ].paymentAddress) ) {
            // error msg is given in doPayment function
            return;
        }
        
        closeSubmission( msg.sender );
        //minersData[ msg.sender ].pendingClaim = false;
        
        
        VerifyClaim( msg.sender, 0, 0 );                        
        
        
        return;
    }    
    

    // 10000 = 100%
    uint public uncleRate = 500; // 5%
    // 10000 = 100%
    uint public poolFees = 0;


    event IncomingFunds( address sender, uint amountInWei );
    function() payable {
        IncomingFunds( msg.sender, msg.value );
    }

    event SetUnlceRateAndFees( address indexed sender, uint error, uint errorInfo );
    function setUnlceRateAndFees( uint _uncleRate, uint _poolFees ) {
        if( ! owners[msg.sender] ) {
            // only owner should change rates
            SetUnlceRateAndFees( msg.sender, 0x80000000, 0 );
            return;
        }
        
        uncleRate = _uncleRate;
        poolFees = _poolFees;
        
        SetUnlceRateAndFees( msg.sender, 0, 0 );
    }
        
    event DoPayment( address indexed sender, address paymentAddress, uint valueInWei );
    function doPayment( uint submissionValue,
                        address paymentAddress ) internal returns(bool) {

        uint payment = submissionValue;
        // take uncle rate into account
        
        // payment = payment * (1-0.25*uncleRate)
        // uncleRate in [0,10000]
        payment = (payment * (4*10000 - uncleRate)) / (4*10000);
        
        // fees
        payment = (payment * (10000 - poolFees)) / 10000;

        if( payment > this.balance ){
            //ErrorLog( "cannot afford to pay", calcPayment( submissionData.numShares, submissionData.difficulty ) );
            VerifyClaim( msg.sender, 0x84000000, payment );        
            return false;
        }
                
        if( ! paymentAddress.send( payment ) ) throw;
        
        DoPayment( msg.sender, paymentAddress, payment ); 
        
        return true;
    }
    
    function getPoolETHBalance( ) constant returns(uint) {
        // debug function for testrpc
        return this.balance;
    }

    event GetShareIndexDebugForTestRPCSubmissionIndex( uint index );    
    event GetShareIndexDebugForTestRPCShareIndex( uint index );
     
    function getShareIndexDebugForTestRPC( address sender ) {
        uint seed = getClaimSeed( sender );
        uint[2] memory result = calculateSubmissionIndex( sender, seed );
        
        GetShareIndexDebugForTestRPCSubmissionIndex( result[0] );
        GetShareIndexDebugForTestRPCShareIndex( result[1] );        
            
    }        
}

    Contract ABI  
[{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"owners","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"newVersionReleased","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"getPoolETHBalance","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"uncleRate","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"sender","type":"address"}],"name":"debugGetNumPendingSubmissions","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"amount","type":"uint256"}],"name":"withdraw","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"sender","type":"address"}],"name":"canRegister","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"poolFees","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"paymentAddress","type":"address"}],"name":"register","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_uncleRate","type":"uint256"},{"name":"_poolFees","type":"uint256"}],"name":"setUnlceRateAndFees","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"version","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"debugResetSubmissions","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"sender","type":"address"},{"name":"seed","type":"uint256"}],"name":"calculateSubmissionIndex","outputs":[{"name":"","type":"uint256[2]"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"sender","type":"address"}],"name":"getClaimSeed","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"rootHash","type":"uint256"},{"name":"rootMin","type":"uint256"},{"name":"rootMax","type":"uint256"},{"name":"leafHash","type":"uint256"},{"name":"leafCounter","type":"uint256"},{"name":"branchIndex","type":"uint256"},{"name":"countersBranch","type":"uint256[]"},{"name":"hashesBranch","type":"uint256[]"}],"name":"verifyAgtDebugForTesting","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"ethashContract","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"disableBlackListForever","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"sender","type":"address"}],"name":"getShareIndexDebugForTestRPC","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"sender","type":"address"},{"name":"seed","type":"uint256"},{"name":"submissionNumber","type":"uint256"},{"name":"shareIndex","type":"uint256"}],"name":"verifySubmissionIndex","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"miner","type":"address"},{"name":"add","type":"bool"}],"name":"updateWhiteList","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"blackListEnabled","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"rlpHeader","type":"bytes"},{"name":"nonce","type":"uint256"},{"name":"submissionIndex","type":"uint256"},{"name":"shareIndex","type":"uint256"},{"name":"dataSetLookup","type":"uint256[]"},{"name":"witnessForLookup","type":"uint256[]"},{"name":"augCountersBranch","type":"uint256[]"},{"name":"augHashesBranch","type":"uint256[]"}],"name":"verifyClaim","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"sender","type":"address"}],"name":"isRegistered","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"miner","type":"address"}],"name":"storeClaimSeed","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"numShares","type":"uint256"},{"name":"difficulty","type":"uint256"},{"name":"min","type":"uint256"},{"name":"max","type":"uint256"},{"name":"augRoot","type":"uint256"},{"name":"lastClaimBeforeVerification","type":"bool"}],"name":"submitClaim","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"sender","type":"address"}],"name":"getMinerId","outputs":[{"name":"","type":"bytes32"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"whiteListEnabled","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"disableWhiteListForever","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"declareNewerVersion","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"existingIds","outputs":[{"name":"","type":"bool"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"withdrawalAddress","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"miner","type":"address"},{"name":"add","type":"bool"}],"name":"updateBlackList","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"id","type":"uint256"},{"name":"numChars","type":"uint256"}],"name":"to62Encoding","outputs":[{"name":"","type":"bytes32"}],"payable":false,"type":"function"},{"inputs":[{"name":"_owners","type":"address[]"},{"name":"_ethashContract","type":"address"},{"name":"_withdrawalAddress","type":"address"},{"name":"_whiteListEnabeled","type":"bool"},{"name":"_blackListEnabled","type":"bool"}],"payable":true,"type":"constructor"},{"payable":true,"type":"fallback"},{"anonymous":false,"inputs":[{"indexed":true,"name":"sender","type":"address"},{"indexed":false,"name":"error","type":"uint256"},{"indexed":false,"name":"errorInfo","type":"uint256"}],"name":"Withdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"sender","type":"address"},{"indexed":false,"name":"error","type":"uint256"},{"indexed":false,"name":"errorInfo","type":"uint256"}],"name":"Register","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"miner","type":"address"},{"indexed":false,"name":"error","type":"uint256"},{"indexed":false,"name":"errorInfo","type":"uint256"},{"indexed":false,"name":"add","type":"bool"}],"name":"UpdateWhiteList","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"miner","type":"address"},{"indexed":false,"name":"error","type":"uint256"},{"indexed":false,"name":"errorInfo","type":"uint256"},{"indexed":false,"name":"add","type":"bool"}],"name":"UpdateBlackList","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"sender","type":"address"},{"indexed":false,"name":"error","type":"uint256"},{"indexed":false,"name":"errorInfo","type":"uint256"}],"name":"DisableBlackListForever","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"sender","type":"address"},{"indexed":false,"name":"error","type":"uint256"},{"indexed":false,"name":"errorInfo","type":"uint256"}],"name":"DisableWhiteListForever","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"sender","type":"address"},{"indexed":false,"name":"error","type":"uint256"},{"indexed":false,"name":"errorInfo","type":"uint256"}],"name":"VerifyExtraData","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"sender","type":"address"},{"indexed":false,"name":"error","type":"uint256"},{"indexed":false,"name":"errorInfo","type":"uint256"}],"name":"VerifyClaim","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"sender","type":"address"},{"indexed":false,"name":"amountInWei","type":"uint256"}],"name":"IncomingFunds","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"sender","type":"address"},{"indexed":false,"name":"error","type":"uint256"},{"indexed":false,"name":"errorInfo","type":"uint256"}],"name":"SetUnlceRateAndFees","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"sender","type":"address"},{"indexed":false,"name":"paymentAddress","type":"address"},{"indexed":false,"name":"valueInWei","type":"uint256"}],"name":"DoPayment","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"index","type":"uint256"}],"name":"GetShareIndexDebugForTestRPCSubmissionIndex","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"index","type":"uint256"}],"name":"GetShareIndexDebugForTestRPCShareIndex","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"sender","type":"address"},{"indexed":false,"name":"error","type":"uint256"},{"indexed":false,"name":"errorInfo","type":"uint256"}],"name":"SubmitClaim","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"sender","type":"address"},{"indexed":false,"name":"error","type":"uint256"},{"indexed":false,"name":"errorInfo","type":"uint256"}],"name":"StoreClaimSeed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"sender","type":"address"},{"indexed":false,"name":"error","type":"uint256"},{"indexed":false,"name":"errorInfo","type":"uint256"}],"name":"DebugResetSubmissions","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"error","type":"uint256"},{"indexed":false,"name":"index","type":"uint256"}],"name":"VerifyAgt","type":"event"}]

  Contract Creation Code Switch To Opcodes View
60a0604052600560608190527f302e312e310000000000000000000000000000000000000000000000000000006080908152620000409160029190620001f8565b506006805460ff191690556101f4600c556000600d5560405162003e2938819003908190833981016040908152815160208301519183015160608401516080850151929094019390915b60005b5b5b5b5060005b85518110156200019e57600160056000886000815181101515620000b457fe5b90602001906020020151600160a060020a0316600160a060020a0316815260200190815260200160002060006101000a81548160ff0219169083151502179055506001600560008860018151811015156200010b57fe5b90602001906020020151600160a060020a0316600160a060020a0316815260200190815260200160002060006101000a81548160ff0219169083151502179055506001600560008860028151811015156200016257fe5b602090810291909101810151600160a060020a03168252810191909152604001600020805460ff19169115159190911790555b60010162000094565b60038054600160a060020a0319908116600160a060020a0388811691909117909255600480549091169186169190911790556009805460ff19168415151761ff001916610100841515021790555b505050505050620002a2565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200023b57805160ff19168380011785556200026b565b828001600101855582156200026b579182015b828111156200026b5782518255916020019190600101906200024e565b5b506200027a9291506200027e565b5090565b6200029f91905b808211156200027a576000815560010162000285565b5090565b90565b613b7780620002b26000396000f3006060604052361561019e5763ffffffff7c0100000000000000000000000000000000000000000000000000000000600035041663022914a781146101ea5780630289e9661461021a5780630abb84091461023e5780631bc412841461026057806321aa4548146102825780632e1a7d4d146102b0578063320d46d4146102c557806333580959146102f55780634420e4861461031757806346b3f6961461033557806354fd4d501461034d5780635eadd607146103dd5780635ed1057d146103ef5780637087ed2c1461044d5780637ed996a31461047b5780637f949ac01461052c578063838a48d61461055857806384c652961461056a5780639e133be414610588578063ac1d0609146105c1578063ad37c41b146105e4578063c2209acb14610608578063c3c5a5471461074f578063c78769401461077f578063cedb217a1461079d578063e2dea715146107c3578063e2e616bb146107f1578063e390e26314610815578063e3d8699814610827578063ee38530414610839578063f2bcd02214610860578063fc2eb8891461088c578063ff5d2c39146108af575b6101e85b60408051600160a060020a033316815234602082015281517f956d4d6b7078569e4433967114fa7538f233475457dc35578fe282cf58f9e01f929181900390910190a15b565b005b34156101f257fe5b610206600160a060020a03600435166108d7565b604080519115158252519081900360200190f35b341561022257fe5b6102066108ec565b604080519115158252519081900360200190f35b341561024657fe5b61024e6108f5565b60408051918252519081900360200190f35b341561026857fe5b61024e610904565b60408051918252519081900360200190f35b341561028a57fe5b61024e600160a060020a036004351661090a565b60408051918252519081900360200190f35b34156102b857fe5b6101e8600435610933565b005b34156102cd57fe5b610206600160a060020a0360043516610a1e565b604080519115158252519081900360200190f35b34156102fd57fe5b61024e610ad7565b60408051918252519081900360200190f35b341561031f57fe5b6101e8600160a060020a0360043516610add565b005b341561033d57fe5b6101e8600435602435610d1c565b005b341561035557fe5b61035d610ddc565b6040805160208082528351818301528351919283929083019185019080838382156103a3575b8051825260208311156103a357601f199092019160209182019101610383565b505050905090810190601f1680156103cf5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34156103e557fe5b6101e8610e67565b005b34156103f757fe5b61040e600160a060020a0360043516602435610eb6565b6040805190819083908083835b80518252602083111561043b57601f19909201916020918201910161041b565b50505090500191505060405180910390f35b341561045557fe5b61024e600160a060020a0360043516611041565b60408051918252519081900360200190f35b341561048357fe5b6040805160c4356004818101356020818102858101820190965281855261020695833595602480359660443596606435966084359660a43596929560e49590940192829185019084908082843750506040805187358901803560208181028481018201909552818452989a99890198929750908201955093508392508501908490808284375094965061115095505050505050565b604080519115158252519081900360200190f35b341561053457fe5b61053c611195565b60408051600160a060020a039092168252519081900360200190f35b341561056057fe5b6101e86111a4565b005b341561057257fe5b6101e8600160a060020a0360043516611263565b005b341561059057fe5b610206600160a060020a0360043516602435604435606435611308565b604080519115158252519081900360200190f35b34156105c957fe5b6101e8600160a060020a03600435166024351515611479565b005b34156105ec57fe5b6102066115ef565b604080519115158252519081900360200190f35b341561061057fe5b6101e8600480803590602001908201803590602001908080601f016020809104026020016040519081016040528093929190818152602001838380828437505060408051602060608901358a01803582810280850184018652818552999b8b359b848101359b968101359a509098506080019650929450810192829185019084908082843750506040805187358901803560208181028481018201909552818452989a998901989297509082019550935083925085019084908082843750506040805187358901803560208181028481018201909552818452989a998901989297509082019550935083925085019084908082843750506040805187358901803560208181028481018201909552818452989a9989019892975090820195509350839250850190849080828437509496506115fd95505050505050565b005b341561075757fe5b610206600160a060020a0360043516611c62565b604080519115158252519081900360200190f35b341561078757fe5b6101e8600160a060020a0360043516611c88565b005b34156107a557fe5b6101e860043560243560443560643560843560a4351515611ea9565b005b34156107cb57fe5b61024e600160a060020a03600435166124ce565b60408051918252519081900360200190f35b34156107f957fe5b6102066124ed565b604080519115158252519081900360200190f35b341561081d57fe5b6101e86124f6565b005b341561082f57fe5b6101e86125b4565b005b341561084157fe5b6102066004356125ec565b604080519115158252519081900360200190f35b341561086857fe5b61053c612601565b60408051600160a060020a039092168252519081900360200190f35b341561089457fe5b6101e8600160a060020a03600435166024351515612610565b005b34156108b757fe5b61024e60043560243561278e565b60408051918252519081900360200190f35b60056020526000908152604090205460ff1681565b60065460ff1681565b600160a060020a033016315b90565b600c5481565b600160a060020a03811660009081526020819052604090205467ffffffffffffffff165b919050565b600160a060020a03331660009081526005602052604090205460ff1615156109a1576040805163800000008152602081018390528151600160a060020a033316927ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b568928290030190a2610a1b565b600454604051600160a060020a039091169082156108fc029083906000818181858888f1935050505015156109d65760006000fd5b6040805160008152602081018390528151600160a060020a033316927ff279e6a1f5e320cca91135676d9cb6e44ca8a08c0b88342bcdb1144f6511b568928290030190a25b50565b600080806802d227003d8d2af800600160a060020a0385165b069150610a4582600b61278e565b60095490915060ff1615610a7e57600160a060020a0384166000908152600a602052604090205460ff161515610a7e5760009250610ad0565b5b600954610100900460ff1615610ab957600160a060020a0384166000908152600b602052604090205460ff1615610ab95760009250610ad0565b5b60008181526008602052604090205460ff161592505b5050919050565b600d5481565b336000806802d227003d8d2af800600160a060020a0384165b069150610b0482600b61278e565b600160a060020a0384166000908152600760209081526040808320548352600890915290205490915060ff1615610b6f576040805163800000008152602081018390528151600160a060020a03331692600080516020613b2c833981519152928290030190a2610d16565b600160a060020a0384161515610bbc576040805163800000018152600160a060020a03868116602083015282513390911692600080516020613b2c833981519152928290030190a2610d16565b60095460ff1615610c2357600160a060020a0333166000908152600a602052604090205460ff161515610c23576040805163800000028152602081018390528151600160a060020a03331692600080516020613b2c833981519152928290030190a2610d16565b5b600954610100900460ff1615610c8f57600160a060020a0333166000908152600b602052604090205460ff1615610c8f576040805163800000038152602081018390528151600160a060020a03331692600080516020613b2c833981519152928290030190a2610d16565b5b600160a060020a0383811660009081526007602090815260408083206001808201805473ffffffffffffffffffffffffffffffffffffffff19168b88161790559086905585845260088352818420805460ff1916909117905580518381529182019290925281513390931692600080516020613b2c833981519152929181900390910190a25b50505050565b600160a060020a03331660009081526005602052604090205460ff161515610d8a576040805163800000008152600060208201528151600160a060020a033316927f212ff53abc1c86b982eeb544d77036ecfc9e7c368460eeba75aa49c808a1bfa9928290030190a2610dd8565b600c829055600d81905560408051600080825260208201528151600160a060020a033316927f212ff53abc1c86b982eeb544d77036ecfc9e7c368460eeba75aa49c808a1bfa9928290030190a25b5050565b6002805460408051602060018416156101000260001901909316849004601f81018490048402820184019092528181529291830182828015610e5f5780601f10610e3457610100808354040283529160200191610e5f565b820191906000526020600020905b815481529060010190602001808311610e4257829003601f168201915b505050505081565b610e703361281a565b60408051600080825260208201528151600160a060020a033316927fb4392733a0c6dd35350239f2e9eb97a9a9e574fc090445fb267bea4114f9d706928290030190a25b565b610ebe613915565b60006000600060006000610ed061393d565b6001608060020a0388169550600080608060020a8a5b600160a060020a038d1660009081526020819052604090205491900497506001608060020a03608060020a820416965067ffffffffffffffff1694508588811515610f2d57fe5b069350600091505b84821015610fd857600160a060020a038b166000908152600160208181526040808420868552825292839020835160c08101855281546001608060020a038082168352608060020a9182900481169483018590529483015480861696830187905281900485166060830152600290920154808516608083015291909104831660a082015295509190910116849010610fcc57610fd8565b5b600190910190610f35565b84821415611002576040805180820190915267ffffffffffffffff80825260208201529850611033565b82516001608060020a03168781151561101757fe5b0690506040604051908101604052808381526020018281525098505b505050505050505092915050565b600061104b613972565b50600160a060020a038216600090815260208181526040808320815160e081018352815467ffffffffffffffff8116825263ffffffff68010000000000000000820481169583018690526c01000000000000000000000000820416938201939093526001608060020a03608060020a9384900481166060830152600183015480821660808401529390930490921660a08301526002015460c0820152919015156110f85760009250610ad0565b60c08201511561110e578160c001519250610ad0565b50604081015163ffffffff1660c8810143111561112e5760009250610ad0565b600f810143116111415760009250610ad0565b600a81014092505b5050919050565b600061115a6139ae565b8981526020810189905260408101889052606081018790526080810186905261118581868686612b0a565b91505b5098975050505050505050565b600354600160a060020a031681565b600160a060020a03331660009081526005602052604090205460ff161515611212576040805163800000008152600060208201528151600160a060020a033316927ff480ca51e917598d93b5e1f0d9ffaca924650e0be8a44687903f25fc9653b247928290030190a26101e6565b6009805461ff001916905560408051600080825260208201528151600160a060020a033316927ff480ca51e917598d93b5e1f0d9ffaca924650e0be8a44687903f25fc9653b247928290030190a25b565b600061126d613915565b61127683611041565b91506112828383610eb6565b90507f3ba53417e57e443ddb98675e360751dde5188b35238f74080d8dd0ae715b810a8160005b60200201516040518082815260200191505060405180910390a17fc02e7f30f38954ffaa58472135d46a24d0edd3ed7b9badb4940f4856546957248160015b60200201516040518082815260200191505060405180910390a15b505050565b60006000600061131661393d565b60008080808a151561132b576000975061146a565b600160a060020a038c166000908152602081815260408083205460018084528285208f8652845293829020825160c08101845281546001608060020a038082168352608060020a9182900481169683019690965295820154808616948201949094529285900484166060840152600201548084166080840152849004831660a0830152928304909116985067ffffffffffffffff90911696509450858a106113d6576000975061146a565b6001608060020a038b169350608060020a8b5b04925086848115156113f757fe5b0691508185604001516001608060020a0316101515611419576000975061146a565b8185602001518660400151016001608060020a0316101561143d576000975061146a565b84516001608060020a03168381151561145257fe5b069050888114611465576000975061146a565b600197505b50505050505050949350505050565b600160a060020a03331660009081526005602052604090205460ff1615156114f157604080516380000000815260006020820152821515818301529051600160a060020a033316917f6b75ddb2bf3491dca8d6231dc4fd31a97485c8ce82025701005eabdac7efa68d919081900360600190a2610dd8565b60095460ff16151561155357604080516380000001815260006020820152821515818301529051600160a060020a033316917f6b75ddb2bf3491dca8d6231dc4fd31a97485c8ce82025701005eabdac7efa68d919081900360600190a2610dd8565b600160a060020a0382166000908152600a60205260409020805460ff191682158015918217909255611589575061158982611c62565b5b156115985761159882612e51565b5b6040805160008152600160a060020a0384811660208301528315158284015291513392909216917f6b75ddb2bf3491dca8d6231dc4fd31a97485c8ce82025701005eabdac7efa68d9181900360600190a25b5050565b600954610100900460ff1681565b6116056139de565b61160d613a28565b600060006116196139ae565b600061162433611c62565b15156116645760408051638400000c8152600060208201528151600160a060020a03331692600080516020613aec833981519152928290030190a2611c52565b611678338d8d61167333611041565b612ea1565b95508560e0015115156116bf576040805163840000038152600060208201528151600160a060020a03331692600080516020613aec833981519152928290030190a2611c52565b6116c88e61322a565b6080810151600160a060020a033316600090815260076020908152604090912054908901519297506116f992613338565b1515611740576080850151604080516384000004815260208101929092528051600160a060020a03331692600080516020613aec83398151915292908290030190a2611c52565b6020850151600160a060020a033016146117985733600160a060020a0316600080516020613aec83398151915263840000058760200151604051808381526020018281526020019250505060405180910390a2611c52565b8c8560600151680100000000000000000201935085606001518410156117f2576040805163840000078152602081018690528151600160a060020a03331692600080516020613aec833981519152928290030190a2611c52565b8560800151841115611838576040805163840000088152602081018690528151600160a060020a03331692600080516020613aec833981519152928290030190a2611c52565b8d6040518082805190602001908083835b602083106118685780518252601f199092019160209182019101611849565b51815160209384036101000a6000190180199092169116179052604080519290940182900390912060a08c015188526060808d0151928901929092526080808d0151948901949094529087018190529186018890525094506118d091508390508c8a8a612b0a565b1515611910576040805163840000098152600060208201528151600160a060020a03331692600080516020613aec833981519152928290030190a2611c52565b600360009054906101000a9004600160a060020a0316600160a060020a03166340ed79f4846001028f7801000000000000000000000000000000000000000000000000028d8d6175308b6040015181151561196757fe5b60408051600060209182015290517c010000000000000000000000000000000000000000000000000000000063ffffffff8a160281526004810188815277ffffffffffffffffffffffffffffffffffffffffffffffff1988166024830152939092046084830181905260a060448401908152865160a485015286519194939092606482019260c49092019188820191028083838215611a21575b805182526020831115611a2157601f199092019160209182019101611a01565b5050509190910184810383528651815286516020918201925081880191028083838215611a69575b805182526020831115611a6957601f199092019160209182019101611a49565b505050905001975050505050505050602060405180830381600087803b1515611a8e57fe5b6102c65a03f11515611a9c57fe5b50506040515160208801519092509050600019811515611ab857fe5b04811115611b5157806001191415611b165733600160a060020a0316600080516020613aec833981519152638400000a6175308860400151811515611af957fe5b6040805193845291900460208301528051918290030190a2611b4c565b60408051638400000b8152602081018390528151600160a060020a03331692600080516020613aec833981519152928290030190a25b611c52565b611b5a33611041565b1515611b9a576040805163840000018152600060208201528151600160a060020a03331692600080516020613aec833981519152928290030190a2611c52565b8560c001511515611bdf576040805163840000028152600060208201528151600160a060020a03331692600080516020613aec833981519152928290030190a2611c52565b604080870151600160a060020a03338116600090815260076020529290922060010154611c0c92166134b9565b1515611c1757611c52565b611c203361281a565b60408051600080825260208201528151600160a060020a03331692600080516020613aec833981519152928290030190a25b5050505050505050505050505050565b600160a060020a038181166000908152600760205260409020600101541615155b919050565b6000611c92613972565b6000611c9d84611041565b92508215611cf657600160a060020a0380851660008181526020818152604080832060020188905580519283529082019290925281513390931692600080516020613b0c833981519152929181900390910190a2610d16565b5050600160a060020a03821660009081526020818152604091829020825160e081018452815467ffffffffffffffff8116825263ffffffff68010000000000000000820481169483018590526c010000000000000000000000008204169482018590526001608060020a03608060020a918290048116606084015260018401548082166080850152919091041660a082015260029091015460c082015291901515611dd8576040805163080000008152600160a060020a03868116602083015282513390911692600080516020613b0c833981519152928290030190a2610d16565b8060c801431115611e20576040805163080000018152600160a060020a03868116602083015282513390911692600080516020613b0c833981519152928290030190a2610d16565b600f81014311611e67576040805163080000028152600160a060020a03868116602083015282513390911692600080516020613b0c833981519152928290030190a2610d16565b6040805163080000038152600160a060020a03868116602083015282513390911692600080516020613b0c833981519152928290030190a25b5b5b5b50505050565b611eb1613972565b611eb961393d565b600160a060020a033316600090815260208181526040808320815160e081018352815467ffffffffffffffff8116825263ffffffff6801000000000000000082048116958301959095526c010000000000000000000000008104909416928101929092526001608060020a03608060020a9384900481166060840152600182015480821660808501529390930490921660a0820181905260029092015460c082015293508190889010611faf5760a084015160408051638100000181526001608060020a0390921660208301528051600160a060020a03331692600080516020613acc83398151915292908290030190a26124c2565b6000846020015163ffffffff161115611ffc576040805163810000028152600060208201528151600160a060020a03331692600080516020613acc833981519152928290030190a26124c2565b6000846000015167ffffffffffffffff1611156120705760808401516001608060020a0316891461207057608084015160408051638100000381526001608060020a0390921660208301528051600160a060020a03331692600080516020613acc83398151915292908290030190a26124c2565b5b67ffffffffffffffff8a1683524415156120a45783600001516001016335a4e9000267ffffffffffffffff1691506120a8565b4491505b81898b02674563918244f40000028115156120bf57fe5b0483602001906001608060020a031690816001608060020a031681525050836060015183604001906001608060020a031690816001608060020a0316815250508783606001906001608060020a031690816001608060020a0316815250508683608001906001608060020a031690816001608060020a031681525050858360a001906001608060020a031690816001608060020a031681525050826001600033600160a060020a0316600160a060020a031681526020019081526020016000206000866000015167ffffffffffffffff16815260200190815260200160002060008201518160000160006101000a8154816001608060020a0302191690836001608060020a0316021790555060208201518160000160106101000a8154816001608060020a0302191690836001608060020a0316021790555060408201518160010160006101000a8154816001608060020a0302191690836001608060020a0316021790555060608201518160010160106101000a8154816001608060020a0302191690836001608060020a0316021790555060808201518160020160006101000a8154816001608060020a0302191690836001608060020a0316021790555060a08201518160020160106101000a8154816001608060020a0302191690836001608060020a0316021790555090505083600001805180919060010167ffffffffffffffff1667ffffffffffffffff168152505043846040019063ffffffff16908163ffffffff16815250508884608001906001608060020a031690816001608060020a031681525050868460a001906001608060020a031690816001608060020a03168152505084612333576000612336565b60015b63ffffffff16602080860191909152606085018051918501516001608060020a0390830181169182905291925090821611156123a6576040805163810000058152600060208201528151600160a060020a03331692600080516020613acc833981519152928290030190a26124c2565b33600160a060020a0316600081815260208181526040808320885181548a8501518b85015160608d015167ffffffffffffffff1990931667ffffffffffffffff909416939093176bffffffff000000000000000019166801000000000000000063ffffffff92831602176fffffffff00000000000000000000000019166c010000000000000000000000009190931602919091176001608060020a03908116608060020a928216830217835560808b015160018401805460a08e01516fffffffffffffffffffffffffffffffff199091169284169290921783169190921690920291909117905560c089015160029091015580519283528c8e02918301919091528051600080516020613acc8339815191529281900390910190a25b50505050505050505050565b600160a060020a0381166000908152600760205260409020545b919050565b60095460ff1681565b600160a060020a03331660009081526005602052604090205460ff161515612564576040805163800000008152600060208201528151600160a060020a033316927fdc68a38b36901151fe2b8cc3293271f1a845d4942ec98d2edc03516cfd78fe80928290030190a26101e6565b6009805460ff1916905560408051600080825260208201528151600160a060020a033316927fdc68a38b36901151fe2b8cc3293271f1a845d4942ec98d2edc03516cfd78fe80928290030190a25b565b600160a060020a03331660009081526005602052604090205460ff1615156125dc5760006000fd5b6006805460ff191660011790555b565b60086020526000908152604090205460ff1681565b600454600160a060020a031681565b600160a060020a03331660009081526005602052604090205460ff16151561268857604080516380000000815260006020820152821515818301529051600160a060020a033316917fa7f452ac5dbc9e18ae638319e3cdc0653d06cb2f0624e0172a1e8bfb5c030a0d919081900360600190a2610dd8565b600954610100900460ff1615156126ef57604080516380000001815260006020820152821515818301529051600160a060020a033316917fa7f452ac5dbc9e18ae638319e3cdc0653d06cb2f0624e0172a1e8bfb5c030a0d919081900360600190a2610dd8565b600160a060020a0382166000908152600b60205260409020805460ff191682158015919091179091558190612728575061272882611c62565b5b156127375761273782612e51565b5b6040805160008152600160a060020a0384811660208301528315158284015291513392909216917fa7f452ac5dbc9e18ae638319e3cdc0653d06cb2f0624e0172a1e8bfb5c030a0d9181900360600190a25b5050565b600080808080603e86900a87106127a55760006000fd5b60009350600092505b8583101561280957603e875b069150600a8210156127d05750603081016127e9565b60248210156127e35750605781016127e9565b50601d81015b5b61010090930260ff84160192603e875b0496505b6001909201916127ae565b8360010294505b5050505092915050565b612822613972565b6000600083600160a060020a0316600160a060020a0316815260200190815260200160002060e060405190810160405290816000820160009054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff1681526020016000820160089054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600c9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160109054906101000a90046001608060020a03166001608060020a03166001608060020a031681526020016001820160009054906101000a90046001608060020a03166001608060020a03166001608060020a031681526020016001820160109054906101000a90046001608060020a03166001608060020a03166001608060020a0316815260200160028201548152505090506000816000019067ffffffffffffffff16908167ffffffffffffffff1681525050600081606001906001608060020a031690816001608060020a0316815250506000816020019063ffffffff16908163ffffffff168152505060008160c0018181525050806000600084600160a060020a0316600160a060020a0316815260200190815260200160002060008201518160000160006101000a81548167ffffffffffffffff021916908367ffffffffffffffff16021790555060208201518160000160086101000a81548163ffffffff021916908363ffffffff160217905550604082015181600001600c6101000a81548163ffffffff021916908363ffffffff16021790555060608201518160000160106101000a8154816001608060020a0302191690836001608060020a0316021790555060808201518160010160006101000a8154816001608060020a0302191690836001608060020a0316021790555060a08201518160010160106101000a8154816001608060020a0302191690836001608060020a0316021790555060c082015181600201559050505b5050565b606084015160808501516000916001608060020a03169082908190819081908190819080825b8c51811015612d7a5760008e6001161115612bb2578c81815181101515612b5357fe5b906020019060200201516001608060020a0316985060808d82815181101515612b7857fe5b906020019060200201519060020a900497508b81815181101515612b9857fe5b906020019060200201519650829550819450899350612c1b565b8298508197508996508c81815181101515612bc957fe5b906020019060200201516001608060020a0316955060808d82815181101515612bee57fe5b906020019060200201519060020a900494508b81815181101515612c0e57fe5b9060200190602002015193505b60408051608060020a808b028c018252602082018a905287028801818301526060810186905290519081900360800190206001608060020a031699508789101580612c665750848610155b15612d26576000811115612caa576040805163800000008152602081018390528151600080516020613aac833981519152929181900390910190a160009a50612e3f565b87891115612ce8576040805163800000018152602081018390528151600080516020613aac833981519152929181900390910190a160009a50612e3f565b84861115612d26576040805163800000028152602081018390528151600080516020613aac833981519152929181900390910190a160009a50612e3f565b5b858810612d64576040805163800000098152602081018390528151600080516020613aac833981519152929181900390910190a160009a50612e3f565b88925084915060028e5b049d505b600101612b30565b60208f01518314612dbb576040805163800000038152602081018590528151600080516020613aac833981519152929181900390910190a160009a50612e3f565b60408f01518214612dfc576040805163800000048152602081018490528151600080516020613aac833981519152929181900390910190a160009a50612e3f565b8e518a14612e3a576040805163800000058152602081018c90528151600080516020613aac833981519152929181900390910190a160009a50612e3f565b60019a505b50505050505050505050949350505050565b600160a060020a038116600090815260076020908152604080832060018101805473ffffffffffffffffffffffffffffffffffffffff1916905554835260089091529020805460ff191690555b50565b612ea96139de565b612eb16139de565b612eb9613972565b612ec161393d565b6000600089600160a060020a0316600160a060020a0316815260200190815260200160002060e060405190810160405290816000820160009054906101000a900467ffffffffffffffff1667ffffffffffffffff1667ffffffffffffffff1681526020016000820160089054906101000a900463ffffffff1663ffffffff1663ffffffff16815260200160008201600c9054906101000a900463ffffffff1663ffffffff1663ffffffff1681526020016000820160109054906101000a90046001608060020a03166001608060020a03166001608060020a031681526020016001820160009054906101000a90046001608060020a03166001608060020a03166001608060020a031681526020016001820160109054906101000a90046001608060020a03166001608060020a03166001608060020a0316815260200160028201548152505091508160a001516001608060020a031683600001818152505081608001516001608060020a031683602001818152505081606001516001608060020a03168360400181815250506001600089600160a060020a0316600160a060020a03168152602001908152602001600020600088815260200190815260200160002060c060405190810160405290816000820160009054906101000a90046001608060020a03166001608060020a03166001608060020a031681526020016000820160109054906101000a90046001608060020a03166001608060020a03166001608060020a031681526020016001820160009054906101000a90046001608060020a03166001608060020a03166001608060020a031681526020016001820160109054906101000a90046001608060020a03166001608060020a03166001608060020a031681526020016002820160009054906101000a90046001608060020a03166001608060020a03166001608060020a031681526020016002820160109054906101000a90046001608060020a03166001608060020a03166001608060020a031681525050905080606001516001608060020a031683606001818152505080608001516001608060020a03168360800181815250508060a001516001608060020a03168360a00181815250506131fd88868989611308565b151560c08401526020820151600063ffffffff9091161160e084015291925082915b505050949350505050565b613232613a28565b61323a613a28565b613242613a5c565b6000613255613250866135b9565b61360d565b91505b6132618261364b565b1561332c578015156132855761327e61327983613671565b6136c2565b8352613320565b80600214156132a95761329f61327983613671565b6136c2565b6020840152613320565b80600814156132cd576132c361327983613671565b6136c2565b6040840152613320565b80600b14156132f1576132e761327983613671565b6136c2565b6060840152613320565b80600c14156133155761330b61327983613671565b6136c2565b6080840152613320565b61331e82613671565b505b5b5b5b5b600101613258565b8293505b505050919050565b600080805b600b8210156133eb5784601583016020811061335557fe5b1a60f860020a02600160f860020a0319168683600a0160208110151561337757fe5b1a60f860020a02600160f860020a0319161415156133df576040805163830000008152602081018790528151600160a060020a033316927f1f663d8c427e3fbf090ed8c66536b06651bca95051509e3a45cb1cbb286312e8928290030190a2600092506134b0565b5b60019091019061333d565b6133f684600b61278e565b9050600091505b600b8210156134ab5780601583016020811061341557fe5b1a60f860020a02600160f860020a031916868360150160208110151561343757fe5b1a60f860020a02600160f860020a03191614151561349f576040805163830000018152602081018390528151600160a060020a033316927f1f663d8c427e3fbf090ed8c66536b06651bca95051509e3a45cb1cbb286312e8928290030190a2600092506134b0565b5b6001909101906133fd565b600192505b50509392505050565b600c546000908390619c4090810382025b049050612710600d546127100382028115156134e257fe5b04905030600160a060020a031631811115613535576040805163840000008152602081018390528151600160a060020a03331692600080516020613aec833981519152928290030190a2600091506135b2565b604051600160a060020a0384169082156108fc029083906000818181858888f1935050505015156135665760006000fd5b60408051600160a060020a03858116825260208201849052825133909116927f64f5f298ab343379f4797d6e595da2d4b4827beba0f856adaa2c02f2fa2ec6be928290030190a2600191505b5092915050565b6135c1613a7d565b815160008115156135e75760408051808201909152600080825260208201529250610ad0565b6020840190506040604051908101604052808281526020018381525092505b5050919050565b613615613a5c565b600061362083613717565b151561362c5760006000fd5b6136358361374a565b8351848452016020830181905290505b50919050565b6000613655613a7d565b5050805160208082015182519184015191019010905b50919050565b613679613a7d565b600060006136868461364b565b156136b4578360200151915061369b826137d0565b8284526020808501829052838201908601529050610ad0565b60006000fd5b5b5050919050565b6000600060006136d184613862565b15156136dd5760006000fd5b6136e684613894565b9150915060208111806136f7575080155b156137025760006000fd5b806020036101000a82510492505b5050919050565b600060008260200151600014156137315760009150613645565b8260000151905060c0815160001a101591505b50919050565b6000600060008360200151600014156137665760009250610ad0565b50508151805160001a9060808210156137825760009250610ad0565b60b882108061379d575060c0821015801561379d575060f882105b5b156137ac5760019250610ad0565b60c08210156137c15760b51982019250610ad0565b60f519820192505b5050919050565b8051600090811a60808110156137e95760019150613645565b60b88110156137fe57607e1981019150613645565b60c081101561382757600183015160b76020839003016101000a9004810160b519019150613645565b60f881101561383c5760be1981019150613645565b600183015160f76020839003016101000a9004810160f5190191505b5b5b5b5b50919050565b6000600082602001516000141561387c5760009150613645565b8260000151905060c0815160001a1091505b50919050565b600060006000600060006138a786613862565b15156138b35760006000fd5b8551805160001a9350915060808310156138d3578194506001935061390c565b60b88310156138f1576001866020015103935081600101945061390c565b60b78303905080600187602001510303935080820160010194505b5b505050915091565b6040604051908101604052806002905b60008152602001906001900390816139255790505090565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a081019190915290565b6040805160e081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c081019190915290565b60a06040519081016040528060008152602001600081526020016000815260200160008152602001600081525090565b610100604051908101604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000151581526020016000151581525090565b60a0604051908101604052806000815260200160008152602001600081526020016000815260200160006000191681525090565b606060405190810160405280613a70613a7d565b8152602001600081525090565b604080518082019091526000808252602082015290565b604080518082019091526000808252602082015290560073884516d7d74e37b06d2f16c5e139ad8d02519f4db1f6eec518b51030e5dc3653ab9d877ae22286591454f9a8d58501caa34a07c99eac2c09bc0066c065400d096caf97202169a068288f02e51ff9fcc85f98e1477f6ad9acbf6ebf25dbcd000909a30e31a36fa185673a7f68383bf8c3f784733c95114c57499b30a2da733e1d759fb22634fe2d322d688a4b46aaf185dd0a3db78ccf01a9218f00ac3df03fa165627a7a723058207838aa74ec18e24ec9f066d5bab4042b322a456dc786b99c961d5576ddc4c4a7002900000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000fbb8b91ffe0ee6b8f626f03e1378f5569432d406000000000000000000000000062d1816ea36366a714c34b9b283f4d377dc0191000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000003000000000000000000000000c8a1dab586dee8a30cb88c87b8a3614e0a391fc50000000000000000000000002be2f917397bacfb3c939f6db3bee80aa606ae31000000000000000000000000f214dde57f32f3f34492ba3148641693058d4a9e

    Constructor Arguments (ABI-encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000fbb8b91ffe0ee6b8f626f03e1378f5569432d406000000000000000000000000062d1816ea36366a714c34b9b283f4d377dc0191000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000003000000000000000000000000c8a1dab586dee8a30cb88c87b8a3614e0a391fc50000000000000000000000002be2f917397bacfb3c939f6db3bee80aa606ae31000000000000000000000000f214dde57f32f3f34492ba3148641693058d4a9e

-----Decoded View---------------
Found 9 constructor arguments :
Arg [0] : 00000000000000000000000000000000000000000000000000000000000000a0
Arg [1] : 000000000000000000000000fbb8b91ffe0ee6b8f626f03e1378f5569432d406
Arg [2] : 000000000000000000000000062d1816ea36366a714c34b9b283f4d377dc0191
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000003
Arg [6] : 000000000000000000000000c8a1dab586dee8a30cb88c87b8a3614e0a391fc5
Arg [7] : 0000000000000000000000002be2f917397bacfb3c939f6db3bee80aa606ae31
Arg [8] : 000000000000000000000000f214dde57f32f3f34492ba3148641693058d4a9e


   Swarm Source:
bzzr://7838aa74ec18e24ec9f066d5bab4042b322a456dc786b99c961d5576ddc4c4a7

 

 Latest 25 blocks (From a total of 65 blocks with 330.10 Ether mined) View All
Block Age txn Difficulty GasUsed Reward
4104391381 days 14 hrs ago691,658.23 TH64177265.0545338978286072 Ether
4094691383 days 19 hrs ago341,365.09 TH60226385.01204948840099784 Ether
4083987386 days 2 hrs ago231,302.03 TH12369955.024139716930331 Ether
4079082387 days 3 hrs ago2971,317.56 TH66191465.132804716407489112 Ether
4073285388 days 9 hrs ago721,341.75 TH41650825.106620726043738178 Ether
4069874389 days 3 hrs ago1451,316.47 TH66780645.092509218440519831 Ether
4060673391 days 2 hrs ago881,314.32 TH34204555.25509206820049892 Ether
4060259391 days 5 hrs ago1331,323.19 TH46718915.117869176748436064 Ether
4060157391 days 5 hrs ago651,330.28 TH22381785.03758291843139584 Ether
4058060391 days 16 hrs ago951,298.03 TH65085885.073151246759551348 Ether
4057978391 days 16 hrs ago631,284.94 TH67462925.048271897977027676 Ether
4054481392 days 11 hrs ago241,329.40 TH6629515.01760408170049892 Ether
4052408392 days 21 hrs ago281,281.13 TH16267775.0213288075 Ether
4046509394 days 4 hrs ago361,267.53 TH66032175.014466449405351364 Ether
4046275394 days 5 hrs ago371,275.09 TH66655365.037147269879946185 Ether
4042785394 days 23 hrs ago491,229.53 TH22513285.198144511750144185 Ether
4039773395 days 15 hrs ago1061,241.19 TH66689875.096003310974539923 Ether
4039039395 days 19 hrs ago461,199.38 TH57337085.061194333374228234 Ether
4038479395 days 22 hrs ago61,188.03 TH4424055.166206040599820992 Ether
4031701397 days 10 hrs ago581,221.59 TH44896385.07622286682 Ether
4028817398 days 1 hr ago21,269.98 TH420005.00063 Ether
4024202399 days 1 hr ago1331,201.19 TH61325485.08966347258 Ether
4021060399 days 18 hrs ago571,160.36 TH38674255.0129779645604986 Ether
4018500400 days 8 hrs ago321,216.91 TH65341705.14297840656 Ether
4017019400 days 16 hrs ago531,208.75 TH42348115.076701142165558 Ether
 Latest 25 uncles (From a total of 29 uncles with 73.13 Ether mined) View All
Block Age UncleNumber Difficulty GasUsed Reward
4125707376 days 8 hrs ago41257021,604.86 TH66862691.875 Ether
4116834378 days 12 hrs ago41168301,605.36 TH65816292.5 Ether
4116298378 days 15 hrs ago41162941,606.86 TH66084742.5 Ether
4091981384 days 9 hrs ago40919761,321.43 TH15098991.875 Ether
4063161390 days 13 hrs ago40631571,309.67 TH66833882.5 Ether
4061322390 days 23 hrs ago40613161,304.53 TH12753861.25 Ether
4049431393 days 13 hrs ago40494271,250.11 TH65559992.5 Ether
4045272394 days 11 hrs ago40452681,274.69 TH33183392.5 Ether
4037773396 days 2 hrs ago40377671,192.93 TH43675701.25 Ether
4033638397 days 15 mins ago40336331,207.58 TH66024611.875 Ether
4031983397 days 9 hrs ago40319781,224.69 TH30967441.875 Ether
4031896397 days 9 hrs ago40318901,221.46 TH31597221.25 Ether
4027308398 days 9 hrs ago40273041,220.38 TH28211472.5 Ether
4023577399 days 5 hrs ago40235721,201.01 TH66914221.875 Ether
4021876399 days 14 hrs ago40218741,173.15 TH58637393.75 Ether
4020625399 days 20 hrs ago40206221,212.06 TH64060703.125 Ether
4014137401 days 7 hrs ago40141321,208.27 TH65520301.875 Ether
4012611401 days 15 hrs ago40126081,156.04 TH66588953.125 Ether
4009025402 days 10 hrs ago40090221,221.44 TH66347643.125 Ether
4002516403 days 20 hrs ago40025131,191.77 TH23340833.125 Ether
3999087404 days 14 hrs ago39990811,078.26 TH61690661.25 Ether
3992187405 days 22 hrs ago39921841,040.34 TH66775213.125 Ether
3991528406 days 1 hr ago39915251,021.46 TH66194383.125 Ether
3988960406 days 13 hrs ago39889561,066.42 TH66498592.5 Ether
3984042407 days 13 hrs ago39840401,068.23 TH66610333.75 Ether
Make sure to use the "downvote" button for any spammy posts, and the "upvote" for interesting conversations.