ETH Price: $2,129.43 (+3.14%)

Transaction Decoder

Block:
6399926 at Sep-26-2018 12:33:34 AM +UTC
Transaction Fee:
0.00685758128 ETH $14.60
Gas Used:
758,582 Gas / 9.04 Gwei

Emitted Events:

103 LivepeerToken.Transfer( from=MerkleMine, to=[Receiver] MultiMerkleMine, value=357295353344847003 )
104 LivepeerToken.Transfer( from=MerkleMine, to=0x3B6374efF72490d99C7c54f060B084C781a0ffb0, value=2084400812772245255 )
105 MerkleMine.Generate( _recipient=0x3B6374efF72490d99C7c54f060B084C781a0ffb0, _caller=[Receiver] MultiMerkleMine, _recipientTokenAmount=2084400812772245255, _callerTokenAmount=357295353344847003, _block=6399926 )
106 LivepeerToken.Transfer( from=MerkleMine, to=[Receiver] MultiMerkleMine, value=357295353344847003 )
107 LivepeerToken.Transfer( from=MerkleMine, to=0x3b638C34332A8aB737990cDc9d896806042FD032, value=2084400812772245255 )
108 MerkleMine.Generate( _recipient=0x3b638C34332A8aB737990cDc9d896806042FD032, _caller=[Receiver] MultiMerkleMine, _recipientTokenAmount=2084400812772245255, _callerTokenAmount=357295353344847003, _block=6399926 )
109 LivepeerToken.Transfer( from=MerkleMine, to=[Receiver] MultiMerkleMine, value=357295353344847003 )
110 LivepeerToken.Transfer( from=MerkleMine, to=0x3B63B3bf0f90FD298e5e556C2097a33b5De8a067, value=2084400812772245255 )
111 MerkleMine.Generate( _recipient=0x3B63B3bf0f90FD298e5e556C2097a33b5De8a067, _caller=[Receiver] MultiMerkleMine, _recipientTokenAmount=2084400812772245255, _callerTokenAmount=357295353344847003, _block=6399926 )
112 LivepeerToken.Transfer( from=MerkleMine, to=[Receiver] MultiMerkleMine, value=357295353344847003 )
113 LivepeerToken.Transfer( from=MerkleMine, to=0x3B63cF7b0C05D4D626702015102a2489A19d9Ca3, value=2084400812772245255 )
114 MerkleMine.Generate( _recipient=0x3B63cF7b0C05D4D626702015102a2489A19d9Ca3, _caller=[Receiver] MultiMerkleMine, _recipientTokenAmount=2084400812772245255, _callerTokenAmount=357295353344847003, _block=6399926 )
115 LivepeerToken.Transfer( from=MerkleMine, to=[Receiver] MultiMerkleMine, value=357295353344847003 )
116 LivepeerToken.Transfer( from=MerkleMine, to=0x3b63DD076184Ae837bFC8b80C244C7f964e1a9b9, value=2084400812772245255 )
117 MerkleMine.Generate( _recipient=0x3b63DD076184Ae837bFC8b80C244C7f964e1a9b9, _caller=[Receiver] MultiMerkleMine, _recipientTokenAmount=2084400812772245255, _callerTokenAmount=357295353344847003, _block=6399926 )
118 LivepeerToken.Transfer( from=[Receiver] MultiMerkleMine, to=[Sender] 0x4830116608c1f6aa444149d9cb32a5abf5f1c72a, value=1786476766724235015 )

Account State Difference:

  Address   Before After State Difference Code
0x48301166...bF5f1c72a
0.267915116523210608 Eth
Nonce: 5688
0.261057535243210608 Eth
Nonce: 5689
0.00685758128
(Nanopool)
8,124.296833443439183749 Eth8,124.303691024719183749 Eth0.00685758128
0x58b6A8A3...e733aB239
0x8e306b00...766cC15c8
(Livepeer: Merkle Mine)

Execution Trace

MultiMerkleMine.multiGenerate( _merkleMineContract=0x8e306b005773bee6bA6A6e8972Bc79D766cC15c8, _recipients=[0x3B6374efF72490d99C7c54f060B084C781a0ffb0, 0x3b638C34332A8aB737990cDc9d896806042FD032, 0x3B63B3bf0f90FD298e5e556C2097a33b5De8a067, 0x3B63cF7b0C05D4D626702015102a2489A19d9Ca3, 0x3b63DD076184Ae837bFC8b80C244C7f964e1a9b9], _merkleProofs=0x00000000000000000000000000000000000000000000000000000000000002C0B47028439DF94124A09D1009732155CB94E306A53305065A7F0B8F4642AA5335505B9E983126BB790964FC354860E44FCD05D207A0D064BA9FA3C2B0B7F7052BC11F7E1C66811C36E7BE377388562A6AD375B1BE930983219B108900E9190555DDA9FB579A4E5E1C502B2046818445EB993D27BFC114F340F75C5C36D7AA8BBD6352D91C2C96C1E4F5881FDA00BAF5AF0C22DDCB00350F8F6E266CA4759DE584878CB387F5978342498DE3F9AE703E7C4387DE0A821E94574D465B1BF758B999C9951FD49E38779F604CD1AAF392E328357A08CA5C6085337EB5B7ADF44AF58371B854D2BF9E31B1EF88F5A47C8D741DF1D27912389B767FAD6CADF65067BAE6B6C1D5BD583B0080978BD84013EF29D489E6CB40C14ECEBC8ECCB306895C390F385EBFE9D279E1AB055441BFBA2D5638E23DEAE3CB2481A6EB083FC422F2AD150A5804D25B83A60CA73B19399226C6C22CDF6A8C0F14DFA59E5C0A17A6E4FBBBEB8C56CE45C4B49F1DDEDCBD9CC222BC5B396353413D2495407EE7C14CDCCC9C36CF26A6E552373A0951DFEA8CB5F78496B8C05BC2BA893CD49A585D54168D583CCF190318996DFCDAD086A523EB84973EE880BF270F05787A2C10A3CF609D5077C8C8988A91E4EF5AF85ED3F54126D4BC8299541C698F63C56C7AFE900AEE88925761081D23A5BF567596EA50EEE4822D8F9F6234F2D92F50A548FBF24CBB3A5733B7690227C94E3780B05AB4CC16027E5F5C15B2F304C86FE7668C2CC88C4946325B2D95526F40211F79B088369F2C22B44975413790EC990DE87D939A97C709A8F3F5B413E2D7187DEDEF2CE22DC5DDF0C86E42913DF72261BF1246958497B44EF0309B36AB364CCF72EAE1F219DB188ACBC7821CDD57D053CA5E37DFA1FC7460F55592404A5BD804DD4060FBBAF11A6BDC0557C70C812EC5CD9AA8007ED51E74A86B2F0ACEAA39987CE1EE5E1150DC99DB6336CCA1BF9A005C776D0E3FC300000000000000000000000000000000000000000000000000000000000002C07D73EB1F588755E3191A30722435C2F4C66EA556363CBF4BB8405D29C322229E787FA3C41189CDFCB36F542DF5328418F5A374784262192A913DBD0B07BD779E6BABF95E1684FD6922DE097EDD8C808BB1B21B31C816DCC31DC312779F564EB8D0C26163E90A3FBC0F2F90FEF7F3B85A981FC4C29E7F5065A0B3380DAC2BF04F6352D91C2C96C1E4F5881FDA00BAF5AF0C22DDCB00350F8F6E266CA4759DE584878CB387F5978342498DE3F9AE703E7C4387DE0A821E94574D465B1BF758B999C9951FD49E38779F604CD1AAF392E328357A08CA5C6085337EB5B7ADF44AF58371B854D2BF9E31B1EF88F5A47C8D741DF1D27912389B767FAD6CADF65067BAE6B6C1D5BD583B0080978BD84013EF29D489E6CB40C14ECEBC8ECCB306895C390F385EBFE9D279E1AB055441BFBA2D5638E23DEAE3CB2481A6EB083FC422F2AD150A5804D25B83A60CA73B19399226C6C22CDF6A8C0F14DFA59E5C0A17A6E4FBBBEB8C56CE45C4B49F1DDEDCBD9CC222BC5B396353413D2495407EE7C14CDCCC9C36CF26A6E552373A0951DFEA8CB5F78496B8C05BC2BA893CD49A585D54168D583CCF190318996DFCDAD086A523EB84973EE880BF270F05787A2C10A3CF609D5077C8C8988A91E4EF5AF85ED3F54126D4BC8299541C698F63C56C7AFE900AEE88925761081D23A5BF567596EA50EEE4822D8F9F6234F2D92F50A548FBF24CBB3A5733B7690227C94E3780B05AB4CC16027E5F5C15B2F304C86FE7668C2CC88C4946325B2D95526F40211F79B088369F2C22B44975413790EC990DE87D939A97C709A8F3F5B413E2D7187DEDEF2CE22DC5DDF0C86E42913DF72261BF1246958497B44EF0309B36AB364CCF72EAE1F219DB188ACBC7821CDD57D053CA5E37DFA1FC7460F55592404A5BD804DD4060FBBAF11A6BDC0557C70C812EC5CD9AA8007ED51E74A86B2F0ACEAA39987CE1EE5E1150DC99DB6336CCA1BF9A005C776D0E3FC300000000000000000000000000000000000000000000000000000000000002C08FA733725CE993BFBAFE64CF0B7DEEF59197CE51E223555D41B458B312ACCBEC5103D18B24DEC0DC3D90E0929A1DBA85AE41F8CE3D7C84135D6F37ECC81BA74415B3DE5D7B14B0989A4112911F1ACD8F19A1970B726126016B5676C99BE5DC39DD078715E7746C0BF870D5B4487E5CB05C3B623B174F2FA8C36864EAF917247801AC31BAFD600B0C10E92B625927890AE22A120542A0C1D0DD21EA02A7250C558D3FC421AEDA2A64929D6D4367D9386FD80129FE913E64E3886055CEA199BDA425890299CADB39AA20CC808CDD473201B4006238381B4EBDA918E04AE5ABD15C96D9CF9D36A39DFF971C88888B38D5BFC44D85980B1E4555C13F2A82DFF56FCA47BF237E597FC3E07A0E15EF791DE946090DB75E20A2FE514C32D6A177B18E9F385EBFE9D279E1AB055441BFBA2D5638E23DEAE3CB2481A6EB083FC422F2AD150A5804D25B83A60CA73B19399226C6C22CDF6A8C0F14DFA59E5C0A17A6E4FBBBEB8C56CE45C4B49F1DDEDCBD9CC222BC5B396353413D2495407EE7C14CDCCC9C36CF26A6E552373A0951DFEA8CB5F78496B8C05BC2BA893CD49A585D54168D583CCF190318996DFCDAD086A523EB84973EE880BF270F05787A2C10A3CF609D5077C8C8988A91E4EF5AF85ED3F54126D4BC8299541C698F63C56C7AFE900AEE88925761081D23A5BF567596EA50EEE4822D8F9F6234F2D92F50A548FBF24CBB3A5733B7690227C94E3780B05AB4CC16027E5F5C15B2F304C86FE7668C2CC88C4946325B2D95526F40211F79B088369F2C22B44975413790EC990DE87D939A97C709A8F3F5B413E2D7187DEDEF2CE22DC5DDF0C86E42913DF72261BF1246958497B44EF0309B36AB364CCF72EAE1F219DB188ACBC7821CDD57D053CA5E37DFA1FC7460F55592404A5BD804DD4060FBBAF11A6BDC0557C70C812EC5CD9AA8007ED51E74A86B2F0ACEAA39987CE1EE5E1150DC99DB6336CCA1BF9A005C776D0E3FC300000000000000000000000000000000000000000000000000000000000002C08B4AC23C9151E615E6981C4EC5663CA4C3D5232A13BE3EA7497A1BB504D6823B2C3524C7D6FC8B9D955BA4F3A766F5AF59BF94A7DE3DE7BEB73247BD850F040611EF2C6206DFB3FEBE6F2D715BC985676661992A2353D24ACA09D561EF1DE8A8DD078715E7746C0BF870D5B4487E5CB05C3B623B174F2FA8C36864EAF917247801AC31BAFD600B0C10E92B625927890AE22A120542A0C1D0DD21EA02A7250C558D3FC421AEDA2A64929D6D4367D9386FD80129FE913E64E3886055CEA199BDA425890299CADB39AA20CC808CDD473201B4006238381B4EBDA918E04AE5ABD15C96D9CF9D36A39DFF971C88888B38D5BFC44D85980B1E4555C13F2A82DFF56FCA47BF237E597FC3E07A0E15EF791DE946090DB75E20A2FE514C32D6A177B18E9F385EBFE9D279E1AB055441BFBA2D5638E23DEAE3CB2481A6EB083FC422F2AD150A5804D25B83A60CA73B19399226C6C22CDF6A8C0F14DFA59E5C0A17A6E4FBBBEB8C56CE45C4B49F1DDEDCBD9CC222BC5B396353413D2495407EE7C14CDCCC9C36CF26A6E552373A0951DFEA8CB5F78496B8C05BC2BA893CD49A585D54168D583CCF190318996DFCDAD086A523EB84973EE880BF270F05787A2C10A3CF609D5077C8C8988A91E4EF5AF85ED3F54126D4BC8299541C698F63C56C7AFE900AEE88925761081D23A5BF567596EA50EEE4822D8F9F6234F2D92F50A548FBF24CBB3A5733B7690227C94E3780B05AB4CC16027E5F5C15B2F304C86FE7668C2CC88C4946325B2D95526F40211F79B088369F2C22B44975413790EC990DE87D939A97C709A8F3F5B413E2D7187DEDEF2CE22DC5DDF0C86E42913DF72261BF1246958497B44EF0309B36AB364CCF72EAE1F219DB188ACBC7821CDD57D053CA5E37DFA1FC7460F55592404A5BD804DD4060FBBAF11A6BDC0557C70C812EC5CD9AA8007ED51E74A86B2F0ACEAA39987CE1EE5E1150DC99DB6336CCA1BF9A005C776D0E3FC300000000000000000000000000000000000000000000000000000000000002C065545DDA88FA0B5423E92201DB2FA20445BD148566430637DCBD5542384D214B7C7A1ABA0ACC0545567219224E379194A791BA76AE3075B660513FACF22393FC47A63717EF236A73B750BFC0AE71A25618DFF436C99765E298A9C10846F9C79E9305E440C1C5726BE6AFF5437428D88D91225C01DFE5CDC8A134BD44BCEF37B101AC31BAFD600B0C10E92B625927890AE22A120542A0C1D0DD21EA02A7250C558D3FC421AEDA2A64929D6D4367D9386FD80129FE913E64E3886055CEA199BDA425890299CADB39AA20CC808CDD473201B4006238381B4EBDA918E04AE5ABD15C96D9CF9D36A39DFF971C88888B38D5BFC44D85980B1E4555C13F2A82DFF56FCA47BF237E597FC3E07A0E15EF791DE946090DB75E20A2FE514C32D6A177B18E9F385EBFE9D279E1AB055441BFBA2D5638E23DEAE3CB2481A6EB083FC422F2AD150A5804D25B83A60CA73B19399226C6C22CDF6A8C0F14DFA59E5C0A17A6E4FBBBEB8C56CE45C4B49F1DDEDCBD9CC222BC5B396353413D2495407EE7C14CDCCC9C36CF26A6E552373A0951DFEA8CB5F78496B8C05BC2BA893CD49A585D54168D583CCF190318996DFCDAD086A523EB84973EE880BF270F05787A2C10A3CF609D5077C8C8988A91E4EF5AF85ED3F54126D4BC8299541C698F63C56C7AFE900AEE88925761081D23A5BF567596EA50EEE4822D8F9F6234F2D92F50A548FBF24CBB3A5733B7690227C94E3780B05AB4CC16027E5F5C15B2F304C86FE7668C2CC88C4946325B2D95526F40211F79B088369F2C22B44975413790EC990DE87D939A97C709A8F3F5B413E2D7187DEDEF2CE22DC5DDF0C86E42913DF72261BF1246958497B44EF0309B36AB364CCF72EAE1F219DB188ACBC7821CDD57D053CA5E37DFA1FC7460F55592404A5BD804DD4060FBBAF11A6BDC0557C70C812EC5CD9AA8007ED51E74A86B2F0ACEAA39987CE1EE5E1150DC99DB6336CCA1BF9A005C776D0E3FC3 )
  • MerkleMine.CALL( )
  • MerkleMine.CALL( )
  • LivepeerToken.balanceOf( _owner=0xBfd0fb15e6C04b396EA12f5BB9Ba803E29B282Be ) => ( balance=0 )
  • MerkleMine.generated( 0x3B6374efF72490d99C7c54f060B084C781a0ffb0 ) => ( False )
  • MerkleMine.generate( _recipient=0x3B6374efF72490d99C7c54f060B084C781a0ffb0, _merkleProof=0xB47028439DF94124A09D1009732155CB94E306A53305065A7F0B8F4642AA5335505B9E983126BB790964FC354860E44FCD05D207A0D064BA9FA3C2B0B7F7052BC11F7E1C66811C36E7BE377388562A6AD375B1BE930983219B108900E9190555DDA9FB579A4E5E1C502B2046818445EB993D27BFC114F340F75C5C36D7AA8BBD6352D91C2C96C1E4F5881FDA00BAF5AF0C22DDCB00350F8F6E266CA4759DE584878CB387F5978342498DE3F9AE703E7C4387DE0A821E94574D465B1BF758B999C9951FD49E38779F604CD1AAF392E328357A08CA5C6085337EB5B7ADF44AF58371B854D2BF9E31B1EF88F5A47C8D741DF1D27912389B767FAD6CADF65067BAE6B6C1D5BD583B0080978BD84013EF29D489E6CB40C14ECEBC8ECCB306895C390F385EBFE9D279E1AB055441BFBA2D5638E23DEAE3CB2481A6EB083FC422F2AD150A5804D25B83A60CA73B19399226C6C22CDF6A8C0F14DFA59E5C0A17A6E4FBBBEB8C56CE45C4B49F1DDEDCBD9CC222BC5B396353413D2495407EE7C14CDCCC9C36CF26A6E552373A0951DFEA8CB5F78496B8C05BC2BA893CD49A585D54168D583CCF190318996DFCDAD086A523EB84973EE880BF270F05787A2C10A3CF609D5077C8C8988A91E4EF5AF85ED3F54126D4BC8299541C698F63C56C7AFE900AEE88925761081D23A5BF567596EA50EEE4822D8F9F6234F2D92F50A548FBF24CBB3A5733B7690227C94E3780B05AB4CC16027E5F5C15B2F304C86FE7668C2CC88C4946325B2D95526F40211F79B088369F2C22B44975413790EC990DE87D939A97C709A8F3F5B413E2D7187DEDEF2CE22DC5DDF0C86E42913DF72261BF1246958497B44EF0309B36AB364CCF72EAE1F219DB188ACBC7821CDD57D053CA5E37DFA1FC7460F55592404A5BD804DD4060FBBAF11A6BDC0557C70C812EC5CD9AA8007ED51E74A86B2F0ACEAA39987CE1EE5E1150DC99DB6336CCA1BF9A005C776D0E3FC3 )
    • MerkleProof.verifyProof( _proof=0xB47028439DF94124A09D1009732155CB94E306A53305065A7F0B8F4642AA5335505B9E983126BB790964FC354860E44FCD05D207A0D064BA9FA3C2B0B7F7052BC11F7E1C66811C36E7BE377388562A6AD375B1BE930983219B108900E9190555DDA9FB579A4E5E1C502B2046818445EB993D27BFC114F340F75C5C36D7AA8BBD6352D91C2C96C1E4F5881FDA00BAF5AF0C22DDCB00350F8F6E266CA4759DE584878CB387F5978342498DE3F9AE703E7C4387DE0A821E94574D465B1BF758B999C9951FD49E38779F604CD1AAF392E328357A08CA5C6085337EB5B7ADF44AF58371B854D2BF9E31B1EF88F5A47C8D741DF1D27912389B767FAD6CADF65067BAE6B6C1D5BD583B0080978BD84013EF29D489E6CB40C14ECEBC8ECCB306895C390F385EBFE9D279E1AB055441BFBA2D5638E23DEAE3CB2481A6EB083FC422F2AD150A5804D25B83A60CA73B19399226C6C22CDF6A8C0F14DFA59E5C0A17A6E4FBBBEB8C56CE45C4B49F1DDEDCBD9CC222BC5B396353413D2495407EE7C14CDCCC9C36CF26A6E552373A0951DFEA8CB5F78496B8C05BC2BA893CD49A585D54168D583CCF190318996DFCDAD086A523EB84973EE880BF270F05787A2C10A3CF609D5077C8C8988A91E4EF5AF85ED3F54126D4BC8299541C698F63C56C7AFE900AEE88925761081D23A5BF567596EA50EEE4822D8F9F6234F2D92F50A548FBF24CBB3A5733B7690227C94E3780B05AB4CC16027E5F5C15B2F304C86FE7668C2CC88C4946325B2D95526F40211F79B088369F2C22B44975413790EC990DE87D939A97C709A8F3F5B413E2D7187DEDEF2CE22DC5DDF0C86E42913DF72261BF1246958497B44EF0309B36AB364CCF72EAE1F219DB188ACBC7821CDD57D053CA5E37DFA1FC7460F55592404A5BD804DD4060FBBAF11A6BDC0557C70C812EC5CD9AA8007ED51E74A86B2F0ACEAA39987CE1EE5E1150DC99DB6336CCA1BF9A005C776D0E3FC3, _root=53F35A304A1E1E20D6648E09BB3073CCD44A5BF1638A01355897A71E801879F8, _leaf=E2B390B1FE727478F19983FDA1FB8F597CC703410024AD03C243B10805D335D3 ) => ( True )
    • LivepeerToken.transfer( _to=0xBfd0fb15e6C04b396EA12f5BB9Ba803E29B282Be, _value=357295353344847003 ) => ( True )
    • LivepeerToken.transfer( _to=0x3B6374efF72490d99C7c54f060B084C781a0ffb0, _value=2084400812772245255 ) => ( True )
    • MerkleMine.generated( 0x3b638C34332A8aB737990cDc9d896806042FD032 ) => ( False )
    • MerkleMine.generate( _recipient=0x3b638C34332A8aB737990cDc9d896806042FD032, _merkleProof=0x7D73EB1F588755E3191A30722435C2F4C66EA556363CBF4BB8405D29C322229E787FA3C41189CDFCB36F542DF5328418F5A374784262192A913DBD0B07BD779E6BABF95E1684FD6922DE097EDD8C808BB1B21B31C816DCC31DC312779F564EB8D0C26163E90A3FBC0F2F90FEF7F3B85A981FC4C29E7F5065A0B3380DAC2BF04F6352D91C2C96C1E4F5881FDA00BAF5AF0C22DDCB00350F8F6E266CA4759DE584878CB387F5978342498DE3F9AE703E7C4387DE0A821E94574D465B1BF758B999C9951FD49E38779F604CD1AAF392E328357A08CA5C6085337EB5B7ADF44AF58371B854D2BF9E31B1EF88F5A47C8D741DF1D27912389B767FAD6CADF65067BAE6B6C1D5BD583B0080978BD84013EF29D489E6CB40C14ECEBC8ECCB306895C390F385EBFE9D279E1AB055441BFBA2D5638E23DEAE3CB2481A6EB083FC422F2AD150A5804D25B83A60CA73B19399226C6C22CDF6A8C0F14DFA59E5C0A17A6E4FBBBEB8C56CE45C4B49F1DDEDCBD9CC222BC5B396353413D2495407EE7C14CDCCC9C36CF26A6E552373A0951DFEA8CB5F78496B8C05BC2BA893CD49A585D54168D583CCF190318996DFCDAD086A523EB84973EE880BF270F05787A2C10A3CF609D5077C8C8988A91E4EF5AF85ED3F54126D4BC8299541C698F63C56C7AFE900AEE88925761081D23A5BF567596EA50EEE4822D8F9F6234F2D92F50A548FBF24CBB3A5733B7690227C94E3780B05AB4CC16027E5F5C15B2F304C86FE7668C2CC88C4946325B2D95526F40211F79B088369F2C22B44975413790EC990DE87D939A97C709A8F3F5B413E2D7187DEDEF2CE22DC5DDF0C86E42913DF72261BF1246958497B44EF0309B36AB364CCF72EAE1F219DB188ACBC7821CDD57D053CA5E37DFA1FC7460F55592404A5BD804DD4060FBBAF11A6BDC0557C70C812EC5CD9AA8007ED51E74A86B2F0ACEAA39987CE1EE5E1150DC99DB6336CCA1BF9A005C776D0E3FC3 )
      • MerkleProof.verifyProof( _proof=0x7D73EB1F588755E3191A30722435C2F4C66EA556363CBF4BB8405D29C322229E787FA3C41189CDFCB36F542DF5328418F5A374784262192A913DBD0B07BD779E6BABF95E1684FD6922DE097EDD8C808BB1B21B31C816DCC31DC312779F564EB8D0C26163E90A3FBC0F2F90FEF7F3B85A981FC4C29E7F5065A0B3380DAC2BF04F6352D91C2C96C1E4F5881FDA00BAF5AF0C22DDCB00350F8F6E266CA4759DE584878CB387F5978342498DE3F9AE703E7C4387DE0A821E94574D465B1BF758B999C9951FD49E38779F604CD1AAF392E328357A08CA5C6085337EB5B7ADF44AF58371B854D2BF9E31B1EF88F5A47C8D741DF1D27912389B767FAD6CADF65067BAE6B6C1D5BD583B0080978BD84013EF29D489E6CB40C14ECEBC8ECCB306895C390F385EBFE9D279E1AB055441BFBA2D5638E23DEAE3CB2481A6EB083FC422F2AD150A5804D25B83A60CA73B19399226C6C22CDF6A8C0F14DFA59E5C0A17A6E4FBBBEB8C56CE45C4B49F1DDEDCBD9CC222BC5B396353413D2495407EE7C14CDCCC9C36CF26A6E552373A0951DFEA8CB5F78496B8C05BC2BA893CD49A585D54168D583CCF190318996DFCDAD086A523EB84973EE880BF270F05787A2C10A3CF609D5077C8C8988A91E4EF5AF85ED3F54126D4BC8299541C698F63C56C7AFE900AEE88925761081D23A5BF567596EA50EEE4822D8F9F6234F2D92F50A548FBF24CBB3A5733B7690227C94E3780B05AB4CC16027E5F5C15B2F304C86FE7668C2CC88C4946325B2D95526F40211F79B088369F2C22B44975413790EC990DE87D939A97C709A8F3F5B413E2D7187DEDEF2CE22DC5DDF0C86E42913DF72261BF1246958497B44EF0309B36AB364CCF72EAE1F219DB188ACBC7821CDD57D053CA5E37DFA1FC7460F55592404A5BD804DD4060FBBAF11A6BDC0557C70C812EC5CD9AA8007ED51E74A86B2F0ACEAA39987CE1EE5E1150DC99DB6336CCA1BF9A005C776D0E3FC3, _root=53F35A304A1E1E20D6648E09BB3073CCD44A5BF1638A01355897A71E801879F8, _leaf=A5FA0131EB655CA2293A06D34D6A00B41015AD007EA27A06B920A2D74D1102AA ) => ( True )
      • LivepeerToken.transfer( _to=0xBfd0fb15e6C04b396EA12f5BB9Ba803E29B282Be, _value=357295353344847003 ) => ( True )
      • LivepeerToken.transfer( _to=0x3b638C34332A8aB737990cDc9d896806042FD032, _value=2084400812772245255 ) => ( True )
      • MerkleMine.generated( 0x3B63B3bf0f90FD298e5e556C2097a33b5De8a067 ) => ( False )
      • MerkleMine.generate( _recipient=0x3B63B3bf0f90FD298e5e556C2097a33b5De8a067, _merkleProof=0x8FA733725CE993BFBAFE64CF0B7DEEF59197CE51E223555D41B458B312ACCBEC5103D18B24DEC0DC3D90E0929A1DBA85AE41F8CE3D7C84135D6F37ECC81BA74415B3DE5D7B14B0989A4112911F1ACD8F19A1970B726126016B5676C99BE5DC39DD078715E7746C0BF870D5B4487E5CB05C3B623B174F2FA8C36864EAF917247801AC31BAFD600B0C10E92B625927890AE22A120542A0C1D0DD21EA02A7250C558D3FC421AEDA2A64929D6D4367D9386FD80129FE913E64E3886055CEA199BDA425890299CADB39AA20CC808CDD473201B4006238381B4EBDA918E04AE5ABD15C96D9CF9D36A39DFF971C88888B38D5BFC44D85980B1E4555C13F2A82DFF56FCA47BF237E597FC3E07A0E15EF791DE946090DB75E20A2FE514C32D6A177B18E9F385EBFE9D279E1AB055441BFBA2D5638E23DEAE3CB2481A6EB083FC422F2AD150A5804D25B83A60CA73B19399226C6C22CDF6A8C0F14DFA59E5C0A17A6E4FBBBEB8C56CE45C4B49F1DDEDCBD9CC222BC5B396353413D2495407EE7C14CDCCC9C36CF26A6E552373A0951DFEA8CB5F78496B8C05BC2BA893CD49A585D54168D583CCF190318996DFCDAD086A523EB84973EE880BF270F05787A2C10A3CF609D5077C8C8988A91E4EF5AF85ED3F54126D4BC8299541C698F63C56C7AFE900AEE88925761081D23A5BF567596EA50EEE4822D8F9F6234F2D92F50A548FBF24CBB3A5733B7690227C94E3780B05AB4CC16027E5F5C15B2F304C86FE7668C2CC88C4946325B2D95526F40211F79B088369F2C22B44975413790EC990DE87D939A97C709A8F3F5B413E2D7187DEDEF2CE22DC5DDF0C86E42913DF72261BF1246958497B44EF0309B36AB364CCF72EAE1F219DB188ACBC7821CDD57D053CA5E37DFA1FC7460F55592404A5BD804DD4060FBBAF11A6BDC0557C70C812EC5CD9AA8007ED51E74A86B2F0ACEAA39987CE1EE5E1150DC99DB6336CCA1BF9A005C776D0E3FC3 )
        • MerkleProof.verifyProof( _proof=0x8FA733725CE993BFBAFE64CF0B7DEEF59197CE51E223555D41B458B312ACCBEC5103D18B24DEC0DC3D90E0929A1DBA85AE41F8CE3D7C84135D6F37ECC81BA74415B3DE5D7B14B0989A4112911F1ACD8F19A1970B726126016B5676C99BE5DC39DD078715E7746C0BF870D5B4487E5CB05C3B623B174F2FA8C36864EAF917247801AC31BAFD600B0C10E92B625927890AE22A120542A0C1D0DD21EA02A7250C558D3FC421AEDA2A64929D6D4367D9386FD80129FE913E64E3886055CEA199BDA425890299CADB39AA20CC808CDD473201B4006238381B4EBDA918E04AE5ABD15C96D9CF9D36A39DFF971C88888B38D5BFC44D85980B1E4555C13F2A82DFF56FCA47BF237E597FC3E07A0E15EF791DE946090DB75E20A2FE514C32D6A177B18E9F385EBFE9D279E1AB055441BFBA2D5638E23DEAE3CB2481A6EB083FC422F2AD150A5804D25B83A60CA73B19399226C6C22CDF6A8C0F14DFA59E5C0A17A6E4FBBBEB8C56CE45C4B49F1DDEDCBD9CC222BC5B396353413D2495407EE7C14CDCCC9C36CF26A6E552373A0951DFEA8CB5F78496B8C05BC2BA893CD49A585D54168D583CCF190318996DFCDAD086A523EB84973EE880BF270F05787A2C10A3CF609D5077C8C8988A91E4EF5AF85ED3F54126D4BC8299541C698F63C56C7AFE900AEE88925761081D23A5BF567596EA50EEE4822D8F9F6234F2D92F50A548FBF24CBB3A5733B7690227C94E3780B05AB4CC16027E5F5C15B2F304C86FE7668C2CC88C4946325B2D95526F40211F79B088369F2C22B44975413790EC990DE87D939A97C709A8F3F5B413E2D7187DEDEF2CE22DC5DDF0C86E42913DF72261BF1246958497B44EF0309B36AB364CCF72EAE1F219DB188ACBC7821CDD57D053CA5E37DFA1FC7460F55592404A5BD804DD4060FBBAF11A6BDC0557C70C812EC5CD9AA8007ED51E74A86B2F0ACEAA39987CE1EE5E1150DC99DB6336CCA1BF9A005C776D0E3FC3, _root=53F35A304A1E1E20D6648E09BB3073CCD44A5BF1638A01355897A71E801879F8, _leaf=7B401AFEF6A9C6A81F68455C121070A66D31610DD6E8E9531081C643340B4AF8 ) => ( True )
        • LivepeerToken.transfer( _to=0xBfd0fb15e6C04b396EA12f5BB9Ba803E29B282Be, _value=357295353344847003 ) => ( True )
        • LivepeerToken.transfer( _to=0x3B63B3bf0f90FD298e5e556C2097a33b5De8a067, _value=2084400812772245255 ) => ( True )
        • MerkleMine.generated( 0x3B63cF7b0C05D4D626702015102a2489A19d9Ca3 ) => ( False )
        • MerkleMine.generate( _recipient=0x3B63cF7b0C05D4D626702015102a2489A19d9Ca3, _merkleProof=0x8B4AC23C9151E615E6981C4EC5663CA4C3D5232A13BE3EA7497A1BB504D6823B2C3524C7D6FC8B9D955BA4F3A766F5AF59BF94A7DE3DE7BEB73247BD850F040611EF2C6206DFB3FEBE6F2D715BC985676661992A2353D24ACA09D561EF1DE8A8DD078715E7746C0BF870D5B4487E5CB05C3B623B174F2FA8C36864EAF917247801AC31BAFD600B0C10E92B625927890AE22A120542A0C1D0DD21EA02A7250C558D3FC421AEDA2A64929D6D4367D9386FD80129FE913E64E3886055CEA199BDA425890299CADB39AA20CC808CDD473201B4006238381B4EBDA918E04AE5ABD15C96D9CF9D36A39DFF971C88888B38D5BFC44D85980B1E4555C13F2A82DFF56FCA47BF237E597FC3E07A0E15EF791DE946090DB75E20A2FE514C32D6A177B18E9F385EBFE9D279E1AB055441BFBA2D5638E23DEAE3CB2481A6EB083FC422F2AD150A5804D25B83A60CA73B19399226C6C22CDF6A8C0F14DFA59E5C0A17A6E4FBBBEB8C56CE45C4B49F1DDEDCBD9CC222BC5B396353413D2495407EE7C14CDCCC9C36CF26A6E552373A0951DFEA8CB5F78496B8C05BC2BA893CD49A585D54168D583CCF190318996DFCDAD086A523EB84973EE880BF270F05787A2C10A3CF609D5077C8C8988A91E4EF5AF85ED3F54126D4BC8299541C698F63C56C7AFE900AEE88925761081D23A5BF567596EA50EEE4822D8F9F6234F2D92F50A548FBF24CBB3A5733B7690227C94E3780B05AB4CC16027E5F5C15B2F304C86FE7668C2CC88C4946325B2D95526F40211F79B088369F2C22B44975413790EC990DE87D939A97C709A8F3F5B413E2D7187DEDEF2CE22DC5DDF0C86E42913DF72261BF1246958497B44EF0309B36AB364CCF72EAE1F219DB188ACBC7821CDD57D053CA5E37DFA1FC7460F55592404A5BD804DD4060FBBAF11A6BDC0557C70C812EC5CD9AA8007ED51E74A86B2F0ACEAA39987CE1EE5E1150DC99DB6336CCA1BF9A005C776D0E3FC3 )
          • MerkleProof.verifyProof( _proof=0x8B4AC23C9151E615E6981C4EC5663CA4C3D5232A13BE3EA7497A1BB504D6823B2C3524C7D6FC8B9D955BA4F3A766F5AF59BF94A7DE3DE7BEB73247BD850F040611EF2C6206DFB3FEBE6F2D715BC985676661992A2353D24ACA09D561EF1DE8A8DD078715E7746C0BF870D5B4487E5CB05C3B623B174F2FA8C36864EAF917247801AC31BAFD600B0C10E92B625927890AE22A120542A0C1D0DD21EA02A7250C558D3FC421AEDA2A64929D6D4367D9386FD80129FE913E64E3886055CEA199BDA425890299CADB39AA20CC808CDD473201B4006238381B4EBDA918E04AE5ABD15C96D9CF9D36A39DFF971C88888B38D5BFC44D85980B1E4555C13F2A82DFF56FCA47BF237E597FC3E07A0E15EF791DE946090DB75E20A2FE514C32D6A177B18E9F385EBFE9D279E1AB055441BFBA2D5638E23DEAE3CB2481A6EB083FC422F2AD150A5804D25B83A60CA73B19399226C6C22CDF6A8C0F14DFA59E5C0A17A6E4FBBBEB8C56CE45C4B49F1DDEDCBD9CC222BC5B396353413D2495407EE7C14CDCCC9C36CF26A6E552373A0951DFEA8CB5F78496B8C05BC2BA893CD49A585D54168D583CCF190318996DFCDAD086A523EB84973EE880BF270F05787A2C10A3CF609D5077C8C8988A91E4EF5AF85ED3F54126D4BC8299541C698F63C56C7AFE900AEE88925761081D23A5BF567596EA50EEE4822D8F9F6234F2D92F50A548FBF24CBB3A5733B7690227C94E3780B05AB4CC16027E5F5C15B2F304C86FE7668C2CC88C4946325B2D95526F40211F79B088369F2C22B44975413790EC990DE87D939A97C709A8F3F5B413E2D7187DEDEF2CE22DC5DDF0C86E42913DF72261BF1246958497B44EF0309B36AB364CCF72EAE1F219DB188ACBC7821CDD57D053CA5E37DFA1FC7460F55592404A5BD804DD4060FBBAF11A6BDC0557C70C812EC5CD9AA8007ED51E74A86B2F0ACEAA39987CE1EE5E1150DC99DB6336CCA1BF9A005C776D0E3FC3, _root=53F35A304A1E1E20D6648E09BB3073CCD44A5BF1638A01355897A71E801879F8, _leaf=FA902EBD5E7FF762A69C606EB8D3345A0A5B8318893752F7B326A9B91F0B8998 ) => ( True )
          • LivepeerToken.transfer( _to=0xBfd0fb15e6C04b396EA12f5BB9Ba803E29B282Be, _value=357295353344847003 ) => ( True )
          • LivepeerToken.transfer( _to=0x3B63cF7b0C05D4D626702015102a2489A19d9Ca3, _value=2084400812772245255 ) => ( True )
          • MerkleMine.generated( 0x3b63DD076184Ae837bFC8b80C244C7f964e1a9b9 ) => ( False )
          • MerkleMine.generate( _recipient=0x3b63DD076184Ae837bFC8b80C244C7f964e1a9b9, _merkleProof=0x65545DDA88FA0B5423E92201DB2FA20445BD148566430637DCBD5542384D214B7C7A1ABA0ACC0545567219224E379194A791BA76AE3075B660513FACF22393FC47A63717EF236A73B750BFC0AE71A25618DFF436C99765E298A9C10846F9C79E9305E440C1C5726BE6AFF5437428D88D91225C01DFE5CDC8A134BD44BCEF37B101AC31BAFD600B0C10E92B625927890AE22A120542A0C1D0DD21EA02A7250C558D3FC421AEDA2A64929D6D4367D9386FD80129FE913E64E3886055CEA199BDA425890299CADB39AA20CC808CDD473201B4006238381B4EBDA918E04AE5ABD15C96D9CF9D36A39DFF971C88888B38D5BFC44D85980B1E4555C13F2A82DFF56FCA47BF237E597FC3E07A0E15EF791DE946090DB75E20A2FE514C32D6A177B18E9F385EBFE9D279E1AB055441BFBA2D5638E23DEAE3CB2481A6EB083FC422F2AD150A5804D25B83A60CA73B19399226C6C22CDF6A8C0F14DFA59E5C0A17A6E4FBBBEB8C56CE45C4B49F1DDEDCBD9CC222BC5B396353413D2495407EE7C14CDCCC9C36CF26A6E552373A0951DFEA8CB5F78496B8C05BC2BA893CD49A585D54168D583CCF190318996DFCDAD086A523EB84973EE880BF270F05787A2C10A3CF609D5077C8C8988A91E4EF5AF85ED3F54126D4BC8299541C698F63C56C7AFE900AEE88925761081D23A5BF567596EA50EEE4822D8F9F6234F2D92F50A548FBF24CBB3A5733B7690227C94E3780B05AB4CC16027E5F5C15B2F304C86FE7668C2CC88C4946325B2D95526F40211F79B088369F2C22B44975413790EC990DE87D939A97C709A8F3F5B413E2D7187DEDEF2CE22DC5DDF0C86E42913DF72261BF1246958497B44EF0309B36AB364CCF72EAE1F219DB188ACBC7821CDD57D053CA5E37DFA1FC7460F55592404A5BD804DD4060FBBAF11A6BDC0557C70C812EC5CD9AA8007ED51E74A86B2F0ACEAA39987CE1EE5E1150DC99DB6336CCA1BF9A005C776D0E3FC3 )
            • MerkleProof.verifyProof( _proof=0x65545DDA88FA0B5423E92201DB2FA20445BD148566430637DCBD5542384D214B7C7A1ABA0ACC0545567219224E379194A791BA76AE3075B660513FACF22393FC47A63717EF236A73B750BFC0AE71A25618DFF436C99765E298A9C10846F9C79E9305E440C1C5726BE6AFF5437428D88D91225C01DFE5CDC8A134BD44BCEF37B101AC31BAFD600B0C10E92B625927890AE22A120542A0C1D0DD21EA02A7250C558D3FC421AEDA2A64929D6D4367D9386FD80129FE913E64E3886055CEA199BDA425890299CADB39AA20CC808CDD473201B4006238381B4EBDA918E04AE5ABD15C96D9CF9D36A39DFF971C88888B38D5BFC44D85980B1E4555C13F2A82DFF56FCA47BF237E597FC3E07A0E15EF791DE946090DB75E20A2FE514C32D6A177B18E9F385EBFE9D279E1AB055441BFBA2D5638E23DEAE3CB2481A6EB083FC422F2AD150A5804D25B83A60CA73B19399226C6C22CDF6A8C0F14DFA59E5C0A17A6E4FBBBEB8C56CE45C4B49F1DDEDCBD9CC222BC5B396353413D2495407EE7C14CDCCC9C36CF26A6E552373A0951DFEA8CB5F78496B8C05BC2BA893CD49A585D54168D583CCF190318996DFCDAD086A523EB84973EE880BF270F05787A2C10A3CF609D5077C8C8988A91E4EF5AF85ED3F54126D4BC8299541C698F63C56C7AFE900AEE88925761081D23A5BF567596EA50EEE4822D8F9F6234F2D92F50A548FBF24CBB3A5733B7690227C94E3780B05AB4CC16027E5F5C15B2F304C86FE7668C2CC88C4946325B2D95526F40211F79B088369F2C22B44975413790EC990DE87D939A97C709A8F3F5B413E2D7187DEDEF2CE22DC5DDF0C86E42913DF72261BF1246958497B44EF0309B36AB364CCF72EAE1F219DB188ACBC7821CDD57D053CA5E37DFA1FC7460F55592404A5BD804DD4060FBBAF11A6BDC0557C70C812EC5CD9AA8007ED51E74A86B2F0ACEAA39987CE1EE5E1150DC99DB6336CCA1BF9A005C776D0E3FC3, _root=53F35A304A1E1E20D6648E09BB3073CCD44A5BF1638A01355897A71E801879F8, _leaf=856056F29941CB6E188F76C61A166C708BBFD2CF64FC91C70261072E76E4B2D5 ) => ( True )
            • LivepeerToken.transfer( _to=0xBfd0fb15e6C04b396EA12f5BB9Ba803E29B282Be, _value=357295353344847003 ) => ( True )
            • LivepeerToken.transfer( _to=0x3b63DD076184Ae837bFC8b80C244C7f964e1a9b9, _value=2084400812772245255 ) => ( True )
            • LivepeerToken.balanceOf( _owner=0xBfd0fb15e6C04b396EA12f5BB9Ba803E29B282Be ) => ( balance=1786476766724235015 )
            • LivepeerToken.transfer( _to=0x4830116608C1F6aA444149D9cB32A5AbF5f1c72a, _value=1786476766724235015 ) => ( True )
              File 1 of 4: MultiMerkleMine
              pragma solidity 0.4.24;
              
              /**
               * @title ERC20Basic
               * @dev Simpler version of ERC20 interface
               * @dev see https://github.com/ethereum/EIPs/issues/179
               */
              contract ERC20Basic {
                  uint256 public totalSupply;
                  function balanceOf(address who) public view returns (uint256);
                  function transfer(address to, uint256 value) public returns (bool);
                  event Transfer(address indexed from, address indexed to, uint256 value);
              }
              
              /**
               * @title ERC20 interface
               * @dev see https://github.com/ethereum/EIPs/issues/20
               */
              contract ERC20 is ERC20Basic {
                  function allowance(address owner, address spender) public view returns (uint256);
                  function transferFrom(address from, address to, uint256 value) public returns (bool);
                  function approve(address spender, uint256 value) public returns (bool);
                  event Approval(address indexed owner, address indexed spender, uint256 value);
              }
              
              /**
               * @title SafeMath
               * @dev Math operations with safety checks that throw on error
               */
              library SafeMath {
                  function mul(uint256 a, uint256 b) internal pure returns (uint256) {
                      if (a == 0) {
                          return 0;
                      }
                      uint256 c = a * b;
                      assert(c / a == b);
                      return c;
                  }
              
                  function div(uint256 a, uint256 b) internal pure returns (uint256) {
                      // assert(b > 0); // Solidity automatically throws when dividing by 0
                      uint256 c = a / b;
                      // assert(a == b * c + a % b); // There is no case in which this doesn't hold
                      return c;
                  }
              
                  function sub(uint256 a, uint256 b) internal pure returns (uint256) {
                      assert(b <= a);
                      return a - b;
                  }
              
                  function add(uint256 a, uint256 b) internal pure returns (uint256) {
                      uint256 c = a + b;
                      assert(c >= a);
                      return c;
                  }
              }
              
              /*
               * @title MerkleProof
               * @dev Merkle proof verification
               * @note Based on https://github.com/ameensol/merkle-tree-solidity/blob/master/src/MerkleProof.sol
               */
              library MerkleProof {
                /*
                 * @dev Verifies a Merkle proof proving the existence of a leaf in a Merkle tree. Assumes that each pair of leaves
                 * and each pair of pre-images is sorted.
                 * @param _proof Merkle proof containing sibling hashes on the branch from the leaf to the root of the Merkle tree
                 * @param _root Merkle root
                 * @param _leaf Leaf of Merkle tree
                 */
                function verifyProof(bytes _proof, bytes32 _root, bytes32 _leaf) public pure returns (bool) {
                  // Check if proof length is a multiple of 32
                  if (_proof.length % 32 != 0) return false;
              
                  bytes32 proofElement;
                  bytes32 computedHash = _leaf;
              
                  for (uint256 i = 32; i <= _proof.length; i += 32) {
                    assembly {
                      // Load the current element of the proof
                      proofElement := mload(add(_proof, i))
                    }
              
                    if (computedHash < proofElement) {
                      // Hash(current computed hash + current element of the proof)
                      computedHash = keccak256(computedHash, proofElement);
                    } else {
                      // Hash(current element of the proof + current computed hash)
                      computedHash = keccak256(proofElement, computedHash);
                    }
                  }
              
                  // Check if the computed hash (root) is equal to the provided root
                  return computedHash == _root;
                }
              }
              
              /**
               * @title MerkleMine
               * @dev Token distribution based on providing Merkle proofs of inclusion in genesis state to generate allocation
               */
              contract MerkleMine {
                  using SafeMath for uint256;
              
                  // ERC20 token being distributed
                  ERC20 public token;
                  // Merkle root representing genesis state which encodes token recipients
                  bytes32 public genesisRoot;
                  // Total amount of tokens that can be generated
                  uint256 public totalGenesisTokens;
                  // Total number of recipients included in genesis state
                  uint256 public totalGenesisRecipients;
                  // Amount of tokens per recipient allocation. Equal to `totalGenesisTokens` / `totalGenesisRecipients`
                  uint256 public tokensPerAllocation;
                  // Minimum ETH balance threshold for recipients included in genesis state
                  uint256 public balanceThreshold;
                  // Block number of genesis - used to determine which ETH accounts are included in the genesis state
                  uint256 public genesisBlock;
                  // Start block where a third party caller (not the recipient) can generate and split the allocation with the recipient
                  // As the current block gets closer to `callerAllocationEndBlock`, the caller receives a larger precentage of the allocation
                  uint256 public callerAllocationStartBlock;
                  // From this block onwards, a third party caller (not the recipient) can generate and claim the recipient's full allocation
                  uint256 public callerAllocationEndBlock;
                  // Number of blocks in the caller allocation period as defined by `callerAllocationEndBlock` - `callerAllocationStartBlock`
                  uint256 public callerAllocationPeriod;
              
                  // Track if the generation process is started
                  bool public started;
              
                  // Track the already generated allocations for recipients
                  mapping (address => bool) public generated;
              
                  // Check that a recipient's allocation has not been generated
                  modifier notGenerated(address _recipient) {
                      require(!generated[_recipient]);
                      _;
                  }
              
                  // Check that the generation period is started
                  modifier isStarted() {
                      require(started);
                      _;
                  }
              
                  // Check that the generation period is not started
                  modifier isNotStarted() {
                      require(!started);
                      _;
                  }
              
                  event Generate(address indexed _recipient, address indexed _caller, uint256 _recipientTokenAmount, uint256 _callerTokenAmount, uint256 _block);
              
                  /**
                   * @dev MerkleMine constructor
                   * @param _token ERC20 token being distributed
                   * @param _genesisRoot Merkle root representing genesis state which encodes token recipients
                   * @param _totalGenesisTokens Total amount of tokens that can be generated
                   * @param _totalGenesisRecipients Total number of recipients included in genesis state
                   * @param _balanceThreshold Minimum ETH balance threshold for recipients included in genesis state
                   * @param _genesisBlock Block number of genesis - used to determine which ETH accounts are included in the genesis state
                   * @param _callerAllocationStartBlock Start block where a third party caller (not the recipient) can generate and split the allocation with the recipient
                   * @param _callerAllocationEndBlock From this block onwards, a third party caller (not the recipient) can generate and claim the recipient's full allocation
                   */
                  function MerkleMine(
                      address _token,
                      bytes32 _genesisRoot,
                      uint256 _totalGenesisTokens,
                      uint256 _totalGenesisRecipients,
                      uint256 _balanceThreshold,
                      uint256 _genesisBlock,
                      uint256 _callerAllocationStartBlock,
                      uint256 _callerAllocationEndBlock
                  )
                      public
                  {
                      // Address of token contract must not be null
                      require(_token != address(0));
                      // Number of recipients must be non-zero
                      require(_totalGenesisRecipients > 0);
                      // Genesis block must be at or before the current block
                      require(_genesisBlock <= block.number);
                      // Start block for caller allocation must be after current block
                      require(_callerAllocationStartBlock > block.number);
                      // End block for caller allocation must be after caller allocation start block
                      require(_callerAllocationEndBlock > _callerAllocationStartBlock);
              
                      token = ERC20(_token);
                      genesisRoot = _genesisRoot;
                      totalGenesisTokens = _totalGenesisTokens;
                      totalGenesisRecipients = _totalGenesisRecipients;
                      tokensPerAllocation = _totalGenesisTokens.div(_totalGenesisRecipients);
                      balanceThreshold = _balanceThreshold;
                      genesisBlock = _genesisBlock;
                      callerAllocationStartBlock = _callerAllocationStartBlock;
                      callerAllocationEndBlock = _callerAllocationEndBlock;
                      callerAllocationPeriod = _callerAllocationEndBlock.sub(_callerAllocationStartBlock);
                  }
              
                  /**
                   * @dev Start the generation period - first checks that this contract's balance is equal to `totalGenesisTokens`
                   * The generation period must not already be started
                   */
                  function start() external isNotStarted {
                      // Check that this contract has a sufficient balance for the generation period
                      require(token.balanceOf(this) >= totalGenesisTokens);
              
                      started = true;
                  }
              
                  /**
                   * @dev Generate a recipient's token allocation. Generation period must be started. Starting from `callerAllocationStartBlock`
                   * a third party caller (not the recipient) can invoke this function to generate the recipient's token
                   * allocation and claim a percentage of it. The percentage of the allocation claimed by the
                   * third party caller is determined by how many blocks have elapsed since `callerAllocationStartBlock`.
                   * After `callerAllocationEndBlock`, a third party caller can claim the full allocation
                   * @param _recipient Recipient of token allocation
                   * @param _merkleProof Proof of recipient's inclusion in genesis state Merkle root
                   */
                  function generate(address _recipient, bytes _merkleProof) external isStarted notGenerated(_recipient) {
                      // Check the Merkle proof
                      bytes32 leaf = keccak256(_recipient);
                      // _merkleProof must prove inclusion of _recipient in the genesis state root
                      require(MerkleProof.verifyProof(_merkleProof, genesisRoot, leaf));
              
                      generated[_recipient] = true;
              
                      address caller = msg.sender;
              
                      if (caller == _recipient) {
                          // If the caller is the recipient, transfer the full allocation to the caller/recipient
                          require(token.transfer(_recipient, tokensPerAllocation));
              
                          Generate(_recipient, _recipient, tokensPerAllocation, 0, block.number);
                      } else {
                          // If the caller is not the recipient, the token allocation generation
                          // can only take place if we are in the caller allocation period
                          require(block.number >= callerAllocationStartBlock);
              
                          uint256 callerTokenAmount = callerTokenAmountAtBlock(block.number);
                          uint256 recipientTokenAmount = tokensPerAllocation.sub(callerTokenAmount);
              
                          if (callerTokenAmount > 0) {
                              require(token.transfer(caller, callerTokenAmount));
                          }
              
                          if (recipientTokenAmount > 0) {
                              require(token.transfer(_recipient, recipientTokenAmount));
                          }
              
                          Generate(_recipient, caller, recipientTokenAmount, callerTokenAmount, block.number);
                      }
                  }
              
                  /**
                   * @dev Return the amount of tokens claimable by a third party caller when generating a recipient's token allocation at a given block
                   * @param _blockNumber Block at which to compute the amount of tokens claimable by a third party caller
                   */
                  function callerTokenAmountAtBlock(uint256 _blockNumber) public view returns (uint256) {
                      if (_blockNumber < callerAllocationStartBlock) {
                          // If the block is before the start of the caller allocation period, the third party caller can claim nothing
                          return 0;
                      } else if (_blockNumber >= callerAllocationEndBlock) {
                          // If the block is at or after the end block of the caller allocation period, the third party caller can claim everything
                          return tokensPerAllocation;
                      } else {
                          // During the caller allocation period, the third party caller can claim an increasing percentage
                          // of the recipient's allocation based on a linear curve - as more blocks pass in the caller allocation
                          // period, the amount claimable by the third party caller increases linearly
                          uint256 blocksSinceCallerAllocationStartBlock = _blockNumber.sub(callerAllocationStartBlock);
                          return tokensPerAllocation.mul(blocksSinceCallerAllocationStartBlock).div(callerAllocationPeriod);
                      }
                  }
              }
              
              /**
               * @title BytesUtil
               * @dev Utilities for extracting bytes from byte arrays
               * Functions taken from:
               * - https://github.com/ethereum/solidity-examples/blob/master/src/unsafe/Memory.sol
               * - https://github.com/ethereum/solidity-examples/blob/master/src/bytes/Bytes.sol
               */
              library BytesUtil{
                  uint256 internal constant BYTES_HEADER_SIZE = 32;
                  uint256 internal constant WORD_SIZE = 32;
                  
                  /**
                   * @dev Returns a memory pointer to the data portion of the provided bytes array.
                   * @param bts Memory byte array
                   */
                  function dataPtr(bytes memory bts) internal pure returns (uint256 addr) {
                      assembly {
                          addr := add(bts, /*BYTES_HEADER_SIZE*/ 32)
                      }
                  }
                  
                  /**
                   * @dev Copy 'len' bytes from memory address 'src', to address 'dest'.
                   * This function does not check the or destination, it only copies
                   * the bytes.
                   * @param src Memory address of source byte array
                   * @param dest Memory address of destination byte array
                   * @param len Number of bytes to copy from `src` to `dest`
                   */
                  function copy(uint256 src, uint256 dest, uint256 len) internal pure {
                      // Copy word-length chunks while possible
                      for (; len >= WORD_SIZE; len -= WORD_SIZE) {
                          assembly {
                              mstore(dest, mload(src))
                          }
                          dest += WORD_SIZE;
                          src += WORD_SIZE;
                      }
              
                      // Copy remaining bytes
                      uint256 mask = 256 ** (WORD_SIZE - len) - 1;
                      assembly {
                          let srcpart := and(mload(src), not(mask))
                          let destpart := and(mload(dest), mask)
                          mstore(dest, or(destpart, srcpart))
                      }
                  }
              
                  /**
                   * @dev Creates a 'bytes memory' variable from the memory address 'addr', with the
                   * length 'len'. The function will allocate new memory for the bytes array, and
                   * the 'len bytes starting at 'addr' will be copied into that new memory.
                   * @param addr Memory address of input byte array
                   * @param len Number of bytes to copy from input byte array
                   */
                  function toBytes(uint256 addr, uint256 len) internal pure returns (bytes memory bts) {
                      bts = new bytes(len);
                      uint256 btsptr = dataPtr(bts);
                      copy(addr, btsptr, len);
                  }
                  
                  /**
                   * @dev Copies 'len' bytes from 'bts' into a new array, starting at the provided 'startIndex'.
                   * Returns the new copy.
                   * Requires that:
                   *  - 'startIndex + len <= self.length'
                   * The length of the substring is: 'len'
                   * @param bts Memory byte array to copy from
                   * @param startIndex Index of `bts` to start copying bytes from
                   * @param len Number of bytes to copy from `bts`
                   */
                  function substr(bytes memory bts, uint256 startIndex, uint256 len) internal pure returns (bytes memory) {
                      require(startIndex + len <= bts.length);
                      if (len == 0) {
                          return;
                      }
                      uint256 addr = dataPtr(bts);
                      return toBytes(addr + startIndex, len);
                  }
              
                  /**
                   * @dev Reads a bytes32 value from a byte array by copying 32 bytes from `bts` starting at the provided `startIndex`.
                   * @param bts Memory byte array to copy from
                   * @param startIndex Index of `bts` to start copying bytes from
                   */
                  function readBytes32(bytes memory bts, uint256 startIndex) internal pure returns (bytes32 result) {
                      require(startIndex + 32 <= bts.length);
              
                      uint256 addr = dataPtr(bts);
              
                      assembly {
                          result := mload(add(addr, startIndex))
                      }
              
                      return result;
                  }
              }
              
              /**
               * @title MultiMerkleMine
               * @dev The MultiMerkleMine contract is purely a convenience wrapper around an existing MerkleMine contract deployed on the blockchain.
               */
              contract MultiMerkleMine {
              	using SafeMath for uint256;
              
              	/**
                   * @dev Generates token allocations for multiple recipients. Generation period must be started.
                   * @param _merkleMineContract Address of the deployed MerkleMine contract
                   * @param _recipients Array of recipients
                   * @param _merkleProofs Proofs for respective recipients constructed in the format: 
                   *       [proof_1_size, proof_1, proof_2_size, proof_2, ... , proof_n_size, proof_n]
                   */
              	function multiGenerate(address _merkleMineContract, address[] _recipients, bytes _merkleProofs) public {
              		MerkleMine mine = MerkleMine(_merkleMineContract);
              		ERC20 token = ERC20(mine.token());
              
              		require(
              			block.number >= mine.callerAllocationStartBlock(),
              			"caller allocation period has not started"
              		);
              		
              		uint256 initialBalance = token.balanceOf(this);
              		bytes[] memory proofs = new bytes[](_recipients.length);
              
              		// Counter to keep track of position in `_merkleProofs` byte array
              		uint256 i = 0;
              		// Counter to keep track of index of each extracted Merkle proof
              		uint256 j = 0;
              
              		// Extract proofs
              		while(i < _merkleProofs.length){
              			uint256 proofSize = uint256(BytesUtil.readBytes32(_merkleProofs, i));
              
              			require(
              				proofSize % 32 == 0,
              				"proof size must be a multiple of 32"
              			);
              
              			proofs[j] = BytesUtil.substr(_merkleProofs, i + 32, proofSize);
              
              			i = i + 32 + proofSize;
              			j++;
              		}
              
              		require(
              			_recipients.length == j,
              			"number of recipients != number of proofs"
              		);
              
              		for (uint256 k = 0; k < _recipients.length; k++) {
              			// If recipient's token allocation has not been generated, generate the token allocation
              			// Else, continue to the next recipient
              			if (!mine.generated(_recipients[k])) {
              				mine.generate(_recipients[k], proofs[k]);
              			}
              		}
              
              		uint256 newBalanceSinceAllocation = token.balanceOf(this);
              		uint256 callerTokensGenerated = newBalanceSinceAllocation.sub(initialBalance);
              
              		// Transfer caller's portion of tokens generated by this function call 
              		if (callerTokensGenerated > 0) {
              			require(token.transfer(msg.sender, callerTokensGenerated));
              		}
              	}
              }

              File 2 of 4: MerkleMine
              pragma solidity 0.4.18;
              
              /**
               * @title ERC20Basic
               * @dev Simpler version of ERC20 interface
               * @dev see https://github.com/ethereum/EIPs/issues/179
               */
              contract ERC20Basic {
                  uint256 public totalSupply;
                  function balanceOf(address who) public view returns (uint256);
                  function transfer(address to, uint256 value) public returns (bool);
                  event Transfer(address indexed from, address indexed to, uint256 value);
              }
              
              /**
               * @title ERC20 interface
               * @dev see https://github.com/ethereum/EIPs/issues/20
               */
              contract ERC20 is ERC20Basic {
                  function allowance(address owner, address spender) public view returns (uint256);
                  function transferFrom(address from, address to, uint256 value) public returns (bool);
                  function approve(address spender, uint256 value) public returns (bool);
                  event Approval(address indexed owner, address indexed spender, uint256 value);
              }
              
              /**
               * @title SafeMath
               * @dev Math operations with safety checks that throw on error
               */
              library SafeMath {
                  function mul(uint256 a, uint256 b) internal pure returns (uint256) {
                      if (a == 0) {
                          return 0;
                      }
                      uint256 c = a * b;
                      assert(c / a == b);
                      return c;
                  }
              
                  function div(uint256 a, uint256 b) internal pure returns (uint256) {
                      // assert(b > 0); // Solidity automatically throws when dividing by 0
                      uint256 c = a / b;
                      // assert(a == b * c + a % b); // There is no case in which this doesn't hold
                      return c;
                  }
              
                  function sub(uint256 a, uint256 b) internal pure returns (uint256) {
                      assert(b <= a);
                      return a - b;
                  }
              
                  function add(uint256 a, uint256 b) internal pure returns (uint256) {
                      uint256 c = a + b;
                      assert(c >= a);
                      return c;
                  }
              }
              
              /*
               * @title MerkleProof
               * @dev Merkle proof verification
               * @note Based on https://github.com/ameensol/merkle-tree-solidity/blob/master/src/MerkleProof.sol
               */
              library MerkleProof {
                /*
                 * @dev Verifies a Merkle proof proving the existence of a leaf in a Merkle tree. Assumes that each pair of leaves
                 * and each pair of pre-images is sorted.
                 * @param _proof Merkle proof containing sibling hashes on the branch from the leaf to the root of the Merkle tree
                 * @param _root Merkle root
                 * @param _leaf Leaf of Merkle tree
                 */
                function verifyProof(bytes _proof, bytes32 _root, bytes32 _leaf) public pure returns (bool) {
                  // Check if proof length is a multiple of 32
                  if (_proof.length % 32 != 0) return false;
              
                  bytes32 proofElement;
                  bytes32 computedHash = _leaf;
              
                  for (uint256 i = 32; i <= _proof.length; i += 32) {
                    assembly {
                      // Load the current element of the proof
                      proofElement := mload(add(_proof, i))
                    }
              
                    if (computedHash < proofElement) {
                      // Hash(current computed hash + current element of the proof)
                      computedHash = keccak256(computedHash, proofElement);
                    } else {
                      // Hash(current element of the proof + current computed hash)
                      computedHash = keccak256(proofElement, computedHash);
                    }
                  }
              
                  // Check if the computed hash (root) is equal to the provided root
                  return computedHash == _root;
                }
              }
              
              /**
               * @title MerkleMine
               * @dev Token distribution based on providing Merkle proofs of inclusion in genesis state to generate allocation
               */
              contract MerkleMine {
                  using SafeMath for uint256;
              
                  // ERC20 token being distributed
                  ERC20 public token;
                  // Merkle root representing genesis state which encodes token recipients
                  bytes32 public genesisRoot;
                  // Total amount of tokens that can be generated
                  uint256 public totalGenesisTokens;
                  // Total number of recipients included in genesis state
                  uint256 public totalGenesisRecipients;
                  // Amount of tokens per recipient allocation. Equal to `totalGenesisTokens` / `totalGenesisRecipients`
                  uint256 public tokensPerAllocation;
                  // Minimum ETH balance threshold for recipients included in genesis state
                  uint256 public balanceThreshold;
                  // Block number of genesis - used to determine which ETH accounts are included in the genesis state
                  uint256 public genesisBlock;
                  // Start block where a third party caller (not the recipient) can generate and split the allocation with the recipient
                  // As the current block gets closer to `callerAllocationEndBlock`, the caller receives a larger precentage of the allocation
                  uint256 public callerAllocationStartBlock;
                  // From this block onwards, a third party caller (not the recipient) can generate and claim the recipient's full allocation
                  uint256 public callerAllocationEndBlock;
                  // Number of blocks in the caller allocation period as defined by `callerAllocationEndBlock` - `callerAllocationStartBlock`
                  uint256 public callerAllocationPeriod;
              
                  // Track if the generation process is started
                  bool public started;
              
                  // Track the already generated allocations for recipients
                  mapping (address => bool) public generated;
              
                  // Check that a recipient's allocation has not been generated
                  modifier notGenerated(address _recipient) {
                      require(!generated[_recipient]);
                      _;
                  }
              
                  // Check that the generation period is started
                  modifier isStarted() {
                      require(started);
                      _;
                  }
              
                  // Check that the generation period is not started
                  modifier isNotStarted() {
                      require(!started);
                      _;
                  }
              
                  event Generate(address indexed _recipient, address indexed _caller, uint256 _recipientTokenAmount, uint256 _callerTokenAmount, uint256 _block);
              
                  /**
                   * @dev MerkleMine constructor
                   * @param _token ERC20 token being distributed
                   * @param _genesisRoot Merkle root representing genesis state which encodes token recipients
                   * @param _totalGenesisTokens Total amount of tokens that can be generated
                   * @param _totalGenesisRecipients Total number of recipients included in genesis state
                   * @param _balanceThreshold Minimum ETH balance threshold for recipients included in genesis state
                   * @param _genesisBlock Block number of genesis - used to determine which ETH accounts are included in the genesis state
                   * @param _callerAllocationStartBlock Start block where a third party caller (not the recipient) can generate and split the allocation with the recipient
                   * @param _callerAllocationEndBlock From this block onwards, a third party caller (not the recipient) can generate and claim the recipient's full allocation
                   */
                  function MerkleMine(
                      address _token,
                      bytes32 _genesisRoot,
                      uint256 _totalGenesisTokens,
                      uint256 _totalGenesisRecipients,
                      uint256 _balanceThreshold,
                      uint256 _genesisBlock,
                      uint256 _callerAllocationStartBlock,
                      uint256 _callerAllocationEndBlock
                  )
                      public
                  {
                      // Address of token contract must not be null
                      require(_token != address(0));
                      // Number of recipients must be non-zero
                      require(_totalGenesisRecipients > 0);
                      // Genesis block must be at or before the current block
                      require(_genesisBlock <= block.number);
                      // Start block for caller allocation must be after current block
                      require(_callerAllocationStartBlock > block.number);
                      // End block for caller allocation must be after caller allocation start block
                      require(_callerAllocationEndBlock > _callerAllocationStartBlock);
              
                      token = ERC20(_token);
                      genesisRoot = _genesisRoot;
                      totalGenesisTokens = _totalGenesisTokens;
                      totalGenesisRecipients = _totalGenesisRecipients;
                      tokensPerAllocation = _totalGenesisTokens.div(_totalGenesisRecipients);
                      balanceThreshold = _balanceThreshold;
                      genesisBlock = _genesisBlock;
                      callerAllocationStartBlock = _callerAllocationStartBlock;
                      callerAllocationEndBlock = _callerAllocationEndBlock;
                      callerAllocationPeriod = _callerAllocationEndBlock.sub(_callerAllocationStartBlock);
                  }
              
                  /**
                   * @dev Start the generation period - first checks that this contract's balance is equal to `totalGenesisTokens`
                   * The generation period must not already be started
                   */
                  function start() external isNotStarted {
                      // Check that this contract has a sufficient balance for the generation period
                      require(token.balanceOf(this) >= totalGenesisTokens);
              
                      started = true;
                  }
              
                  /**
                   * @dev Generate a recipient's token allocation. Generation period must be started. Starting from `callerAllocationStartBlock`
                   * a third party caller (not the recipient) can invoke this function to generate the recipient's token
                   * allocation and claim a percentage of it. The percentage of the allocation claimed by the
                   * third party caller is determined by how many blocks have elapsed since `callerAllocationStartBlock`.
                   * After `callerAllocationEndBlock`, a third party caller can claim the full allocation
                   * @param _recipient Recipient of token allocation
                   * @param _merkleProof Proof of recipient's inclusion in genesis state Merkle root
                   */
                  function generate(address _recipient, bytes _merkleProof) external isStarted notGenerated(_recipient) {
                      // Check the Merkle proof
                      bytes32 leaf = keccak256(_recipient);
                      // _merkleProof must prove inclusion of _recipient in the genesis state root
                      require(MerkleProof.verifyProof(_merkleProof, genesisRoot, leaf));
              
                      generated[_recipient] = true;
              
                      address caller = msg.sender;
              
                      if (caller == _recipient) {
                          // If the caller is the recipient, transfer the full allocation to the caller/recipient
                          require(token.transfer(_recipient, tokensPerAllocation));
              
                          Generate(_recipient, _recipient, tokensPerAllocation, 0, block.number);
                      } else {
                          // If the caller is not the recipient, the token allocation generation
                          // can only take place if we are in the caller allocation period
                          require(block.number >= callerAllocationStartBlock);
              
                          uint256 callerTokenAmount = callerTokenAmountAtBlock(block.number);
                          uint256 recipientTokenAmount = tokensPerAllocation.sub(callerTokenAmount);
              
                          if (callerTokenAmount > 0) {
                              require(token.transfer(caller, callerTokenAmount));
                          }
              
                          if (recipientTokenAmount > 0) {
                              require(token.transfer(_recipient, recipientTokenAmount));
                          }
              
                          Generate(_recipient, caller, recipientTokenAmount, callerTokenAmount, block.number);
                      }
                  }
              
                  /**
                   * @dev Return the amount of tokens claimable by a third party caller when generating a recipient's token allocation at a given block
                   * @param _blockNumber Block at which to compute the amount of tokens claimable by a third party caller
                   */
                  function callerTokenAmountAtBlock(uint256 _blockNumber) public view returns (uint256) {
                      if (_blockNumber < callerAllocationStartBlock) {
                          // If the block is before the start of the caller allocation period, the third party caller can claim nothing
                          return 0;
                      } else if (_blockNumber >= callerAllocationEndBlock) {
                          // If the block is at or after the end block of the caller allocation period, the third party caller can claim everything
                          return tokensPerAllocation;
                      } else {
                          // During the caller allocation period, the third party caller can claim an increasing percentage
                          // of the recipient's allocation based on a linear curve - as more blocks pass in the caller allocation
                          // period, the amount claimable by the third party caller increases linearly
                          uint256 blocksSinceCallerAllocationStartBlock = _blockNumber.sub(callerAllocationStartBlock);
                          return tokensPerAllocation.mul(blocksSinceCallerAllocationStartBlock).div(callerAllocationPeriod);
                      }
                  }
              }

              File 3 of 4: LivepeerToken
              /**
               *Submitted for verification at Etherscan.io on 2018-04-30
              */
              
              pragma solidity 0.4.18;
              
              /**
               * @title ERC20Basic
               * @dev Simpler version of ERC20 interface
               * @dev see https://github.com/ethereum/EIPs/issues/179
               */
              contract ERC20Basic {
                uint256 public totalSupply;
                function balanceOf(address who) public view returns (uint256);
                function transfer(address to, uint256 value) public returns (bool);
                event Transfer(address indexed from, address indexed to, uint256 value);
              }
              
              /**
               * @title ERC20 interface
               * @dev see https://github.com/ethereum/EIPs/issues/20
               */
              contract ERC20 is ERC20Basic {
                function allowance(address owner, address spender) public view returns (uint256);
                function transferFrom(address from, address to, uint256 value) public returns (bool);
                function approve(address spender, uint256 value) public returns (bool);
                event Approval(address indexed owner, address indexed spender, uint256 value);
              }
              
              /**
               * @title Ownable
               * @dev The Ownable contract has an owner address, and provides basic authorization control
               * functions, this simplifies the implementation of "user permissions".
               */
              contract Ownable {
                address public owner;
              
              
                event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
              
              
                /**
                 * @dev The Ownable constructor sets the original `owner` of the contract to the sender
                 * account.
                 */
                function Ownable() public {
                  owner = msg.sender;
                }
              
              
                /**
                 * @dev Throws if called by any account other than the owner.
                 */
                modifier onlyOwner() {
                  require(msg.sender == owner);
                  _;
                }
              
              
                /**
                 * @dev Allows the current owner to transfer control of the contract to a newOwner.
                 * @param newOwner The address to transfer ownership to.
                 */
                function transferOwnership(address newOwner) public onlyOwner {
                  require(newOwner != address(0));
                  OwnershipTransferred(owner, newOwner);
                  owner = newOwner;
                }
              
              }
              
              /**
               * @title SafeMath
               * @dev Math operations with safety checks that throw on error
               */
              library SafeMath {
                function mul(uint256 a, uint256 b) internal pure returns (uint256) {
                  if (a == 0) {
                    return 0;
                  }
                  uint256 c = a * b;
                  assert(c / a == b);
                  return c;
                }
              
                function div(uint256 a, uint256 b) internal pure returns (uint256) {
                  // assert(b > 0); // Solidity automatically throws when dividing by 0
                  uint256 c = a / b;
                  // assert(a == b * c + a % b); // There is no case in which this doesn't hold
                  return c;
                }
              
                function sub(uint256 a, uint256 b) internal pure returns (uint256) {
                  assert(b <= a);
                  return a - b;
                }
              
                function add(uint256 a, uint256 b) internal pure returns (uint256) {
                  uint256 c = a + b;
                  assert(c >= a);
                  return c;
                }
              }
              
              /**
               * @title Basic token
               * @dev Basic version of StandardToken, with no allowances.
               */
              contract BasicToken is ERC20Basic {
                using SafeMath for uint256;
              
                mapping(address => uint256) balances;
              
                /**
                * @dev transfer token for a specified address
                * @param _to The address to transfer to.
                * @param _value The amount to be transferred.
                */
                function transfer(address _to, uint256 _value) public returns (bool) {
                  require(_to != address(0));
                  require(_value <= balances[msg.sender]);
              
                  // SafeMath.sub will throw if there is not enough balance.
                  balances[msg.sender] = balances[msg.sender].sub(_value);
                  balances[_to] = balances[_to].add(_value);
                  Transfer(msg.sender, _to, _value);
                  return true;
                }
              
                /**
                * @dev Gets the balance of the specified address.
                * @param _owner The address to query the the balance of.
                * @return An uint256 representing the amount owned by the passed address.
                */
                function balanceOf(address _owner) public view returns (uint256 balance) {
                  return balances[_owner];
                }
              
              }
              
              /**
               * @title Standard ERC20 token
               *
               * @dev Implementation of the basic standard token.
               * @dev https://github.com/ethereum/EIPs/issues/20
               * @dev Based on code by FirstBlood: https://github.com/Firstbloodio/token/blob/master/smart_contract/FirstBloodToken.sol
               */
              contract StandardToken is ERC20, BasicToken {
              
                mapping (address => mapping (address => uint256)) internal allowed;
              
              
                /**
                 * @dev Transfer tokens from one address to another
                 * @param _from address The address which you want to send tokens from
                 * @param _to address The address which you want to transfer to
                 * @param _value uint256 the amount of tokens to be transferred
                 */
                function transferFrom(address _from, address _to, uint256 _value) public returns (bool) {
                  require(_to != address(0));
                  require(_value <= balances[_from]);
                  require(_value <= allowed[_from][msg.sender]);
              
                  balances[_from] = balances[_from].sub(_value);
                  balances[_to] = balances[_to].add(_value);
                  allowed[_from][msg.sender] = allowed[_from][msg.sender].sub(_value);
                  Transfer(_from, _to, _value);
                  return true;
                }
              
                /**
                 * @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender.
                 *
                 * Beware that changing an allowance with this method brings the risk that someone may use both the old
                 * and the new allowance by unfortunate transaction ordering. One possible solution to mitigate this
                 * race condition is to first reduce the spender's allowance to 0 and set the desired value afterwards:
                 * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
                 * @param _spender The address which will spend the funds.
                 * @param _value The amount of tokens to be spent.
                 */
                function approve(address _spender, uint256 _value) public returns (bool) {
                  allowed[msg.sender][_spender] = _value;
                  Approval(msg.sender, _spender, _value);
                  return true;
                }
              
                /**
                 * @dev Function to check the amount of tokens that an owner allowed to a spender.
                 * @param _owner address The address which owns the funds.
                 * @param _spender address The address which will spend the funds.
                 * @return A uint256 specifying the amount of tokens still available for the spender.
                 */
                function allowance(address _owner, address _spender) public view returns (uint256) {
                  return allowed[_owner][_spender];
                }
              
                /**
                 * @dev Increase the amount of tokens that an owner allowed to a spender.
                 *
                 * approve should be called when allowed[_spender] == 0. To increment
                 * allowed value is better to use this function to avoid 2 calls (and wait until
                 * the first transaction is mined)
                 * From MonolithDAO Token.sol
                 * @param _spender The address which will spend the funds.
                 * @param _addedValue The amount of tokens to increase the allowance by.
                 */
                function increaseApproval(address _spender, uint _addedValue) public returns (bool) {
                  allowed[msg.sender][_spender] = allowed[msg.sender][_spender].add(_addedValue);
                  Approval(msg.sender, _spender, allowed[msg.sender][_spender]);
                  return true;
                }
              
                /**
                 * @dev Decrease the amount of tokens that an owner allowed to a spender.
                 *
                 * approve should be called when allowed[_spender] == 0. To decrement
                 * allowed value is better to use this function to avoid 2 calls (and wait until
                 * the first transaction is mined)
                 * From MonolithDAO Token.sol
                 * @param _spender The address which will spend the funds.
                 * @param _subtractedValue The amount of tokens to decrease the allowance by.
                 */
                function decreaseApproval(address _spender, uint _subtractedValue) public returns (bool) {
                  uint oldValue = allowed[msg.sender][_spender];
                  if (_subtractedValue > oldValue) {
                    allowed[msg.sender][_spender] = 0;
                  } else {
                    allowed[msg.sender][_spender] = oldValue.sub(_subtractedValue);
                  }
                  Approval(msg.sender, _spender, allowed[msg.sender][_spender]);
                  return true;
                }
              
              }
              
              /**
               * @title Mintable token
               * @dev Simple ERC20 Token example, with mintable token creation
               * @dev Issue: * https://github.com/OpenZeppelin/zeppelin-solidity/issues/120
               * Based on code by TokenMarketNet: https://github.com/TokenMarketNet/ico/blob/master/contracts/MintableToken.sol
               */
              
              contract MintableToken is StandardToken, Ownable {
                event Mint(address indexed to, uint256 amount);
                event MintFinished();
              
                bool public mintingFinished = false;
              
              
                modifier canMint() {
                  require(!mintingFinished);
                  _;
                }
              
                /**
                 * @dev Function to mint tokens
                 * @param _to The address that will receive the minted tokens.
                 * @param _amount The amount of tokens to mint.
                 * @return A boolean that indicates if the operation was successful.
                 */
                function mint(address _to, uint256 _amount) onlyOwner canMint public returns (bool) {
                  totalSupply = totalSupply.add(_amount);
                  balances[_to] = balances[_to].add(_amount);
                  Mint(_to, _amount);
                  Transfer(address(0), _to, _amount);
                  return true;
                }
              
                /**
                 * @dev Function to stop minting new tokens.
                 * @return True if the operation was successful.
                 */
                function finishMinting() onlyOwner canMint public returns (bool) {
                  mintingFinished = true;
                  MintFinished();
                  return true;
                }
              }
              
              contract VariableSupplyToken is MintableToken {
                  event Burn(address indexed burner, uint256 value);
              
                  /*
                   * @dev Burns a specific amount of the sender's tokens
                   * @param _value The amount of tokens to be burned
                   */
                  function burn(uint256 _amount) public {
                      // Must not burn more than the sender owns
                      require(_amount <= balances[msg.sender]);
              
                      address burner = msg.sender;
                      balances[burner] = balances[burner].sub(_amount);
                      totalSupply = totalSupply.sub(_amount);
              
                      Burn(burner, _amount);
                  }
              }
              
              contract ILivepeerToken is ERC20, Ownable {
                  function mint(address _to, uint256 _amount) public returns (bool);
                  function burn(uint256 _amount) public;
              }
              
              contract LivepeerToken is ILivepeerToken, VariableSupplyToken {
                  string public name = "Livepeer Token";
                  uint8 public decimals = 18;
                  string public symbol = "LPT";
                  string public version = "0.1";
              }

              File 4 of 4: MerkleProof
              pragma solidity 0.4.18;
              
              /*
               * @title MerkleProof
               * @dev Merkle proof verification
               * @note Based on https://github.com/ameensol/merkle-tree-solidity/blob/master/src/MerkleProof.sol
               */
              library MerkleProof {
                /*
                 * @dev Verifies a Merkle proof proving the existence of a leaf in a Merkle tree. Assumes that each pair of leaves
                 * and each pair of pre-images is sorted.
                 * @param _proof Merkle proof containing sibling hashes on the branch from the leaf to the root of the Merkle tree
                 * @param _root Merkle root
                 * @param _leaf Leaf of Merkle tree
                 */
                function verifyProof(bytes _proof, bytes32 _root, bytes32 _leaf) public pure returns (bool) {
                  // Check if proof length is a multiple of 32
                  if (_proof.length % 32 != 0) return false;
              
                  bytes32 proofElement;
                  bytes32 computedHash = _leaf;
              
                  for (uint256 i = 32; i <= _proof.length; i += 32) {
                    assembly {
                      // Load the current element of the proof
                      proofElement := mload(add(_proof, i))
                    }
              
                    if (computedHash < proofElement) {
                      // Hash(current computed hash + current element of the proof)
                      computedHash = keccak256(computedHash, proofElement);
                    } else {
                      // Hash(current element of the proof + current computed hash)
                      computedHash = keccak256(proofElement, computedHash);
                    }
                  }
              
                  // Check if the computed hash (root) is equal to the provided root
                  return computedHash == _root;
                }
              }