ETH Price: $2,532.21 (+0.55%)

Transaction Decoder

Block:
12111246 at Mar-25-2021 11:59:57 PM +UTC
Transaction Fee:
0.176188582 ETH $446.15
Gas Used:
1,061,377 Gas / 166 Gwei

Emitted Events:

177 Aggregator.ChainlinkRequested( id=848DD4FE2DD61126FA27D2F0EC68A328EC211F1B1D23D4F85CAAB9928D7919C7 )
178 LinkToken.0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef( 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef, 0x00000000000000000000000025fa978ea1a7dc9bdc33a2959b9053eae57169b5, 0x000000000000000000000000180486507e7e20490fc0228efd182989e0bd61cc, 0000000000000000000000000000000000000000000000000a688906bd8b0000 )
179 LinkToken.Transfer( from=[Receiver] Aggregator, to=Oracle, value=750000000000000000, data=0x4042994600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000A2EF5FD990294D1FBD928D2CB351B7570000000000000000000000000000000000000000000000000000000025FA978EA1A7DC9BDC33A2959B9053EAE57169B56A9705B4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010AEC000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000 )
180 Oracle.OracleRequest( specId=A2EF5FD990294D1FBD928D2CB351B75700000000000000000000000000000000, requester=[Receiver] Aggregator, requestId=848DD4FE2DD61126FA27D2F0EC68A328EC211F1B1D23D4F85CAAB9928D7919C7, payment=750000000000000000, callbackAddr=[Receiver] Aggregator, callbackFunctionId=System.Byte[], cancelExpiration=1616717097, dataVersion=1, data=0x )
181 Aggregator.ChainlinkRequested( id=008B459587E4505978ADE4268350DC2A0AB9263F7D9369D4A8CB6CEA2C58CD8B )
182 LinkToken.0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef( 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef, 0x00000000000000000000000025fa978ea1a7dc9bdc33a2959b9053eae57169b5, 0x000000000000000000000000d9a815095266584cbcc8357a1ac1d7007ff2e847, 0000000000000000000000000000000000000000000000000a688906bd8b0000 )
183 LinkToken.Transfer( from=[Receiver] Aggregator, to=Oracle, value=750000000000000000, data=0x404299460000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000046BA54D90A6445A2A7478EC4CC95F8C50000000000000000000000000000000000000000000000000000000025FA978EA1A7DC9BDC33A2959B9053EAE57169B56A9705B4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010AED000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000 )
184 Oracle.OracleRequest( specId=46BA54D90A6445A2A7478EC4CC95F8C500000000000000000000000000000000, requester=[Receiver] Aggregator, requestId=008B459587E4505978ADE4268350DC2A0AB9263F7D9369D4A8CB6CEA2C58CD8B, payment=750000000000000000, callbackAddr=[Receiver] Aggregator, callbackFunctionId=System.Byte[], cancelExpiration=1616717097, dataVersion=1, data=0x )
185 Aggregator.ChainlinkRequested( id=7EB3FEB80C987626926184AFCAB487B97C48DAA0CCD11062EA1AEC014FD3CECC )
186 LinkToken.0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef( 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef, 0x00000000000000000000000025fa978ea1a7dc9bdc33a2959b9053eae57169b5, 0x000000000000000000000000049bd8c3adc3fe7d3fc2a44541d955a537c2a484, 0000000000000000000000000000000000000000000000000a688906bd8b0000 )
187 LinkToken.Transfer( from=[Receiver] Aggregator, to=Oracle, value=750000000000000000, data=0x4042994600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000660E3AA4F520460BAADAFE565B8C57400000000000000000000000000000000000000000000000000000000025FA978EA1A7DC9BDC33A2959B9053EAE57169B56A9705B4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010AEE000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000 )
188 Oracle.OracleRequest( specId=660E3AA4F520460BAADAFE565B8C574000000000000000000000000000000000, requester=[Receiver] Aggregator, requestId=7EB3FEB80C987626926184AFCAB487B97C48DAA0CCD11062EA1AEC014FD3CECC, payment=750000000000000000, callbackAddr=[Receiver] Aggregator, callbackFunctionId=System.Byte[], cancelExpiration=1616717097, dataVersion=1, data=0x )
189 Aggregator.ChainlinkRequested( id=BBD9D1209504BFB8BFE5A348E23442B9D7BACD261AA95BEC7CF950133496FDE9 )
190 LinkToken.0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef( 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef, 0x00000000000000000000000025fa978ea1a7dc9bdc33a2959b9053eae57169b5, 0x00000000000000000000000026d5a7517017b76d99ce6db6db172ffeced09f54, 0000000000000000000000000000000000000000000000000a688906bd8b0000 )
191 LinkToken.Transfer( from=[Receiver] Aggregator, to=Oracle, value=750000000000000000, data=0x4042994600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000511A0B92908B42639B1C547A17E62F2E0000000000000000000000000000000000000000000000000000000025FA978EA1A7DC9BDC33A2959B9053EAE57169B56A9705B4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010AEF000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000 )
192 Oracle.OracleRequest( specId=511A0B92908B42639B1C547A17E62F2E00000000000000000000000000000000, requester=[Receiver] Aggregator, requestId=BBD9D1209504BFB8BFE5A348E23442B9D7BACD261AA95BEC7CF950133496FDE9, payment=750000000000000000, callbackAddr=[Receiver] Aggregator, callbackFunctionId=System.Byte[], cancelExpiration=1616717097, dataVersion=1, data=0x )
193 Aggregator.ChainlinkRequested( id=D71A0F12ED4B28229A8BF34908E6E279F09C7D1F5DFA2C609D94F8EB44AC0039 )
194 LinkToken.0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef( 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef, 0x00000000000000000000000025fa978ea1a7dc9bdc33a2959b9053eae57169b5, 0x0000000000000000000000004565300c576431e5228e8aa32642d5739cf9247d, 0000000000000000000000000000000000000000000000000a688906bd8b0000 )
195 LinkToken.Transfer( from=[Receiver] Aggregator, to=0x4565300c576431e5228e8aa32642d5739cf9247d, value=750000000000000000, data=0x4042994600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000D385652A23574164ABB72053B6AE489C0000000000000000000000000000000000000000000000000000000025FA978EA1A7DC9BDC33A2959B9053EAE57169B56A9705B4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010AF0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000 )
196 0x4565300c576431e5228e8aa32642d5739cf9247d.0xd8d7ecc4800d25fa53ce0372f13a416d98907a7ef3d8d3bdd79cf4fe75529c65( 0xd8d7ecc4800d25fa53ce0372f13a416d98907a7ef3d8d3bdd79cf4fe75529c65, 0xd385652a23574164abb72053b6ae489c00000000000000000000000000000000, 00000000000000000000000025fa978ea1a7dc9bdc33a2959b9053eae57169b5, d71a0f12ed4b28229a8bf34908e6e279f09c7d1f5dfa2c609d94f8eb44ac0039, 0000000000000000000000000000000000000000000000000a688906bd8b0000, 00000000000000000000000025fa978ea1a7dc9bdc33a2959b9053eae57169b5, 6a9705b400000000000000000000000000000000000000000000000000000000, 00000000000000000000000000000000000000000000000000000000605d2529, 0000000000000000000000000000000000000000000000000000000000000001, 0000000000000000000000000000000000000000000000000000000000000100, 0000000000000000000000000000000000000000000000000000000000000000 )
197 Aggregator.ChainlinkRequested( id=8F1ED2E76916E196EE92993A27D728BD34AEF3E54A37DE692CE84CD80FF8A058 )
198 LinkToken.0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef( 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef, 0x00000000000000000000000025fa978ea1a7dc9bdc33a2959b9053eae57169b5, 0x000000000000000000000000b92ec7d213a28e21b426d79ede3c9bbcf6917c09, 0000000000000000000000000000000000000000000000000a688906bd8b0000 )
199 LinkToken.Transfer( from=[Receiver] Aggregator, to=Oracle, value=750000000000000000, data=0x4042994600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C6AEFDC316F545EAB179DE1A29D25F320000000000000000000000000000000000000000000000000000000025FA978EA1A7DC9BDC33A2959B9053EAE57169B56A9705B4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010AF1000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000 )
200 Oracle.OracleRequest( specId=C6AEFDC316F545EAB179DE1A29D25F3200000000000000000000000000000000, requester=[Receiver] Aggregator, requestId=8F1ED2E76916E196EE92993A27D728BD34AEF3E54A37DE692CE84CD80FF8A058, payment=750000000000000000, callbackAddr=[Receiver] Aggregator, callbackFunctionId=System.Byte[], cancelExpiration=1616717097, dataVersion=1, data=0x )
201 Aggregator.ChainlinkRequested( id=B03FB3E4C3CA896110029A96226D1E3A05BE6B49E0BF7C3D3CF627F91BA287EA )
202 LinkToken.0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef( 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef, 0x00000000000000000000000025fa978ea1a7dc9bdc33a2959b9053eae57169b5, 0x0000000000000000000000002ed7e9fcd3c0568dc6167f0b8aee06a02cd9ebd8, 0000000000000000000000000000000000000000000000000a688906bd8b0000 )
203 LinkToken.Transfer( from=[Receiver] Aggregator, to=Oracle, value=750000000000000000, data=0x40429946000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009258D955ACE44DA79F5C2BA2877E3AD90000000000000000000000000000000000000000000000000000000025FA978EA1A7DC9BDC33A2959B9053EAE57169B56A9705B4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010AF2000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000 )
204 Oracle.OracleRequest( specId=9258D955ACE44DA79F5C2BA2877E3AD900000000000000000000000000000000, requester=[Receiver] Aggregator, requestId=B03FB3E4C3CA896110029A96226D1E3A05BE6B49E0BF7C3D3CF627F91BA287EA, payment=750000000000000000, callbackAddr=[Receiver] Aggregator, callbackFunctionId=System.Byte[], cancelExpiration=1616717097, dataVersion=1, data=0x )
205 Aggregator.ChainlinkRequested( id=981DAA6BE81A6966745346D4817C30D1F9611CDB2CB2A414B8B3AD502CFE4D25 )
206 LinkToken.0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef( 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef, 0x00000000000000000000000025fa978ea1a7dc9bdc33a2959b9053eae57169b5, 0x00000000000000000000000072f3dff4cd17816604dd2df6c2741e739484ca62, 0000000000000000000000000000000000000000000000000a688906bd8b0000 )
207 LinkToken.Transfer( from=[Receiver] Aggregator, to=Oracle, value=750000000000000000, data=0x4042994600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000EC8CE80540874FDAAAA067503017051D0000000000000000000000000000000000000000000000000000000025FA978EA1A7DC9BDC33A2959B9053EAE57169B56A9705B4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010AF3000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000 )
208 Oracle.OracleRequest( specId=EC8CE80540874FDAAAA067503017051D00000000000000000000000000000000, requester=[Receiver] Aggregator, requestId=981DAA6BE81A6966745346D4817C30D1F9611CDB2CB2A414B8B3AD502CFE4D25, payment=750000000000000000, callbackAddr=[Receiver] Aggregator, callbackFunctionId=System.Byte[], cancelExpiration=1616717097, dataVersion=1, data=0x )
209 Aggregator.ChainlinkRequested( id=5CDCBBA15D2F6BEF89582ACCAAFD56C67D6A8B12748DA3A5127F060D7A74E853 )
210 LinkToken.0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef( 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef, 0x00000000000000000000000025fa978ea1a7dc9bdc33a2959b9053eae57169b5, 0x00000000000000000000000029e3b3c76e7ae0d681bf1a6bcee1c0e7d17dbaa9, 0000000000000000000000000000000000000000000000000a688906bd8b0000 )
211 LinkToken.Transfer( from=[Receiver] Aggregator, to=0x29e3b3c76e7ae0d681bf1a6bcee1c0e7d17dbaa9, value=750000000000000000, data=0x4042994600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000AFCC2D75F0494906BB644D3EB5CFEE9C0000000000000000000000000000000000000000000000000000000025FA978EA1A7DC9BDC33A2959B9053EAE57169B56A9705B4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010AF4000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000 )
212 0x29e3b3c76e7ae0d681bf1a6bcee1c0e7d17dbaa9.0xd8d7ecc4800d25fa53ce0372f13a416d98907a7ef3d8d3bdd79cf4fe75529c65( 0xd8d7ecc4800d25fa53ce0372f13a416d98907a7ef3d8d3bdd79cf4fe75529c65, 0xafcc2d75f0494906bb644d3eb5cfee9c00000000000000000000000000000000, 00000000000000000000000025fa978ea1a7dc9bdc33a2959b9053eae57169b5, 5cdcbba15d2f6bef89582accaafd56c67d6a8b12748da3a5127f060d7a74e853, 0000000000000000000000000000000000000000000000000a688906bd8b0000, 00000000000000000000000025fa978ea1a7dc9bdc33a2959b9053eae57169b5, 6a9705b400000000000000000000000000000000000000000000000000000000, 00000000000000000000000000000000000000000000000000000000605d2529, 0000000000000000000000000000000000000000000000000000000000000001, 0000000000000000000000000000000000000000000000000000000000000100, 0000000000000000000000000000000000000000000000000000000000000000 )
213 Aggregator.NewRound( roundId=7611, startedBy=[Sender] 0xd8aa8f3be2fb0c790d3579dcf68a04701c1e33db )

Account State Difference:

  Address   Before After State Difference Code
0x049Bd8C3...537c2A484
0x18048650...9E0BD61Cc
0x25Fa978e...aE57169B5
(Chainlink: EUR / USD Aggregator)
0x26d5A751...EcEd09f54
0x29e3b3c7...7d17DBAA9
0x2Ed7E9fC...02CD9ebd8
0x4565300C...39CF9247d
0x51491077...4EcF986CA
0x72f3dFf4...39484CA62
(F2Pool Old)
7,020.055653126159360481 Eth7,020.231841708159360481 Eth0.176188582
0xB92ec7D2...cf6917c09
0xd8Aa8F3b...01C1e33DB
495.39080545940528543 Eth
Nonce: 277637
495.21461687740528543 Eth
Nonce: 277638
0.176188582
0xd9A81509...07ff2E847

Execution Trace

Aggregator.requestRateUpdate( )
  • LinkToken.transferAndCall( _to=0x180486507E7e20490FC0228efd182989E0BD61Cc, _value=750000000000000000, _data=0x4042994600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000A2EF5FD990294D1FBD928D2CB351B7570000000000000000000000000000000000000000000000000000000025FA978EA1A7DC9BDC33A2959B9053EAE57169B56A9705B4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010AEC000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000 ) => ( success=True )
    • Oracle.onTokenTransfer( _sender=0x25Fa978ea1a7dc9bDc33a2959B9053EaE57169B5, _amount=750000000000000000, _data=0x4042994600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000A2EF5FD990294D1FBD928D2CB351B7570000000000000000000000000000000000000000000000000000000025FA978EA1A7DC9BDC33A2959B9053EAE57169B56A9705B4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010AEC000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000 )
      • Oracle.oracleRequest( _sender=0x25Fa978ea1a7dc9bDc33a2959B9053EaE57169B5, _payment=750000000000000000, _specId=A2EF5FD990294D1FBD928D2CB351B75700000000000000000000000000000000, _callbackAddress=0x25Fa978ea1a7dc9bDc33a2959B9053EaE57169B5, _callbackFunctionId=System.Byte[], _nonce=68332, _dataVersion=1, _data=0x )
      • LinkToken.transferAndCall( _to=0xd9A815095266584cBcC8357a1aC1D7007ff2E847, _value=750000000000000000, _data=0x404299460000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000046BA54D90A6445A2A7478EC4CC95F8C50000000000000000000000000000000000000000000000000000000025FA978EA1A7DC9BDC33A2959B9053EAE57169B56A9705B4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010AED000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000 ) => ( success=True )
        • Oracle.onTokenTransfer( _sender=0x25Fa978ea1a7dc9bDc33a2959B9053EaE57169B5, _amount=750000000000000000, _data=0x404299460000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000046BA54D90A6445A2A7478EC4CC95F8C50000000000000000000000000000000000000000000000000000000025FA978EA1A7DC9BDC33A2959B9053EAE57169B56A9705B4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010AED000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000 )
          • Oracle.oracleRequest( _sender=0x25Fa978ea1a7dc9bDc33a2959B9053EaE57169B5, _payment=750000000000000000, _specId=46BA54D90A6445A2A7478EC4CC95F8C500000000000000000000000000000000, _callbackAddress=0x25Fa978ea1a7dc9bDc33a2959B9053EaE57169B5, _callbackFunctionId=System.Byte[], _nonce=68333, _dataVersion=1, _data=0x )
          • LinkToken.transferAndCall( _to=0x049Bd8C3adC3fE7d3Fc2a44541d955A537c2A484, _value=750000000000000000, _data=0x4042994600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000660E3AA4F520460BAADAFE565B8C57400000000000000000000000000000000000000000000000000000000025FA978EA1A7DC9BDC33A2959B9053EAE57169B56A9705B4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010AEE000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000 ) => ( success=True )
            • Oracle.onTokenTransfer( _sender=0x25Fa978ea1a7dc9bDc33a2959B9053EaE57169B5, _amount=750000000000000000, _data=0x4042994600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000660E3AA4F520460BAADAFE565B8C57400000000000000000000000000000000000000000000000000000000025FA978EA1A7DC9BDC33A2959B9053EAE57169B56A9705B4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010AEE000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000 )
              • Oracle.oracleRequest( _sender=0x25Fa978ea1a7dc9bDc33a2959B9053EaE57169B5, _payment=750000000000000000, _specId=660E3AA4F520460BAADAFE565B8C574000000000000000000000000000000000, _callbackAddress=0x25Fa978ea1a7dc9bDc33a2959B9053EaE57169B5, _callbackFunctionId=System.Byte[], _nonce=68334, _dataVersion=1, _data=0x )
              • LinkToken.transferAndCall( _to=0x26d5A7517017b76D99ce6dB6dB172ffEcEd09f54, _value=750000000000000000, _data=0x4042994600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000511A0B92908B42639B1C547A17E62F2E0000000000000000000000000000000000000000000000000000000025FA978EA1A7DC9BDC33A2959B9053EAE57169B56A9705B4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010AEF000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000 ) => ( success=True )
                • Oracle.onTokenTransfer( _sender=0x25Fa978ea1a7dc9bDc33a2959B9053EaE57169B5, _amount=750000000000000000, _data=0x4042994600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000511A0B92908B42639B1C547A17E62F2E0000000000000000000000000000000000000000000000000000000025FA978EA1A7DC9BDC33A2959B9053EAE57169B56A9705B4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010AEF000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000 )
                  • Oracle.oracleRequest( _sender=0x25Fa978ea1a7dc9bDc33a2959B9053EaE57169B5, _payment=750000000000000000, _specId=511A0B92908B42639B1C547A17E62F2E00000000000000000000000000000000, _callbackAddress=0x25Fa978ea1a7dc9bDc33a2959B9053EaE57169B5, _callbackFunctionId=System.Byte[], _nonce=68335, _dataVersion=1, _data=0x )
                  • LinkToken.transferAndCall( _to=0x4565300C576431e5228e8aA32642D5739CF9247d, _value=750000000000000000, _data=0x4042994600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000D385652A23574164ABB72053B6AE489C0000000000000000000000000000000000000000000000000000000025FA978EA1A7DC9BDC33A2959B9053EAE57169B56A9705B4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010AF0000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000 ) => ( success=True )
                    • 0x4565300c576431e5228e8aa32642d5739cf9247d.a4c0ed36( )
                      • 0x4565300c576431e5228e8aa32642d5739cf9247d.40429946( )
                      • LinkToken.transferAndCall( _to=0xB92ec7D213a28e21b426D79EDe3c9BBcf6917c09, _value=750000000000000000, _data=0x4042994600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C6AEFDC316F545EAB179DE1A29D25F320000000000000000000000000000000000000000000000000000000025FA978EA1A7DC9BDC33A2959B9053EAE57169B56A9705B4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010AF1000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000 ) => ( success=True )
                        • Oracle.onTokenTransfer( _sender=0x25Fa978ea1a7dc9bDc33a2959B9053EaE57169B5, _amount=750000000000000000, _data=0x4042994600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C6AEFDC316F545EAB179DE1A29D25F320000000000000000000000000000000000000000000000000000000025FA978EA1A7DC9BDC33A2959B9053EAE57169B56A9705B4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010AF1000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000 )
                          • Oracle.oracleRequest( _sender=0x25Fa978ea1a7dc9bDc33a2959B9053EaE57169B5, _payment=750000000000000000, _specId=C6AEFDC316F545EAB179DE1A29D25F3200000000000000000000000000000000, _callbackAddress=0x25Fa978ea1a7dc9bDc33a2959B9053EaE57169B5, _callbackFunctionId=System.Byte[], _nonce=68337, _dataVersion=1, _data=0x )
                          • LinkToken.transferAndCall( _to=0x2Ed7E9fCd3c0568dC6167F0b8aEe06A02CD9ebd8, _value=750000000000000000, _data=0x40429946000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009258D955ACE44DA79F5C2BA2877E3AD90000000000000000000000000000000000000000000000000000000025FA978EA1A7DC9BDC33A2959B9053EAE57169B56A9705B4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010AF2000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000 ) => ( success=True )
                            • Oracle.onTokenTransfer( _sender=0x25Fa978ea1a7dc9bDc33a2959B9053EaE57169B5, _amount=750000000000000000, _data=0x40429946000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009258D955ACE44DA79F5C2BA2877E3AD90000000000000000000000000000000000000000000000000000000025FA978EA1A7DC9BDC33A2959B9053EAE57169B56A9705B4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010AF2000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000 )
                              • Oracle.oracleRequest( _sender=0x25Fa978ea1a7dc9bDc33a2959B9053EaE57169B5, _payment=750000000000000000, _specId=9258D955ACE44DA79F5C2BA2877E3AD900000000000000000000000000000000, _callbackAddress=0x25Fa978ea1a7dc9bDc33a2959B9053EaE57169B5, _callbackFunctionId=System.Byte[], _nonce=68338, _dataVersion=1, _data=0x )
                              • LinkToken.transferAndCall( _to=0x72f3dFf4CD17816604dd2df6C2741e739484CA62, _value=750000000000000000, _data=0x4042994600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000EC8CE80540874FDAAAA067503017051D0000000000000000000000000000000000000000000000000000000025FA978EA1A7DC9BDC33A2959B9053EAE57169B56A9705B4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010AF3000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000 ) => ( success=True )
                                • Oracle.onTokenTransfer( _sender=0x25Fa978ea1a7dc9bDc33a2959B9053EaE57169B5, _amount=750000000000000000, _data=0x4042994600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000EC8CE80540874FDAAAA067503017051D0000000000000000000000000000000000000000000000000000000025FA978EA1A7DC9BDC33A2959B9053EAE57169B56A9705B4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010AF3000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000 )
                                  • Oracle.oracleRequest( _sender=0x25Fa978ea1a7dc9bDc33a2959B9053EaE57169B5, _payment=750000000000000000, _specId=EC8CE80540874FDAAAA067503017051D00000000000000000000000000000000, _callbackAddress=0x25Fa978ea1a7dc9bDc33a2959B9053EaE57169B5, _callbackFunctionId=System.Byte[], _nonce=68339, _dataVersion=1, _data=0x )
                                  • LinkToken.transferAndCall( _to=0x29e3b3c76e7ae0d681bf1a6BceE1c0E7d17DBAA9, _value=750000000000000000, _data=0x4042994600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000AFCC2D75F0494906BB644D3EB5CFEE9C0000000000000000000000000000000000000000000000000000000025FA978EA1A7DC9BDC33A2959B9053EAE57169B56A9705B4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010AF4000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000 ) => ( success=True )
                                    • 0x29e3b3c76e7ae0d681bf1a6bcee1c0e7d17dbaa9.a4c0ed36( )
                                      • 0x29e3b3c76e7ae0d681bf1a6bcee1c0e7d17dbaa9.40429946( )
                                        File 1 of 9: Aggregator
                                        pragma solidity 0.4.24;
                                        
                                        /**
                                        * @dev A library for working with mutable byte buffers in Solidity.
                                        *
                                        * Byte buffers are mutable and expandable, and provide a variety of primitives
                                        * for writing to them. At any time you can fetch a bytes object containing the
                                        * current contents of the buffer. The bytes object should not be stored between
                                        * operations, as it may change due to resizing of the buffer.
                                        */
                                        library Buffer {
                                          /**
                                          * @dev Represents a mutable buffer. Buffers have a current value (buf) and
                                          *      a capacity. The capacity may be longer than the current value, in
                                          *      which case it can be extended without the need to allocate more memory.
                                          */
                                          struct buffer {
                                            bytes buf;
                                            uint capacity;
                                          }
                                        
                                          /**
                                          * @dev Initializes a buffer with an initial capacity.
                                          * @param buf The buffer to initialize.
                                          * @param capacity The number of bytes of space to allocate the buffer.
                                          * @return The buffer, for chaining.
                                          */
                                          function init(buffer memory buf, uint capacity) internal pure returns(buffer memory) {
                                            if (capacity % 32 != 0) {
                                              capacity += 32 - (capacity % 32);
                                            }
                                            // Allocate space for the buffer data
                                            buf.capacity = capacity;
                                            assembly {
                                              let ptr := mload(0x40)
                                              mstore(buf, ptr)
                                              mstore(ptr, 0)
                                              mstore(0x40, add(32, add(ptr, capacity)))
                                            }
                                            return buf;
                                          }
                                        
                                          /**
                                          * @dev Initializes a new buffer from an existing bytes object.
                                          *      Changes to the buffer may mutate the original value.
                                          * @param b The bytes object to initialize the buffer with.
                                          * @return A new buffer.
                                          */
                                          function fromBytes(bytes memory b) internal pure returns(buffer memory) {
                                            buffer memory buf;
                                            buf.buf = b;
                                            buf.capacity = b.length;
                                            return buf;
                                          }
                                        
                                          function resize(buffer memory buf, uint capacity) private pure {
                                            bytes memory oldbuf = buf.buf;
                                            init(buf, capacity);
                                            append(buf, oldbuf);
                                          }
                                        
                                          function max(uint a, uint b) private pure returns(uint) {
                                            if (a > b) {
                                              return a;
                                            }
                                            return b;
                                          }
                                        
                                          /**
                                          * @dev Sets buffer length to 0.
                                          * @param buf The buffer to truncate.
                                          * @return The original buffer, for chaining..
                                          */
                                          function truncate(buffer memory buf) internal pure returns (buffer memory) {
                                            assembly {
                                              let bufptr := mload(buf)
                                              mstore(bufptr, 0)
                                            }
                                            return buf;
                                          }
                                        
                                          /**
                                          * @dev Writes a byte string to a buffer. Resizes if doing so would exceed
                                          *      the capacity of the buffer.
                                          * @param buf The buffer to append to.
                                          * @param off The start offset to write to.
                                          * @param data The data to append.
                                          * @param len The number of bytes to copy.
                                          * @return The original buffer, for chaining.
                                          */
                                          function write(buffer memory buf, uint off, bytes memory data, uint len) internal pure returns(buffer memory) {
                                            require(len <= data.length);
                                        
                                            if (off + len > buf.capacity) {
                                              resize(buf, max(buf.capacity, len + off) * 2);
                                            }
                                        
                                            uint dest;
                                            uint src;
                                            assembly {
                                              // Memory address of the buffer data
                                              let bufptr := mload(buf)
                                              // Length of existing buffer data
                                              let buflen := mload(bufptr)
                                              // Start address = buffer address + offset + sizeof(buffer length)
                                              dest := add(add(bufptr, 32), off)
                                              // Update buffer length if we're extending it
                                              if gt(add(len, off), buflen) {
                                                mstore(bufptr, add(len, off))
                                              }
                                              src := add(data, 32)
                                            }
                                        
                                            // Copy word-length chunks while possible
                                            for (; len >= 32; len -= 32) {
                                              assembly {
                                                mstore(dest, mload(src))
                                              }
                                              dest += 32;
                                              src += 32;
                                            }
                                        
                                            // Copy remaining bytes
                                            uint mask = 256 ** (32 - len) - 1;
                                            assembly {
                                              let srcpart := and(mload(src), not(mask))
                                              let destpart := and(mload(dest), mask)
                                              mstore(dest, or(destpart, srcpart))
                                            }
                                        
                                            return buf;
                                          }
                                        
                                          /**
                                          * @dev Appends a byte string to a buffer. Resizes if doing so would exceed
                                          *      the capacity of the buffer.
                                          * @param buf The buffer to append to.
                                          * @param data The data to append.
                                          * @param len The number of bytes to copy.
                                          * @return The original buffer, for chaining.
                                          */
                                          function append(buffer memory buf, bytes memory data, uint len) internal pure returns (buffer memory) {
                                            return write(buf, buf.buf.length, data, len);
                                          }
                                        
                                          /**
                                          * @dev Appends a byte string to a buffer. Resizes if doing so would exceed
                                          *      the capacity of the buffer.
                                          * @param buf The buffer to append to.
                                          * @param data The data to append.
                                          * @return The original buffer, for chaining.
                                          */
                                          function append(buffer memory buf, bytes memory data) internal pure returns (buffer memory) {
                                            return write(buf, buf.buf.length, data, data.length);
                                          }
                                        
                                          /**
                                          * @dev Writes a byte to the buffer. Resizes if doing so would exceed the
                                          *      capacity of the buffer.
                                          * @param buf The buffer to append to.
                                          * @param off The offset to write the byte at.
                                          * @param data The data to append.
                                          * @return The original buffer, for chaining.
                                          */
                                          function writeUint8(buffer memory buf, uint off, uint8 data) internal pure returns(buffer memory) {
                                            if (off >= buf.capacity) {
                                              resize(buf, buf.capacity * 2);
                                            }
                                        
                                            assembly {
                                              // Memory address of the buffer data
                                              let bufptr := mload(buf)
                                              // Length of existing buffer data
                                              let buflen := mload(bufptr)
                                              // Address = buffer address + sizeof(buffer length) + off
                                              let dest := add(add(bufptr, off), 32)
                                              mstore8(dest, data)
                                              // Update buffer length if we extended it
                                              if eq(off, buflen) {
                                                mstore(bufptr, add(buflen, 1))
                                              }
                                            }
                                            return buf;
                                          }
                                        
                                          /**
                                          * @dev Appends a byte to the buffer. Resizes if doing so would exceed the
                                          *      capacity of the buffer.
                                          * @param buf The buffer to append to.
                                          * @param data The data to append.
                                          * @return The original buffer, for chaining.
                                          */
                                          function appendUint8(buffer memory buf, uint8 data) internal pure returns(buffer memory) {
                                            return writeUint8(buf, buf.buf.length, data);
                                          }
                                        
                                          /**
                                          * @dev Writes up to 32 bytes to the buffer. Resizes if doing so would
                                          *      exceed the capacity of the buffer.
                                          * @param buf The buffer to append to.
                                          * @param off The offset to write at.
                                          * @param data The data to append.
                                          * @param len The number of bytes to write (left-aligned).
                                          * @return The original buffer, for chaining.
                                          */
                                          function write(buffer memory buf, uint off, bytes32 data, uint len) private pure returns(buffer memory) {
                                            if (len + off > buf.capacity) {
                                              resize(buf, (len + off) * 2);
                                            }
                                        
                                            uint mask = 256 ** len - 1;
                                            // Right-align data
                                            data = data >> (8 * (32 - len));
                                            assembly {
                                              // Memory address of the buffer data
                                              let bufptr := mload(buf)
                                              // Address = buffer address + sizeof(buffer length) + off + len
                                              let dest := add(add(bufptr, off), len)
                                              mstore(dest, or(and(mload(dest), not(mask)), data))
                                              // Update buffer length if we extended it
                                              if gt(add(off, len), mload(bufptr)) {
                                                mstore(bufptr, add(off, len))
                                              }
                                            }
                                            return buf;
                                          }
                                        
                                          /**
                                          * @dev Writes a bytes20 to the buffer. Resizes if doing so would exceed the
                                          *      capacity of the buffer.
                                          * @param buf The buffer to append to.
                                          * @param off The offset to write at.
                                          * @param data The data to append.
                                          * @return The original buffer, for chaining.
                                          */
                                          function writeBytes20(buffer memory buf, uint off, bytes20 data) internal pure returns (buffer memory) {
                                            return write(buf, off, bytes32(data), 20);
                                          }
                                        
                                          /**
                                          * @dev Appends a bytes20 to the buffer. Resizes if doing so would exceed
                                          *      the capacity of the buffer.
                                          * @param buf The buffer to append to.
                                          * @param data The data to append.
                                          * @return The original buffer, for chhaining.
                                          */
                                          function appendBytes20(buffer memory buf, bytes20 data) internal pure returns (buffer memory) {
                                            return write(buf, buf.buf.length, bytes32(data), 20);
                                          }
                                        
                                          /**
                                          * @dev Appends a bytes32 to the buffer. Resizes if doing so would exceed
                                          *      the capacity of the buffer.
                                          * @param buf The buffer to append to.
                                          * @param data The data to append.
                                          * @return The original buffer, for chaining.
                                          */
                                          function appendBytes32(buffer memory buf, bytes32 data) internal pure returns (buffer memory) {
                                            return write(buf, buf.buf.length, data, 32);
                                          }
                                        
                                          /**
                                          * @dev Writes an integer to the buffer. Resizes if doing so would exceed
                                          *      the capacity of the buffer.
                                          * @param buf The buffer to append to.
                                          * @param off The offset to write at.
                                          * @param data The data to append.
                                          * @param len The number of bytes to write (right-aligned).
                                          * @return The original buffer, for chaining.
                                          */
                                          function writeInt(buffer memory buf, uint off, uint data, uint len) private pure returns(buffer memory) {
                                            if (len + off > buf.capacity) {
                                              resize(buf, (len + off) * 2);
                                            }
                                        
                                            uint mask = 256 ** len - 1;
                                            assembly {
                                              // Memory address of the buffer data
                                              let bufptr := mload(buf)
                                              // Address = buffer address + off + sizeof(buffer length) + len
                                              let dest := add(add(bufptr, off), len)
                                              mstore(dest, or(and(mload(dest), not(mask)), data))
                                              // Update buffer length if we extended it
                                              if gt(add(off, len), mload(bufptr)) {
                                                mstore(bufptr, add(off, len))
                                              }
                                            }
                                            return buf;
                                          }
                                        
                                          /**
                                           * @dev Appends a byte to the end of the buffer. Resizes if doing so would
                                           * exceed the capacity of the buffer.
                                           * @param buf The buffer to append to.
                                           * @param data The data to append.
                                           * @return The original buffer.
                                           */
                                          function appendInt(buffer memory buf, uint data, uint len) internal pure returns(buffer memory) {
                                            return writeInt(buf, buf.buf.length, data, len);
                                          }
                                        }
                                        
                                        library CBOR {
                                          using Buffer for Buffer.buffer;
                                        
                                          uint8 private constant MAJOR_TYPE_INT = 0;
                                          uint8 private constant MAJOR_TYPE_NEGATIVE_INT = 1;
                                          uint8 private constant MAJOR_TYPE_BYTES = 2;
                                          uint8 private constant MAJOR_TYPE_STRING = 3;
                                          uint8 private constant MAJOR_TYPE_ARRAY = 4;
                                          uint8 private constant MAJOR_TYPE_MAP = 5;
                                          uint8 private constant MAJOR_TYPE_CONTENT_FREE = 7;
                                        
                                          function encodeType(Buffer.buffer memory buf, uint8 major, uint value) private pure {
                                            if(value <= 23) {
                                              buf.appendUint8(uint8((major << 5) | value));
                                            } else if(value <= 0xFF) {
                                              buf.appendUint8(uint8((major << 5) | 24));
                                              buf.appendInt(value, 1);
                                            } else if(value <= 0xFFFF) {
                                              buf.appendUint8(uint8((major << 5) | 25));
                                              buf.appendInt(value, 2);
                                            } else if(value <= 0xFFFFFFFF) {
                                              buf.appendUint8(uint8((major << 5) | 26));
                                              buf.appendInt(value, 4);
                                            } else if(value <= 0xFFFFFFFFFFFFFFFF) {
                                              buf.appendUint8(uint8((major << 5) | 27));
                                              buf.appendInt(value, 8);
                                            }
                                          }
                                        
                                          function encodeIndefiniteLengthType(Buffer.buffer memory buf, uint8 major) private pure {
                                            buf.appendUint8(uint8((major << 5) | 31));
                                          }
                                        
                                          function encodeUInt(Buffer.buffer memory buf, uint value) internal pure {
                                            encodeType(buf, MAJOR_TYPE_INT, value);
                                          }
                                        
                                          function encodeInt(Buffer.buffer memory buf, int value) internal pure {
                                            if(value >= 0) {
                                              encodeType(buf, MAJOR_TYPE_INT, uint(value));
                                            } else {
                                              encodeType(buf, MAJOR_TYPE_NEGATIVE_INT, uint(-1 - value));
                                            }
                                          }
                                        
                                          function encodeBytes(Buffer.buffer memory buf, bytes value) internal pure {
                                            encodeType(buf, MAJOR_TYPE_BYTES, value.length);
                                            buf.append(value);
                                          }
                                        
                                          function encodeString(Buffer.buffer memory buf, string value) internal pure {
                                            encodeType(buf, MAJOR_TYPE_STRING, bytes(value).length);
                                            buf.append(bytes(value));
                                          }
                                        
                                          function startArray(Buffer.buffer memory buf) internal pure {
                                            encodeIndefiniteLengthType(buf, MAJOR_TYPE_ARRAY);
                                          }
                                        
                                          function startMap(Buffer.buffer memory buf) internal pure {
                                            encodeIndefiniteLengthType(buf, MAJOR_TYPE_MAP);
                                          }
                                        
                                          function endSequence(Buffer.buffer memory buf) internal pure {
                                            encodeIndefiniteLengthType(buf, MAJOR_TYPE_CONTENT_FREE);
                                          }
                                        }
                                        
                                        /**
                                         * @title Library for common Chainlink functions
                                         * @dev Uses imported CBOR library for encoding to buffer
                                         */
                                        library Chainlink {
                                          uint256 internal constant defaultBufferSize = 256; // solhint-disable-line const-name-snakecase
                                        
                                          using CBOR for Buffer.buffer;
                                        
                                          struct Request {
                                            bytes32 id;
                                            address callbackAddress;
                                            bytes4 callbackFunctionId;
                                            uint256 nonce;
                                            Buffer.buffer buf;
                                          }
                                        
                                          /**
                                           * @notice Initializes a Chainlink request
                                           * @dev Sets the ID, callback address, and callback function signature on the request
                                           * @param self The uninitialized request
                                           * @param _id The Job Specification ID
                                           * @param _callbackAddress The callback address
                                           * @param _callbackFunction The callback function signature
                                           * @return The initialized request
                                           */
                                          function initialize(
                                            Request memory self,
                                            bytes32 _id,
                                            address _callbackAddress,
                                            bytes4 _callbackFunction
                                          ) internal pure returns (Chainlink.Request memory) {
                                            Buffer.init(self.buf, defaultBufferSize);
                                            self.id = _id;
                                            self.callbackAddress = _callbackAddress;
                                            self.callbackFunctionId = _callbackFunction;
                                            return self;
                                          }
                                        
                                          /**
                                           * @notice Sets the data for the buffer without encoding CBOR on-chain
                                           * @dev CBOR can be closed with curly-brackets {} or they can be left off
                                           * @param self The initialized request
                                           * @param _data The CBOR data
                                           */
                                          function setBuffer(Request memory self, bytes _data)
                                            internal pure
                                          {
                                            Buffer.init(self.buf, _data.length);
                                            Buffer.append(self.buf, _data);
                                          }
                                        
                                          /**
                                           * @notice Adds a string value to the request with a given key name
                                           * @param self The initialized request
                                           * @param _key The name of the key
                                           * @param _value The string value to add
                                           */
                                          function add(Request memory self, string _key, string _value)
                                            internal pure
                                          {
                                            self.buf.encodeString(_key);
                                            self.buf.encodeString(_value);
                                          }
                                        
                                          /**
                                           * @notice Adds a bytes value to the request with a given key name
                                           * @param self The initialized request
                                           * @param _key The name of the key
                                           * @param _value The bytes value to add
                                           */
                                          function addBytes(Request memory self, string _key, bytes _value)
                                            internal pure
                                          {
                                            self.buf.encodeString(_key);
                                            self.buf.encodeBytes(_value);
                                          }
                                        
                                          /**
                                           * @notice Adds a int256 value to the request with a given key name
                                           * @param self The initialized request
                                           * @param _key The name of the key
                                           * @param _value The int256 value to add
                                           */
                                          function addInt(Request memory self, string _key, int256 _value)
                                            internal pure
                                          {
                                            self.buf.encodeString(_key);
                                            self.buf.encodeInt(_value);
                                          }
                                        
                                          /**
                                           * @notice Adds a uint256 value to the request with a given key name
                                           * @param self The initialized request
                                           * @param _key The name of the key
                                           * @param _value The uint256 value to add
                                           */
                                          function addUint(Request memory self, string _key, uint256 _value)
                                            internal pure
                                          {
                                            self.buf.encodeString(_key);
                                            self.buf.encodeUInt(_value);
                                          }
                                        
                                          /**
                                           * @notice Adds an array of strings to the request with a given key name
                                           * @param self The initialized request
                                           * @param _key The name of the key
                                           * @param _values The array of string values to add
                                           */
                                          function addStringArray(Request memory self, string _key, string[] memory _values)
                                            internal pure
                                          {
                                            self.buf.encodeString(_key);
                                            self.buf.startArray();
                                            for (uint256 i = 0; i < _values.length; i++) {
                                              self.buf.encodeString(_values[i]);
                                            }
                                            self.buf.endSequence();
                                          }
                                        }
                                        
                                        interface ENSInterface {
                                        
                                          // Logged when the owner of a node assigns a new owner to a subnode.
                                          event NewOwner(bytes32 indexed node, bytes32 indexed label, address owner);
                                        
                                          // Logged when the owner of a node transfers ownership to a new account.
                                          event Transfer(bytes32 indexed node, address owner);
                                        
                                          // Logged when the resolver for a node changes.
                                          event NewResolver(bytes32 indexed node, address resolver);
                                        
                                          // Logged when the TTL of a node changes
                                          event NewTTL(bytes32 indexed node, uint64 ttl);
                                        
                                        
                                          function setSubnodeOwner(bytes32 node, bytes32 label, address owner) external;
                                          function setResolver(bytes32 node, address resolver) external;
                                          function setOwner(bytes32 node, address owner) external;
                                          function setTTL(bytes32 node, uint64 ttl) external;
                                          function owner(bytes32 node) external view returns (address);
                                          function resolver(bytes32 node) external view returns (address);
                                          function ttl(bytes32 node) external view returns (uint64);
                                        
                                        }
                                        
                                        interface LinkTokenInterface {
                                          function allowance(address owner, address spender) external returns (uint256 remaining);
                                          function approve(address spender, uint256 value) external returns (bool success);
                                          function balanceOf(address owner) external returns (uint256 balance);
                                          function decimals() external returns (uint8 decimalPlaces);
                                          function decreaseApproval(address spender, uint256 addedValue) external returns (bool success);
                                          function increaseApproval(address spender, uint256 subtractedValue) external;
                                          function name() external returns (string tokenName);
                                          function symbol() external returns (string tokenSymbol);
                                          function totalSupply() external returns (uint256 totalTokensIssued);
                                          function transfer(address to, uint256 value) external returns (bool success);
                                          function transferAndCall(address to, uint256 value, bytes data) external returns (bool success);
                                          function transferFrom(address from, address to, uint256 value) external returns (bool success);
                                        }
                                        
                                        interface ChainlinkRequestInterface {
                                          function oracleRequest(
                                            address sender,
                                            uint256 payment,
                                            bytes32 id,
                                            address callbackAddress,
                                            bytes4 callbackFunctionId,
                                            uint256 nonce,
                                            uint256 version,
                                            bytes data
                                          ) external;
                                        
                                          function cancelOracleRequest(
                                            bytes32 requestId,
                                            uint256 payment,
                                            bytes4 callbackFunctionId,
                                            uint256 expiration
                                          ) external;
                                        }
                                        
                                        interface PointerInterface {
                                          function getAddress() external view returns (address);
                                        }
                                        
                                        
                                        contract ENSResolver {
                                          function addr(bytes32 node) public view returns (address);
                                        }
                                        
                                        
                                        /**
                                         * @title SafeMath
                                         * @dev Math operations with safety checks that throw on error
                                         */
                                        library SafeMath {
                                        
                                          /**
                                          * @dev Multiplies two numbers, throws on overflow.
                                          */
                                          function mul(uint256 _a, uint256 _b) internal pure returns (uint256 c) {
                                            // Gas optimization: this is cheaper than asserting 'a' not being zero, but the
                                            // benefit is lost if 'b' is also tested.
                                            // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
                                            if (_a == 0) {
                                              return 0;
                                            }
                                        
                                            c = _a * _b;
                                            assert(c / _a == _b);
                                            return c;
                                          }
                                        
                                          /**
                                          * @dev Integer division of two numbers, truncating the quotient.
                                          */
                                          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 _a / _b;
                                          }
                                        
                                          /**
                                          * @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend).
                                          */
                                          function sub(uint256 _a, uint256 _b) internal pure returns (uint256) {
                                            assert(_b <= _a);
                                            return _a - _b;
                                          }
                                        
                                          /**
                                          * @dev Adds two numbers, throws on overflow.
                                          */
                                          function add(uint256 _a, uint256 _b) internal pure returns (uint256 c) {
                                            c = _a + _b;
                                            assert(c >= _a);
                                            return c;
                                          }
                                        }
                                        
                                        /**
                                         * @title The ChainlinkClient contract
                                         * @notice Contract writers can inherit this contract in order to create requests for the
                                         * Chainlink network
                                         */
                                        contract ChainlinkClient {
                                          using Chainlink for Chainlink.Request;
                                          using SafeMath for uint256;
                                        
                                          uint256 constant internal LINK = 10**18;
                                          uint256 constant private AMOUNT_OVERRIDE = 0;
                                          address constant private SENDER_OVERRIDE = 0x0;
                                          uint256 constant private ARGS_VERSION = 1;
                                          bytes32 constant private ENS_TOKEN_SUBNAME = keccak256("link");
                                          bytes32 constant private ENS_ORACLE_SUBNAME = keccak256("oracle");
                                          address constant private LINK_TOKEN_POINTER = 0xC89bD4E1632D3A43CB03AAAd5262cbe4038Bc571;
                                        
                                          ENSInterface private ens;
                                          bytes32 private ensNode;
                                          LinkTokenInterface private link;
                                          ChainlinkRequestInterface private oracle;
                                          uint256 private requests = 1;
                                          mapping(bytes32 => address) private pendingRequests;
                                        
                                          event ChainlinkRequested(bytes32 indexed id);
                                          event ChainlinkFulfilled(bytes32 indexed id);
                                          event ChainlinkCancelled(bytes32 indexed id);
                                        
                                          /**
                                           * @notice Creates a request that can hold additional parameters
                                           * @param _specId The Job Specification ID that the request will be created for
                                           * @param _callbackAddress The callback address that the response will be sent to
                                           * @param _callbackFunctionSignature The callback function signature to use for the callback address
                                           * @return A Chainlink Request struct in memory
                                           */
                                          function buildChainlinkRequest(
                                            bytes32 _specId,
                                            address _callbackAddress,
                                            bytes4 _callbackFunctionSignature
                                          ) internal pure returns (Chainlink.Request memory) {
                                            Chainlink.Request memory req;
                                            return req.initialize(_specId, _callbackAddress, _callbackFunctionSignature);
                                          }
                                        
                                          /**
                                           * @notice Creates a Chainlink request to the stored oracle address
                                           * @dev Calls `chainlinkRequestTo` with the stored oracle address
                                           * @param _req The initialized Chainlink Request
                                           * @param _payment The amount of LINK to send for the request
                                           * @return The request ID
                                           */
                                          function sendChainlinkRequest(Chainlink.Request memory _req, uint256 _payment)
                                            internal
                                            returns (bytes32)
                                          {
                                            return sendChainlinkRequestTo(oracle, _req, _payment);
                                          }
                                        
                                          /**
                                           * @notice Creates a Chainlink request to the specified oracle address
                                           * @dev Generates and stores a request ID, increments the local nonce, and uses `transferAndCall` to
                                           * send LINK which creates a request on the target oracle contract.
                                           * Emits ChainlinkRequested event.
                                           * @param _oracle The address of the oracle for the request
                                           * @param _req The initialized Chainlink Request
                                           * @param _payment The amount of LINK to send for the request
                                           * @return The request ID
                                           */
                                          function sendChainlinkRequestTo(address _oracle, Chainlink.Request memory _req, uint256 _payment)
                                            internal
                                            returns (bytes32 requestId)
                                          {
                                            requestId = keccak256(abi.encodePacked(this, requests));
                                            _req.nonce = requests;
                                            pendingRequests[requestId] = _oracle;
                                            emit ChainlinkRequested(requestId);
                                            require(link.transferAndCall(_oracle, _payment, encodeRequest(_req)), "unable to transferAndCall to oracle");
                                            requests += 1;
                                        
                                            return requestId;
                                          }
                                        
                                          /**
                                           * @notice Allows a request to be cancelled if it has not been fulfilled
                                           * @dev Requires keeping track of the expiration value emitted from the oracle contract.
                                           * Deletes the request from the `pendingRequests` mapping.
                                           * Emits ChainlinkCancelled event.
                                           * @param _requestId The request ID
                                           * @param _payment The amount of LINK sent for the request
                                           * @param _callbackFunc The callback function specified for the request
                                           * @param _expiration The time of the expiration for the request
                                           */
                                          function cancelChainlinkRequest(
                                            bytes32 _requestId,
                                            uint256 _payment,
                                            bytes4 _callbackFunc,
                                            uint256 _expiration
                                          )
                                            internal
                                          {
                                            ChainlinkRequestInterface requested = ChainlinkRequestInterface(pendingRequests[_requestId]);
                                            delete pendingRequests[_requestId];
                                            emit ChainlinkCancelled(_requestId);
                                            requested.cancelOracleRequest(_requestId, _payment, _callbackFunc, _expiration);
                                          }
                                        
                                          /**
                                           * @notice Sets the stored oracle address
                                           * @param _oracle The address of the oracle contract
                                           */
                                          function setChainlinkOracle(address _oracle) internal {
                                            oracle = ChainlinkRequestInterface(_oracle);
                                          }
                                        
                                          /**
                                           * @notice Sets the LINK token address
                                           * @param _link The address of the LINK token contract
                                           */
                                          function setChainlinkToken(address _link) internal {
                                            link = LinkTokenInterface(_link);
                                          }
                                        
                                          /**
                                           * @notice Sets the Chainlink token address for the public
                                           * network as given by the Pointer contract
                                           */
                                          function setPublicChainlinkToken() internal {
                                            setChainlinkToken(PointerInterface(LINK_TOKEN_POINTER).getAddress());
                                          }
                                        
                                          /**
                                           * @notice Retrieves the stored address of the LINK token
                                           * @return The address of the LINK token
                                           */
                                          function chainlinkTokenAddress()
                                            internal
                                            view
                                            returns (address)
                                          {
                                            return address(link);
                                          }
                                        
                                          /**
                                           * @notice Retrieves the stored address of the oracle contract
                                           * @return The address of the oracle contract
                                           */
                                          function chainlinkOracleAddress()
                                            internal
                                            view
                                            returns (address)
                                          {
                                            return address(oracle);
                                          }
                                        
                                          /**
                                           * @notice Allows for a request which was created on another contract to be fulfilled
                                           * on this contract
                                           * @param _oracle The address of the oracle contract that will fulfill the request
                                           * @param _requestId The request ID used for the response
                                           */
                                          function addChainlinkExternalRequest(address _oracle, bytes32 _requestId)
                                            internal
                                            notPendingRequest(_requestId)
                                          {
                                            pendingRequests[_requestId] = _oracle;
                                          }
                                        
                                          /**
                                           * @notice Sets the stored oracle and LINK token contracts with the addresses resolved by ENS
                                           * @dev Accounts for subnodes having different resolvers
                                           * @param _ens The address of the ENS contract
                                           * @param _node The ENS node hash
                                           */
                                          function useChainlinkWithENS(address _ens, bytes32 _node)
                                            internal
                                          {
                                            ens = ENSInterface(_ens);
                                            ensNode = _node;
                                            bytes32 linkSubnode = keccak256(abi.encodePacked(ensNode, ENS_TOKEN_SUBNAME));
                                            ENSResolver resolver = ENSResolver(ens.resolver(linkSubnode));
                                            setChainlinkToken(resolver.addr(linkSubnode));
                                            updateChainlinkOracleWithENS();
                                          }
                                        
                                          /**
                                           * @notice Sets the stored oracle contract with the address resolved by ENS
                                           * @dev This may be called on its own as long as `useChainlinkWithENS` has been called previously
                                           */
                                          function updateChainlinkOracleWithENS()
                                            internal
                                          {
                                            bytes32 oracleSubnode = keccak256(abi.encodePacked(ensNode, ENS_ORACLE_SUBNAME));
                                            ENSResolver resolver = ENSResolver(ens.resolver(oracleSubnode));
                                            setChainlinkOracle(resolver.addr(oracleSubnode));
                                          }
                                        
                                          /**
                                           * @notice Encodes the request to be sent to the oracle contract
                                           * @dev The Chainlink node expects values to be in order for the request to be picked up. Order of types
                                           * will be validated in the oracle contract.
                                           * @param _req The initialized Chainlink Request
                                           * @return The bytes payload for the `transferAndCall` method
                                           */
                                          function encodeRequest(Chainlink.Request memory _req)
                                            private
                                            view
                                            returns (bytes memory)
                                          {
                                            return abi.encodeWithSelector(
                                              oracle.oracleRequest.selector,
                                              SENDER_OVERRIDE, // Sender value - overridden by onTokenTransfer by the requesting contract's address
                                              AMOUNT_OVERRIDE, // Amount value - overridden by onTokenTransfer by the actual amount of LINK sent
                                              _req.id,
                                              _req.callbackAddress,
                                              _req.callbackFunctionId,
                                              _req.nonce,
                                              ARGS_VERSION,
                                              _req.buf.buf);
                                          }
                                        
                                          /**
                                           * @notice Ensures that the fulfillment is valid for this contract
                                           * @dev Use if the contract developer prefers methods instead of modifiers for validation
                                           * @param _requestId The request ID for fulfillment
                                           */
                                          function validateChainlinkCallback(bytes32 _requestId)
                                            internal
                                            recordChainlinkFulfillment(_requestId)
                                            // solhint-disable-next-line no-empty-blocks
                                          {}
                                        
                                          /**
                                           * @dev Reverts if the sender is not the oracle of the request.
                                           * Emits ChainlinkFulfilled event.
                                           * @param _requestId The request ID for fulfillment
                                           */
                                          modifier recordChainlinkFulfillment(bytes32 _requestId) {
                                            require(msg.sender == pendingRequests[_requestId], "Source must be the oracle of the request");
                                            delete pendingRequests[_requestId];
                                            emit ChainlinkFulfilled(_requestId);
                                            _;
                                          }
                                        
                                          /**
                                           * @dev Reverts if the request is already pending
                                           * @param _requestId The request ID for fulfillment
                                           */
                                          modifier notPendingRequest(bytes32 _requestId) {
                                            require(pendingRequests[_requestId] == address(0), "Request is already pending");
                                            _;
                                          }
                                        }
                                        
                                        interface AggregatorInterface {
                                          function latestAnswer() external view returns (int256);
                                          function latestTimestamp() external view returns (uint256);
                                          function latestRound() external view returns (uint256);
                                          function getAnswer(uint256 roundId) external view returns (int256);
                                          function getTimestamp(uint256 roundId) external view returns (uint256);
                                        
                                          event AnswerUpdated(int256 indexed current, uint256 indexed roundId, uint256 timestamp);
                                          event NewRound(uint256 indexed roundId, address indexed startedBy);
                                        }
                                        
                                        library SignedSafeMath {
                                        
                                          /**
                                           * @dev Adds two int256s and makes sure the result doesn't overflow. Signed
                                           * integers aren't supported by the SafeMath library, thus this method
                                           * @param _a The first number to be added
                                           * @param _a The second number to be added
                                           */
                                          function add(int256 _a, int256 _b)
                                            internal
                                            pure
                                            returns (int256)
                                          {
                                            int256 c = _a + _b;
                                            require((_b >= 0 && c >= _a) || (_b < 0 && c < _a), "SignedSafeMath: addition overflow");
                                        
                                            return c;
                                          }
                                        }
                                        
                                        /**
                                         * @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 OwnershipRenounced(address indexed previousOwner);
                                          event OwnershipTransferred(
                                            address indexed previousOwner,
                                            address indexed newOwner
                                          );
                                        
                                        
                                          /**
                                           * @dev The Ownable constructor sets the original `owner` of the contract to the sender
                                           * account.
                                           */
                                          constructor() 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 relinquish control of the contract.
                                           * @notice Renouncing to ownership will leave the contract without an owner.
                                           * It will not be possible to call the functions with the `onlyOwner`
                                           * modifier anymore.
                                           */
                                          function renounceOwnership() public onlyOwner {
                                            emit OwnershipRenounced(owner);
                                            owner = address(0);
                                          }
                                        
                                          /**
                                           * @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 {
                                            _transferOwnership(_newOwner);
                                          }
                                        
                                          /**
                                           * @dev Transfers control of the contract to a newOwner.
                                           * @param _newOwner The address to transfer ownership to.
                                           */
                                          function _transferOwnership(address _newOwner) internal {
                                            require(_newOwner != address(0));
                                            emit OwnershipTransferred(owner, _newOwner);
                                            owner = _newOwner;
                                          }
                                        }
                                        
                                        /**
                                         * @title An example Chainlink contract with aggregation
                                         * @notice Requesters can use this contract as a framework for creating
                                         * requests to multiple Chainlink nodes and running aggregation
                                         * as the contract receives answers.
                                         */
                                        contract Aggregator is AggregatorInterface, ChainlinkClient, Ownable {
                                          using SignedSafeMath for int256;
                                        
                                          struct Answer {
                                            uint128 minimumResponses;
                                            uint128 maxResponses;
                                            int256[] responses;
                                          }
                                        
                                          event ResponseReceived(int256 indexed response, uint256 indexed answerId, address indexed sender);
                                        
                                          int256 private currentAnswerValue;
                                          uint256 private updatedTimestampValue;
                                          uint256 private latestCompletedAnswer;
                                          uint128 public paymentAmount;
                                          uint128 public minimumResponses;
                                          bytes32[] public jobIds;
                                          address[] public oracles;
                                        
                                          uint256 private answerCounter = 1;
                                          mapping(address => bool) public authorizedRequesters;
                                          mapping(bytes32 => uint256) private requestAnswers;
                                          mapping(uint256 => Answer) private answers;
                                          mapping(uint256 => int256) private currentAnswers;
                                          mapping(uint256 => uint256) private updatedTimestamps;
                                        
                                          uint256 constant private MAX_ORACLE_COUNT = 45;
                                        
                                          /**
                                           * @notice Deploy with the address of the LINK token and arrays of matching
                                           * length containing the addresses of the oracles and their corresponding
                                           * Job IDs.
                                           * @dev Sets the LinkToken address for the network, addresses of the oracles,
                                           * and jobIds in storage.
                                           * @param _link The address of the LINK token
                                           * @param _paymentAmount the amount of LINK to be sent to each oracle for each request
                                           * @param _minimumResponses the minimum number of responses
                                           * before an answer will be calculated
                                           * @param _oracles An array of oracle addresses
                                           * @param _jobIds An array of Job IDs
                                           */
                                          constructor(
                                            address _link,
                                            uint128 _paymentAmount,
                                            uint128 _minimumResponses,
                                            address[] _oracles,
                                            bytes32[] _jobIds
                                          ) public Ownable() {
                                            setChainlinkToken(_link);
                                            updateRequestDetails(_paymentAmount, _minimumResponses, _oracles, _jobIds);
                                          }
                                        
                                          /**
                                           * @notice Creates a Chainlink request for each oracle in the oracles array.
                                           * @dev This example does not include request parameters. Reference any documentation
                                           * associated with the Job IDs used to determine the required parameters per-request.
                                           */
                                          function requestRateUpdate()
                                            external
                                            ensureAuthorizedRequester()
                                          {
                                            Chainlink.Request memory request;
                                            bytes32 requestId;
                                            uint256 oraclePayment = paymentAmount;
                                        
                                            for (uint i = 0; i < oracles.length; i++) {
                                              request = buildChainlinkRequest(jobIds[i], this, this.chainlinkCallback.selector);
                                              requestId = sendChainlinkRequestTo(oracles[i], request, oraclePayment);
                                              requestAnswers[requestId] = answerCounter;
                                            }
                                            answers[answerCounter].minimumResponses = minimumResponses;
                                            answers[answerCounter].maxResponses = uint128(oracles.length);
                                            answerCounter = answerCounter.add(1);
                                        
                                            emit NewRound(answerCounter, msg.sender);
                                          }
                                        
                                          /**
                                           * @notice Receives the answer from the Chainlink node.
                                           * @dev This function can only be called by the oracle that received the request.
                                           * @param _clRequestId The Chainlink request ID associated with the answer
                                           * @param _response The answer provided by the Chainlink node
                                           */
                                          function chainlinkCallback(bytes32 _clRequestId, int256 _response)
                                            external
                                          {
                                            validateChainlinkCallback(_clRequestId);
                                        
                                            uint256 answerId = requestAnswers[_clRequestId];
                                            delete requestAnswers[_clRequestId];
                                        
                                            answers[answerId].responses.push(_response);
                                            emit ResponseReceived(_response, answerId, msg.sender);
                                            updateLatestAnswer(answerId);
                                            deleteAnswer(answerId);
                                          }
                                        
                                          /**
                                           * @notice Updates the arrays of oracles and jobIds with new values,
                                           * overwriting the old values.
                                           * @dev Arrays are validated to be equal length.
                                           * @param _paymentAmount the amount of LINK to be sent to each oracle for each request
                                           * @param _minimumResponses the minimum number of responses
                                           * before an answer will be calculated
                                           * @param _oracles An array of oracle addresses
                                           * @param _jobIds An array of Job IDs
                                           */
                                          function updateRequestDetails(
                                            uint128 _paymentAmount,
                                            uint128 _minimumResponses,
                                            address[] _oracles,
                                            bytes32[] _jobIds
                                          )
                                            public
                                            onlyOwner()
                                            validateAnswerRequirements(_minimumResponses, _oracles, _jobIds)
                                          {
                                            paymentAmount = _paymentAmount;
                                            minimumResponses = _minimumResponses;
                                            jobIds = _jobIds;
                                            oracles = _oracles;
                                          }
                                        
                                          /**
                                           * @notice Allows the owner of the contract to withdraw any LINK balance
                                           * available on the contract.
                                           * @dev The contract will need to have a LINK balance in order to create requests.
                                           * @param _recipient The address to receive the LINK tokens
                                           * @param _amount The amount of LINK to send from the contract
                                           */
                                          function transferLINK(address _recipient, uint256 _amount)
                                            public
                                            onlyOwner()
                                          {
                                            LinkTokenInterface linkToken = LinkTokenInterface(chainlinkTokenAddress());
                                            require(linkToken.transfer(_recipient, _amount), "LINK transfer failed");
                                          }
                                        
                                          /**
                                           * @notice Called by the owner to permission other addresses to generate new
                                           * requests to oracles.
                                           * @param _requester the address whose permissions are being set
                                           * @param _allowed boolean that determines whether the requester is
                                           * permissioned or not
                                           */
                                          function setAuthorization(address _requester, bool _allowed)
                                            external
                                            onlyOwner()
                                          {
                                            authorizedRequesters[_requester] = _allowed;
                                          }
                                        
                                          /**
                                           * @notice Cancels an outstanding Chainlink request.
                                           * The oracle contract requires the request ID and additional metadata to
                                           * validate the cancellation. Only old answers can be cancelled.
                                           * @param _requestId is the identifier for the chainlink request being cancelled
                                           * @param _payment is the amount of LINK paid to the oracle for the request
                                           * @param _expiration is the time when the request expires
                                           */
                                          function cancelRequest(
                                            bytes32 _requestId,
                                            uint256 _payment,
                                            uint256 _expiration
                                          )
                                            external
                                            ensureAuthorizedRequester()
                                          {
                                            uint256 answerId = requestAnswers[_requestId];
                                            require(answerId < latestCompletedAnswer, "Cannot modify an in-progress answer");
                                        
                                            delete requestAnswers[_requestId];
                                            answers[answerId].responses.push(0);
                                            deleteAnswer(answerId);
                                        
                                            cancelChainlinkRequest(
                                              _requestId,
                                              _payment,
                                              this.chainlinkCallback.selector,
                                              _expiration
                                            );
                                          }
                                        
                                          /**
                                           * @notice Called by the owner to kill the contract. This transfers all LINK
                                           * balance and ETH balance (if there is any) to the owner.
                                           */
                                          function destroy()
                                            external
                                            onlyOwner()
                                          {
                                            LinkTokenInterface linkToken = LinkTokenInterface(chainlinkTokenAddress());
                                            transferLINK(owner, linkToken.balanceOf(address(this)));
                                            selfdestruct(owner);
                                          }
                                        
                                          /**
                                           * @dev Performs aggregation of the answers received from the Chainlink nodes.
                                           * Assumes that at least half the oracles are honest and so can't contol the
                                           * middle of the ordered responses.
                                           * @param _answerId The answer ID associated with the group of requests
                                           */
                                          function updateLatestAnswer(uint256 _answerId)
                                            private
                                            ensureMinResponsesReceived(_answerId)
                                            ensureOnlyLatestAnswer(_answerId)
                                          {
                                            uint256 responseLength = answers[_answerId].responses.length;
                                            uint256 middleIndex = responseLength.div(2);
                                            int256 currentAnswerTemp;
                                            if (responseLength % 2 == 0) {
                                              int256 median1 = quickselect(answers[_answerId].responses, middleIndex);
                                              int256 median2 = quickselect(answers[_answerId].responses, middleIndex.add(1)); // quickselect is 1 indexed
                                              currentAnswerTemp = median1.add(median2) / 2; // signed integers are not supported by SafeMath
                                            } else {
                                              currentAnswerTemp = quickselect(answers[_answerId].responses, middleIndex.add(1)); // quickselect is 1 indexed
                                            }
                                            currentAnswerValue = currentAnswerTemp;
                                            latestCompletedAnswer = _answerId;
                                            updatedTimestampValue = now;
                                            updatedTimestamps[_answerId] = now;
                                            currentAnswers[_answerId] = currentAnswerTemp;
                                            emit AnswerUpdated(currentAnswerTemp, _answerId, now);
                                          }
                                        
                                          /**
                                           * @notice get the most recently reported answer
                                           */
                                          function latestAnswer()
                                            external
                                            view
                                            returns (int256)
                                          {
                                            return currentAnswers[latestCompletedAnswer];
                                          }
                                        
                                          /**
                                           * @notice get the last updated at block timestamp
                                           */
                                          function latestTimestamp()
                                            external
                                            view
                                            returns (uint256)
                                          {
                                            return updatedTimestamps[latestCompletedAnswer];
                                          }
                                        
                                          /**
                                           * @notice get past rounds answers
                                           * @param _roundId the answer number to retrieve the answer for
                                           */
                                          function getAnswer(uint256 _roundId)
                                            external
                                            view
                                            returns (int256)
                                          {
                                            return currentAnswers[_roundId];
                                          }
                                        
                                          /**
                                           * @notice get block timestamp when an answer was last updated
                                           * @param _roundId the answer number to retrieve the updated timestamp for
                                           */
                                          function getTimestamp(uint256 _roundId)
                                            external
                                            view
                                            returns (uint256)
                                          {
                                            return updatedTimestamps[_roundId];
                                          }
                                        
                                          /**
                                           * @notice get the latest completed round where the answer was updated
                                           */
                                          function latestRound() external view returns (uint256) {
                                            return latestCompletedAnswer;
                                          }
                                        
                                          /**
                                           * @dev Returns the kth value of the ordered array
                                           * See: http://www.cs.yale.edu/homes/aspnes/pinewiki/QuickSelect.html
                                           * @param _a The list of elements to pull from
                                           * @param _k The index, 1 based, of the elements you want to pull from when ordered
                                           */
                                          function quickselect(int256[] memory _a, uint256 _k)
                                            private
                                            pure
                                            returns (int256)
                                          {
                                            int256[] memory a = _a;
                                            uint256 k = _k;
                                            uint256 aLen = a.length;
                                            int256[] memory a1 = new int256[](aLen);
                                            int256[] memory a2 = new int256[](aLen);
                                            uint256 a1Len;
                                            uint256 a2Len;
                                            int256 pivot;
                                            uint256 i;
                                        
                                            while (true) {
                                              pivot = a[aLen.div(2)];
                                              a1Len = 0;
                                              a2Len = 0;
                                              for (i = 0; i < aLen; i++) {
                                                if (a[i] < pivot) {
                                                  a1[a1Len] = a[i];
                                                  a1Len++;
                                                } else if (a[i] > pivot) {
                                                  a2[a2Len] = a[i];
                                                  a2Len++;
                                                }
                                              }
                                              if (k <= a1Len) {
                                                aLen = a1Len;
                                                (a, a1) = swap(a, a1);
                                              } else if (k > (aLen.sub(a2Len))) {
                                                k = k.sub(aLen.sub(a2Len));
                                                aLen = a2Len;
                                                (a, a2) = swap(a, a2);
                                              } else {
                                                return pivot;
                                              }
                                            }
                                          }
                                        
                                          /**
                                           * @dev Swaps the pointers to two uint256 arrays in memory
                                           * @param _a The pointer to the first in memory array
                                           * @param _b The pointer to the second in memory array
                                           */
                                          function swap(int256[] memory _a, int256[] memory _b)
                                            private
                                            pure
                                            returns(int256[] memory, int256[] memory)
                                          {
                                            return (_b, _a);
                                          }
                                        
                                          /**
                                           * @dev Cleans up the answer record if all responses have been received.
                                           * @param _answerId The identifier of the answer to be deleted
                                           */
                                          function deleteAnswer(uint256 _answerId)
                                            private
                                            ensureAllResponsesReceived(_answerId)
                                          {
                                            delete answers[_answerId];
                                          }
                                        
                                          /**
                                           * @dev Prevents taking an action if the minimum number of responses has not
                                           * been received for an answer.
                                           * @param _answerId The the identifier of the answer that keeps track of the responses.
                                           */
                                          modifier ensureMinResponsesReceived(uint256 _answerId) {
                                            if (answers[_answerId].responses.length >= answers[_answerId].minimumResponses) {
                                              _;
                                            }
                                          }
                                        
                                          /**
                                           * @dev Prevents taking an action if not all responses are received for an answer.
                                           * @param _answerId The the identifier of the answer that keeps track of the responses.
                                           */
                                          modifier ensureAllResponsesReceived(uint256 _answerId) {
                                            if (answers[_answerId].responses.length == answers[_answerId].maxResponses) {
                                              _;
                                            }
                                          }
                                        
                                          /**
                                           * @dev Prevents taking an action if a newer answer has been recorded.
                                           * @param _answerId The current answer's identifier.
                                           * Answer IDs are in ascending order.
                                           */
                                          modifier ensureOnlyLatestAnswer(uint256 _answerId) {
                                            if (latestCompletedAnswer <= _answerId) {
                                              _;
                                            }
                                          }
                                        
                                          /**
                                           * @dev Ensures corresponding number of oracles and jobs.
                                           * @param _oracles The list of oracles.
                                           * @param _jobIds The list of jobs.
                                           */
                                          modifier validateAnswerRequirements(
                                            uint256 _minimumResponses,
                                            address[] _oracles,
                                            bytes32[] _jobIds
                                          ) {
                                            require(_oracles.length <= MAX_ORACLE_COUNT, "cannot have more than 45 oracles");
                                            require(_oracles.length >= _minimumResponses, "must have at least as many oracles as responses");
                                            require(_oracles.length == _jobIds.length, "must have exactly as many oracles as job IDs");
                                            _;
                                          }
                                        
                                          /**
                                           * @dev Reverts if `msg.sender` is not authorized to make requests.
                                           */
                                          modifier ensureAuthorizedRequester() {
                                            require(authorizedRequesters[msg.sender] || msg.sender == owner, "Not an authorized address for creating requests");
                                            _;
                                          }
                                        
                                        }

                                        File 2 of 9: LinkToken
                                        pragma solidity ^0.4.16;
                                        
                                        
                                        /**
                                         * @title SafeMath
                                         * @dev Math operations with safety checks that throw on error
                                         */
                                        library SafeMath {
                                          function mul(uint256 a, uint256 b) internal constant returns (uint256) {
                                            uint256 c = a * b;
                                            assert(a == 0 || c / a == b);
                                            return c;
                                          }
                                        
                                          function div(uint256 a, uint256 b) internal constant 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 constant returns (uint256) {
                                            assert(b <= a);
                                            return a - b;
                                          }
                                        
                                          function add(uint256 a, uint256 b) internal constant returns (uint256) {
                                            uint256 c = a + b;
                                            assert(c >= a);
                                            return c;
                                          }
                                        }
                                        
                                        
                                        /**
                                         * @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) constant returns (uint256);
                                          function transfer(address to, uint256 value) 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) constant returns (uint256);
                                          function transferFrom(address from, address to, uint256 value) returns (bool);
                                          function approve(address spender, uint256 value) returns (bool);
                                          event Approval(address indexed owner, address indexed spender, uint256 value);
                                        }
                                        
                                        contract ERC677 is ERC20 {
                                          function transferAndCall(address to, uint value, bytes data) returns (bool success);
                                        
                                          event Transfer(address indexed from, address indexed to, uint value, bytes data);
                                        }
                                        
                                        contract ERC677Receiver {
                                          function onTokenTransfer(address _sender, uint _value, bytes _data);
                                        }
                                        
                                        /**
                                         * @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) returns (bool) {
                                            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) constant 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)) 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) returns (bool) {
                                            var _allowance = allowed[_from][msg.sender];
                                        
                                            // Check is not needed because sub(_allowance, _value) will already throw if this condition is not met
                                            // require (_value <= _allowance);
                                        
                                            balances[_from] = balances[_from].sub(_value);
                                            balances[_to] = balances[_to].add(_value);
                                            allowed[_from][msg.sender] = _allowance.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.
                                           * @param _spender The address which will spend the funds.
                                           * @param _value The amount of tokens to be spent.
                                           */
                                          function approve(address _spender, uint256 _value) 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) constant returns (uint256 remaining) {
                                            return allowed[_owner][_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
                                           */
                                          function increaseApproval (address _spender, uint _addedValue) 
                                            returns (bool success) {
                                            allowed[msg.sender][_spender] = allowed[msg.sender][_spender].add(_addedValue);
                                            Approval(msg.sender, _spender, allowed[msg.sender][_spender]);
                                            return true;
                                          }
                                        
                                          function decreaseApproval (address _spender, uint _subtractedValue) 
                                            returns (bool success) {
                                            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;
                                          }
                                        
                                        }
                                        
                                        contract ERC677Token is ERC677 {
                                        
                                          /**
                                          * @dev transfer token to a contract address with additional data if the recipient is a contact.
                                          * @param _to The address to transfer to.
                                          * @param _value The amount to be transferred.
                                          * @param _data The extra data to be passed to the receiving contract.
                                          */
                                          function transferAndCall(address _to, uint _value, bytes _data)
                                            public
                                            returns (bool success)
                                          {
                                            super.transfer(_to, _value);
                                            Transfer(msg.sender, _to, _value, _data);
                                            if (isContract(_to)) {
                                              contractFallback(_to, _value, _data);
                                            }
                                            return true;
                                          }
                                        
                                        
                                          // PRIVATE
                                        
                                          function contractFallback(address _to, uint _value, bytes _data)
                                            private
                                          {
                                            ERC677Receiver receiver = ERC677Receiver(_to);
                                            receiver.onTokenTransfer(msg.sender, _value, _data);
                                          }
                                        
                                          function isContract(address _addr)
                                            private
                                            returns (bool hasCode)
                                          {
                                            uint length;
                                            assembly { length := extcodesize(_addr) }
                                            return length > 0;
                                          }
                                        
                                        }
                                        
                                        contract LinkToken is StandardToken, ERC677Token {
                                        
                                          uint public constant totalSupply = 10**27;
                                          string public constant name = 'ChainLink Token';
                                          uint8 public constant decimals = 18;
                                          string public constant symbol = 'LINK';
                                        
                                          function LinkToken()
                                            public
                                          {
                                            balances[msg.sender] = totalSupply;
                                          }
                                        
                                          /**
                                          * @dev transfer token to a specified address with additional data if the recipient is a contract.
                                          * @param _to The address to transfer to.
                                          * @param _value The amount to be transferred.
                                          * @param _data The extra data to be passed to the receiving contract.
                                          */
                                          function transferAndCall(address _to, uint _value, bytes _data)
                                            public
                                            validRecipient(_to)
                                            returns (bool success)
                                          {
                                            return super.transferAndCall(_to, _value, _data);
                                          }
                                        
                                          /**
                                          * @dev transfer token to a specified address.
                                          * @param _to The address to transfer to.
                                          * @param _value The amount to be transferred.
                                          */
                                          function transfer(address _to, uint _value)
                                            public
                                            validRecipient(_to)
                                            returns (bool success)
                                          {
                                            return super.transfer(_to, _value);
                                          }
                                        
                                          /**
                                           * @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender.
                                           * @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
                                            validRecipient(_spender)
                                            returns (bool)
                                          {
                                            return super.approve(_spender,  _value);
                                          }
                                        
                                          /**
                                           * @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
                                            validRecipient(_to)
                                            returns (bool)
                                          {
                                            return super.transferFrom(_from, _to, _value);
                                          }
                                        
                                        
                                          // MODIFIERS
                                        
                                          modifier validRecipient(address _recipient) {
                                            require(_recipient != address(0) && _recipient != address(this));
                                            _;
                                          }
                                        
                                        }

                                        File 3 of 9: Oracle
                                        /*                                                                                           
                                        *      ___ ___       ___         ___                                                             
                                        *      `MM `MMb     dMM'         `MM                                                             
                                        *       MM  MMM.   ,PMM           MM                                                             
                                        *   ____MM  M`Mb   d'MM    ___    MM   __   ____  ___  __   ____         _____  ___  __   __     
                                        *  6MMMMMM  M YM. ,P MM  6MMMMb   MM   d'  6MMMMb `MM 6MM  6MMMMb\      6MMMMMb `MM 6MM  6MMbMMM 
                                        * 6M'  `MM  M `Mb d' MM 8M'  `Mb  MM  d'  6M'  `Mb MM69 " MM'    `     6M'   `Mb MM69 " 6M'`Mb   
                                        * MM    MM  M  YM.P  MM     ,oMM  MM d'   MM    MM MM'    YM.          MM     MM MM'    MM  MM   
                                        * MM    MM  M  `Mb'  MM ,6MM9'MM  MMdM.   MMMMMMMM MM      YMMMMb      MM     MM MM     YM.,M9   
                                        * MM    MM  M   YP   MM MM'   MM  MMPYM.  MM       MM          `Mb     MM     MM MM      YMM9    
                                        * YM.  ,MM  M   `'   MM MM.  ,MM  MM  YM. YM    d9 MM     L    ,MM 68b YM.   ,M9 MM     (M       
                                        *  YMMMMMM__M_      _MM_`YMMM9'Yb_MM_  YM._YMMMM9 _MM_    MYMMMM9  Y89  YMMMMM9 _MM_     YMMMMb. 
                                        *                                                                                       6M    Yb 
                                        *                                                                                       YM.   d9 
                                        *                                                                                        YMMMM9  
                                        */
                                        
                                        pragma solidity 0.4.24;
                                        
                                        /**
                                         * @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 OwnershipRenounced(address indexed previousOwner);
                                          event OwnershipTransferred(
                                            address indexed previousOwner,
                                            address indexed newOwner
                                          );
                                        
                                        
                                          /**
                                           * @dev The Ownable constructor sets the original `owner` of the contract to the sender
                                           * account.
                                           */
                                          constructor() 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 relinquish control of the contract.
                                           * @notice Renouncing to ownership will leave the contract without an owner.
                                           * It will not be possible to call the functions with the `onlyOwner`
                                           * modifier anymore.
                                           */
                                          function renounceOwnership() public onlyOwner {
                                            emit OwnershipRenounced(owner);
                                            owner = address(0);
                                          }
                                        
                                          /**
                                           * @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 {
                                            _transferOwnership(_newOwner);
                                          }
                                        
                                          /**
                                           * @dev Transfers control of the contract to a newOwner.
                                           * @param _newOwner The address to transfer ownership to.
                                           */
                                          function _transferOwnership(address _newOwner) internal {
                                            require(_newOwner != address(0));
                                            emit OwnershipTransferred(owner, _newOwner);
                                            owner = _newOwner;
                                          }
                                        }
                                        
                                        // File: openzeppelin-solidity/contracts/math/SafeMath.sol
                                        
                                        pragma solidity ^0.4.24;
                                        
                                        
                                        /**
                                         * @title SafeMath
                                         * @dev Math operations with safety checks that throw on error
                                         */
                                        library SafeMath {
                                        
                                          /**
                                          * @dev Multiplies two numbers, throws on overflow.
                                          */
                                          function mul(uint256 _a, uint256 _b) internal pure returns (uint256 c) {
                                            // Gas optimization: this is cheaper than asserting 'a' not being zero, but the
                                            // benefit is lost if 'b' is also tested.
                                            // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
                                            if (_a == 0) {
                                              return 0;
                                            }
                                        
                                            c = _a * _b;
                                            assert(c / _a == _b);
                                            return c;
                                          }
                                        
                                          /**
                                          * @dev Integer division of two numbers, truncating the quotient.
                                          */
                                          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 _a / _b;
                                          }
                                        
                                          /**
                                          * @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend).
                                          */
                                          function sub(uint256 _a, uint256 _b) internal pure returns (uint256) {
                                            assert(_b <= _a);
                                            return _a - _b;
                                          }
                                        
                                          /**
                                          * @dev Adds two numbers, throws on overflow.
                                          */
                                          function add(uint256 _a, uint256 _b) internal pure returns (uint256 c) {
                                            c = _a + _b;
                                            assert(c >= _a);
                                            return c;
                                          }
                                        }
                                        
                                        // File: contracts/interfaces/ChainlinkRequestInterface.sol
                                        
                                        pragma solidity 0.4.24;
                                        
                                        interface ChainlinkRequestInterface {
                                          function oracleRequest(
                                            address sender,
                                            uint256 payment,
                                            bytes32 id,
                                            address callbackAddress,
                                            bytes4 callbackFunctionId,
                                            uint256 nonce,
                                            uint256 version,
                                            bytes data
                                          ) external;
                                        
                                          function cancelOracleRequest(
                                            bytes32 requestId,
                                            uint256 payment,
                                            bytes4 callbackFunctionId,
                                            uint256 expiration
                                          ) external;
                                        }
                                        
                                        // File: contracts/interfaces/OracleInterface.sol
                                        
                                        pragma solidity 0.4.24;
                                        
                                        interface OracleInterface {
                                          function fulfillOracleRequest(
                                            bytes32 requestId,
                                            uint256 payment,
                                            address callbackAddress,
                                            bytes4 callbackFunctionId,
                                            uint256 expiration,
                                            bytes32 data
                                          ) external returns (bool);
                                          function getAuthorizationStatus(address node) external view returns (bool);
                                          function setFulfillmentPermission(address node, bool allowed) external;
                                          function withdraw(address recipient, uint256 amount) external;
                                          function withdrawable() external view returns (uint256);
                                        }
                                        
                                        // File: contracts/interfaces/LinkTokenInterface.sol
                                        
                                        pragma solidity 0.4.24;
                                        
                                        interface LinkTokenInterface {
                                          function allowance(address owner, address spender) external returns (bool success);
                                          function approve(address spender, uint256 value) external returns (bool success);
                                          function balanceOf(address owner) external returns (uint256 balance);
                                          function decimals() external returns (uint8 decimalPlaces);
                                          function decreaseApproval(address spender, uint256 addedValue) external returns (bool success);
                                          function increaseApproval(address spender, uint256 subtractedValue) external;
                                          function name() external returns (string tokenName);
                                          function symbol() external returns (string tokenSymbol);
                                          function totalSupply() external returns (uint256 totalTokensIssued);
                                          function transfer(address to, uint256 value) external returns (bool success);
                                          function transferAndCall(address to, uint256 value, bytes data) external returns (bool success);
                                          function transferFrom(address from, address to, uint256 value) external returns (bool success);
                                        }
                                        
                                        // File: contracts/Oracle.sol
                                        
                                        pragma solidity 0.4.24;
                                        
                                        
                                        
                                        
                                        
                                        
                                        /**
                                         * @title The Chainlink Oracle contract
                                         * @notice Node operators can deploy this contract to fulfill requests sent to them
                                         */
                                        contract Oracle is ChainlinkRequestInterface, OracleInterface, Ownable {
                                          using SafeMath for uint256;
                                        
                                          uint256 constant public EXPIRY_TIME = 5 minutes;
                                          uint256 constant private MINIMUM_CONSUMER_GAS_LIMIT = 400000;
                                          // We initialize fields to 1 instead of 0 so that the first invocation
                                          // does not cost more gas.
                                          uint256 constant private ONE_FOR_CONSISTENT_GAS_COST = 1;
                                          uint256 constant private SELECTOR_LENGTH = 4;
                                          uint256 constant private EXPECTED_REQUEST_WORDS = 2;
                                          // solium-disable-next-line zeppelin/no-arithmetic-operations
                                          uint256 constant private MINIMUM_REQUEST_LENGTH = SELECTOR_LENGTH + (32 * EXPECTED_REQUEST_WORDS);
                                        
                                          LinkTokenInterface internal LinkToken;
                                          mapping(bytes32 => bytes32) private commitments;
                                          mapping(address => bool) private authorizedNodes;
                                          uint256 private withdrawableTokens = ONE_FOR_CONSISTENT_GAS_COST;
                                        
                                          event OracleRequest(
                                            bytes32 indexed specId,
                                            address requester,
                                            bytes32 requestId,
                                            uint256 payment,
                                            address callbackAddr,
                                            bytes4 callbackFunctionId,
                                            uint256 cancelExpiration,
                                            uint256 dataVersion,
                                            bytes data
                                          );
                                        
                                          event CancelOracleRequest(
                                            bytes32 indexed requestId
                                          );
                                        
                                          /**
                                           * @notice Deploy with the address of the LINK token
                                           * @dev Sets the LinkToken address for the imported LinkTokenInterface
                                           * @param _link The address of the LINK token
                                           */
                                          constructor(address _link) Ownable() public {
                                            LinkToken = LinkTokenInterface(_link);
                                          }
                                        
                                          /**
                                           * @notice Called when LINK is sent to the contract via `transferAndCall`
                                           * @dev The data payload's first 2 words will be overwritten by the `_sender` and `_amount`
                                           * values to ensure correctness. Calls oracleRequest.
                                           * @param _sender Address of the sender
                                           * @param _amount Amount of LINK sent (specified in wei)
                                           * @param _data Payload of the transaction
                                           */
                                          function onTokenTransfer(
                                            address _sender,
                                            uint256 _amount,
                                            bytes _data
                                          )
                                            public
                                            onlyLINK
                                            validRequestLength(_data)
                                            permittedFunctionsForLINK(_data)
                                          {
                                            assembly {
                                              // solium-disable-next-line security/no-low-level-calls
                                              mstore(add(_data, 36), _sender) // ensure correct sender is passed
                                              // solium-disable-next-line security/no-low-level-calls
                                              mstore(add(_data, 68), _amount)    // ensure correct amount is passed
                                            }
                                            // solium-disable-next-line security/no-low-level-calls
                                            require(address(this).delegatecall(_data), "Unable to create request"); // calls oracleRequest
                                          }
                                        
                                          /**
                                           * @notice Creates the Chainlink request
                                           * @dev Stores the hash of the params as the on-chain commitment for the request.
                                           * Emits OracleRequest event for the Chainlink node to detect.
                                           * @param _sender The sender of the request
                                           * @param _payment The amount of payment given (specified in wei)
                                           * @param _specId The Job Specification ID
                                           * @param _callbackAddress The callback address for the response
                                           * @param _callbackFunctionId The callback function ID for the response
                                           * @param _nonce The nonce sent by the requester
                                           * @param _dataVersion The specified data version
                                           * @param _data The CBOR payload of the request
                                           */
                                          function oracleRequest(
                                            address _sender,
                                            uint256 _payment,
                                            bytes32 _specId,
                                            address _callbackAddress,
                                            bytes4 _callbackFunctionId,
                                            uint256 _nonce,
                                            uint256 _dataVersion,
                                            bytes _data
                                          )
                                            external
                                            onlyLINK
                                            checkCallbackAddress(_callbackAddress)
                                          {
                                            bytes32 requestId = keccak256(abi.encodePacked(_sender, _nonce));
                                            require(commitments[requestId] == 0, "Must use a unique ID");
                                            uint256 expiration = now.add(EXPIRY_TIME);
                                        
                                            commitments[requestId] = keccak256(
                                              abi.encodePacked(
                                                _payment,
                                                _callbackAddress,
                                                _callbackFunctionId,
                                                expiration
                                              )
                                            );
                                        
                                            emit OracleRequest(
                                              _specId,
                                              _sender,
                                              requestId,
                                              _payment,
                                              _callbackAddress,
                                              _callbackFunctionId,
                                              expiration,
                                              _dataVersion,
                                              _data);
                                          }
                                        
                                          /**
                                           * @notice Called by the Chainlink node to fulfill requests
                                           * @dev Given params must hash back to the commitment stored from `oracleRequest`.
                                           * Will call the callback address' callback function without bubbling up error
                                           * checking in a `require` so that the node can get paid.
                                           * @param _requestId The fulfillment request ID that must match the requester's
                                           * @param _payment The payment amount that will be released for the oracle (specified in wei)
                                           * @param _callbackAddress The callback address to call for fulfillment
                                           * @param _callbackFunctionId The callback function ID to use for fulfillment
                                           * @param _expiration The expiration that the node should respond by before the requester can cancel
                                           * @param _data The data to return to the consuming contract
                                           * @return Status if the external call was successful
                                           */
                                          function fulfillOracleRequest(
                                            bytes32 _requestId,
                                            uint256 _payment,
                                            address _callbackAddress,
                                            bytes4 _callbackFunctionId,
                                            uint256 _expiration,
                                            bytes32 _data
                                          )
                                            external
                                            onlyAuthorizedNode
                                            isValidRequest(_requestId)
                                            returns (bool)
                                          {
                                            bytes32 paramsHash = keccak256(
                                              abi.encodePacked(
                                                _payment,
                                                _callbackAddress,
                                                _callbackFunctionId,
                                                _expiration
                                              )
                                            );
                                            require(commitments[_requestId] == paramsHash, "Params do not match request ID");
                                            withdrawableTokens = withdrawableTokens.add(_payment);
                                            delete commitments[_requestId];
                                            require(gasleft() >= MINIMUM_CONSUMER_GAS_LIMIT, "Must provide consumer enough gas");
                                            // All updates to the oracle's fulfillment should come before calling the
                                            // callback(addr+functionId) as it is untrusted.
                                            // See: https://solidity.readthedocs.io/en/develop/security-considerations.html#use-the-checks-effects-interactions-pattern
                                            return _callbackAddress.call(_callbackFunctionId, _requestId, _data); // solium-disable-line security/no-low-level-calls
                                          }
                                        
                                          /**
                                           * @notice Use this to check if a node is authorized for fulfilling requests
                                           * @param _node The address of the Chainlink node
                                           * @return The authorization status of the node
                                           */
                                          function getAuthorizationStatus(address _node) external view returns (bool) {
                                            return authorizedNodes[_node];
                                          }
                                        
                                          /**
                                           * @notice Sets the fulfillment permission for a given node. Use `true` to allow, `false` to disallow.
                                           * @param _node The address of the Chainlink node
                                           * @param _allowed Bool value to determine if the node can fulfill requests
                                           */
                                          function setFulfillmentPermission(address _node, bool _allowed) external onlyOwner {
                                            authorizedNodes[_node] = _allowed;
                                          }
                                        
                                          /**
                                           * @notice Allows the node operator to withdraw earned LINK to a given address
                                           * @dev The owner of the contract can be another wallet and does not have to be a Chainlink node
                                           * @param _recipient The address to send the LINK token to
                                           * @param _amount The amount to send (specified in wei)
                                           */
                                          function withdraw(address _recipient, uint256 _amount)
                                            external
                                            onlyOwner
                                            hasAvailableFunds(_amount)
                                          {
                                            withdrawableTokens = withdrawableTokens.sub(_amount);
                                            assert(LinkToken.transfer(_recipient, _amount));
                                          }
                                        
                                          /**
                                           * @notice Displays the amount of LINK that is available for the node operator to withdraw
                                           * @dev We use `ONE_FOR_CONSISTENT_GAS_COST` in place of 0 in storage
                                           * @return The amount of withdrawable LINK on the contract
                                           */
                                          function withdrawable() external view onlyOwner returns (uint256) {
                                            return withdrawableTokens.sub(ONE_FOR_CONSISTENT_GAS_COST);
                                          }
                                        
                                          /**
                                           * @notice Allows requesters to cancel requests sent to this oracle contract. Will transfer the LINK
                                           * sent for the request back to the requester's address.
                                           * @dev Given params must hash to a commitment stored on the contract in order for the request to be valid
                                           * Emits CancelOracleRequest event.
                                           * @param _requestId The request ID
                                           * @param _payment The amount of payment given (specified in wei)
                                           * @param _callbackFunc The requester's specified callback address
                                           * @param _expiration The time of the expiration for the request
                                           */
                                          function cancelOracleRequest(
                                            bytes32 _requestId,
                                            uint256 _payment,
                                            bytes4 _callbackFunc,
                                            uint256 _expiration
                                          ) external {
                                            bytes32 paramsHash = keccak256(
                                              abi.encodePacked(
                                                _payment,
                                                msg.sender,
                                                _callbackFunc,
                                                _expiration)
                                            );
                                            require(paramsHash == commitments[_requestId], "Params do not match request ID");
                                            require(_expiration <= now, "Request is not expired");
                                        
                                            delete commitments[_requestId];
                                            emit CancelOracleRequest(_requestId);
                                        
                                            assert(LinkToken.transfer(msg.sender, _payment));
                                          }
                                        
                                          // MODIFIERS
                                        
                                          /**
                                           * @dev Reverts if amount requested is greater than withdrawable balance
                                           * @param _amount The given amount to compare to `withdrawableTokens`
                                           */
                                          modifier hasAvailableFunds(uint256 _amount) {
                                            require(withdrawableTokens >= _amount.add(ONE_FOR_CONSISTENT_GAS_COST), "Amount requested is greater than withdrawable balance");
                                            _;
                                          }
                                        
                                          /**
                                           * @dev Reverts if request ID does not exist
                                           * @param _requestId The given request ID to check in stored `commitments`
                                           */
                                          modifier isValidRequest(bytes32 _requestId) {
                                            require(commitments[_requestId] != 0, "Must have a valid requestId");
                                            _;
                                          }
                                        
                                          /**
                                           * @dev Reverts if `msg.sender` is not authorized to fulfill requests
                                           */
                                          modifier onlyAuthorizedNode() {
                                            require(authorizedNodes[msg.sender] || msg.sender == owner, "Not an authorized node to fulfill requests");
                                            _;
                                          }
                                        
                                          /**
                                           * @dev Reverts if not sent from the LINK token
                                           */
                                          modifier onlyLINK() {
                                            require(msg.sender == address(LinkToken), "Must use LINK token");
                                            _;
                                          }
                                        
                                          /**
                                           * @dev Reverts if the given data does not begin with the `oracleRequest` function selector
                                           * @param _data The data payload of the request
                                           */
                                          modifier permittedFunctionsForLINK(bytes _data) {
                                            bytes4 funcSelector;
                                            assembly {
                                              // solium-disable-next-line security/no-low-level-calls
                                              funcSelector := mload(add(_data, 32))
                                            }
                                            require(funcSelector == this.oracleRequest.selector, "Must use whitelisted functions");
                                            _;
                                          }
                                        
                                          /**
                                           * @dev Reverts if the callback address is the LINK token
                                           * @param _to The callback address
                                           */
                                          modifier checkCallbackAddress(address _to) {
                                            require(_to != address(LinkToken), "Cannot callback to LINK");
                                            _;
                                          }
                                        
                                          /**
                                           * @dev Reverts if the given payload is less than needed to create a request
                                           * @param _data The request payload
                                           */
                                          modifier validRequestLength(bytes _data) {
                                            require(_data.length >= MINIMUM_REQUEST_LENGTH, "Invalid request length");
                                            _;
                                          }
                                        
                                        }

                                        File 4 of 9: Oracle
                                        /*                                                                                           
                                        *      ___ ___       ___         ___                                                             
                                        *      `MM `MMb     dMM'         `MM                                                             
                                        *       MM  MMM.   ,PMM           MM                                                             
                                        *   ____MM  M`Mb   d'MM    ___    MM   __   ____  ___  __   ____         _____  ___  __   __     
                                        *  6MMMMMM  M YM. ,P MM  6MMMMb   MM   d'  6MMMMb `MM 6MM  6MMMMb\      6MMMMMb `MM 6MM  6MMbMMM 
                                        * 6M'  `MM  M `Mb d' MM 8M'  `Mb  MM  d'  6M'  `Mb MM69 " MM'    `     6M'   `Mb MM69 " 6M'`Mb   
                                        * MM    MM  M  YM.P  MM     ,oMM  MM d'   MM    MM MM'    YM.          MM     MM MM'    MM  MM   
                                        * MM    MM  M  `Mb'  MM ,6MM9'MM  MMdM.   MMMMMMMM MM      YMMMMb      MM     MM MM     YM.,M9   
                                        * MM    MM  M   YP   MM MM'   MM  MMPYM.  MM       MM          `Mb     MM     MM MM      YMM9    
                                        * YM.  ,MM  M   `'   MM MM.  ,MM  MM  YM. YM    d9 MM     L    ,MM 68b YM.   ,M9 MM     (M       
                                        *  YMMMMMM__M_      _MM_`YMMM9'Yb_MM_  YM._YMMMM9 _MM_    MYMMMM9  Y89  YMMMMM9 _MM_     YMMMMb. 
                                        *                                                                                       6M    Yb 
                                        *                                                                                       YM.   d9 
                                        *                                                                                        YMMMM9  
                                        */
                                        
                                        pragma solidity 0.4.24;
                                        
                                        /**
                                         * @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 OwnershipRenounced(address indexed previousOwner);
                                          event OwnershipTransferred(
                                            address indexed previousOwner,
                                            address indexed newOwner
                                          );
                                        
                                        
                                          /**
                                           * @dev The Ownable constructor sets the original `owner` of the contract to the sender
                                           * account.
                                           */
                                          constructor() 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 relinquish control of the contract.
                                           * @notice Renouncing to ownership will leave the contract without an owner.
                                           * It will not be possible to call the functions with the `onlyOwner`
                                           * modifier anymore.
                                           */
                                          function renounceOwnership() public onlyOwner {
                                            emit OwnershipRenounced(owner);
                                            owner = address(0);
                                          }
                                        
                                          /**
                                           * @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 {
                                            _transferOwnership(_newOwner);
                                          }
                                        
                                          /**
                                           * @dev Transfers control of the contract to a newOwner.
                                           * @param _newOwner The address to transfer ownership to.
                                           */
                                          function _transferOwnership(address _newOwner) internal {
                                            require(_newOwner != address(0));
                                            emit OwnershipTransferred(owner, _newOwner);
                                            owner = _newOwner;
                                          }
                                        }
                                        
                                        // File: openzeppelin-solidity/contracts/math/SafeMath.sol
                                        
                                        pragma solidity ^0.4.24;
                                        
                                        
                                        /**
                                         * @title SafeMath
                                         * @dev Math operations with safety checks that throw on error
                                         */
                                        library SafeMath {
                                        
                                          /**
                                          * @dev Multiplies two numbers, throws on overflow.
                                          */
                                          function mul(uint256 _a, uint256 _b) internal pure returns (uint256 c) {
                                            // Gas optimization: this is cheaper than asserting 'a' not being zero, but the
                                            // benefit is lost if 'b' is also tested.
                                            // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
                                            if (_a == 0) {
                                              return 0;
                                            }
                                        
                                            c = _a * _b;
                                            assert(c / _a == _b);
                                            return c;
                                          }
                                        
                                          /**
                                          * @dev Integer division of two numbers, truncating the quotient.
                                          */
                                          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 _a / _b;
                                          }
                                        
                                          /**
                                          * @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend).
                                          */
                                          function sub(uint256 _a, uint256 _b) internal pure returns (uint256) {
                                            assert(_b <= _a);
                                            return _a - _b;
                                          }
                                        
                                          /**
                                          * @dev Adds two numbers, throws on overflow.
                                          */
                                          function add(uint256 _a, uint256 _b) internal pure returns (uint256 c) {
                                            c = _a + _b;
                                            assert(c >= _a);
                                            return c;
                                          }
                                        }
                                        
                                        // File: contracts/interfaces/ChainlinkRequestInterface.sol
                                        
                                        pragma solidity 0.4.24;
                                        
                                        interface ChainlinkRequestInterface {
                                          function oracleRequest(
                                            address sender,
                                            uint256 payment,
                                            bytes32 id,
                                            address callbackAddress,
                                            bytes4 callbackFunctionId,
                                            uint256 nonce,
                                            uint256 version,
                                            bytes data
                                          ) external;
                                        
                                          function cancelOracleRequest(
                                            bytes32 requestId,
                                            uint256 payment,
                                            bytes4 callbackFunctionId,
                                            uint256 expiration
                                          ) external;
                                        }
                                        
                                        // File: contracts/interfaces/OracleInterface.sol
                                        
                                        pragma solidity 0.4.24;
                                        
                                        interface OracleInterface {
                                          function fulfillOracleRequest(
                                            bytes32 requestId,
                                            uint256 payment,
                                            address callbackAddress,
                                            bytes4 callbackFunctionId,
                                            uint256 expiration,
                                            bytes32 data
                                          ) external returns (bool);
                                          function getAuthorizationStatus(address node) external view returns (bool);
                                          function setFulfillmentPermission(address node, bool allowed) external;
                                          function withdraw(address recipient, uint256 amount) external;
                                          function withdrawable() external view returns (uint256);
                                        }
                                        
                                        // File: contracts/interfaces/LinkTokenInterface.sol
                                        
                                        pragma solidity 0.4.24;
                                        
                                        interface LinkTokenInterface {
                                          function allowance(address owner, address spender) external returns (bool success);
                                          function approve(address spender, uint256 value) external returns (bool success);
                                          function balanceOf(address owner) external returns (uint256 balance);
                                          function decimals() external returns (uint8 decimalPlaces);
                                          function decreaseApproval(address spender, uint256 addedValue) external returns (bool success);
                                          function increaseApproval(address spender, uint256 subtractedValue) external;
                                          function name() external returns (string tokenName);
                                          function symbol() external returns (string tokenSymbol);
                                          function totalSupply() external returns (uint256 totalTokensIssued);
                                          function transfer(address to, uint256 value) external returns (bool success);
                                          function transferAndCall(address to, uint256 value, bytes data) external returns (bool success);
                                          function transferFrom(address from, address to, uint256 value) external returns (bool success);
                                        }
                                        
                                        // File: contracts/Oracle.sol
                                        
                                        pragma solidity 0.4.24;
                                        
                                        
                                        
                                        
                                        
                                        
                                        /**
                                         * @title The Chainlink Oracle contract
                                         * @notice Node operators can deploy this contract to fulfill requests sent to them
                                         */
                                        contract Oracle is ChainlinkRequestInterface, OracleInterface, Ownable {
                                          using SafeMath for uint256;
                                        
                                          uint256 constant public EXPIRY_TIME = 5 minutes;
                                          uint256 constant private MINIMUM_CONSUMER_GAS_LIMIT = 400000;
                                          // We initialize fields to 1 instead of 0 so that the first invocation
                                          // does not cost more gas.
                                          uint256 constant private ONE_FOR_CONSISTENT_GAS_COST = 1;
                                          uint256 constant private SELECTOR_LENGTH = 4;
                                          uint256 constant private EXPECTED_REQUEST_WORDS = 2;
                                          // solium-disable-next-line zeppelin/no-arithmetic-operations
                                          uint256 constant private MINIMUM_REQUEST_LENGTH = SELECTOR_LENGTH + (32 * EXPECTED_REQUEST_WORDS);
                                        
                                          LinkTokenInterface internal LinkToken;
                                          mapping(bytes32 => bytes32) private commitments;
                                          mapping(address => bool) private authorizedNodes;
                                          uint256 private withdrawableTokens = ONE_FOR_CONSISTENT_GAS_COST;
                                        
                                          event OracleRequest(
                                            bytes32 indexed specId,
                                            address requester,
                                            bytes32 requestId,
                                            uint256 payment,
                                            address callbackAddr,
                                            bytes4 callbackFunctionId,
                                            uint256 cancelExpiration,
                                            uint256 dataVersion,
                                            bytes data
                                          );
                                        
                                          event CancelOracleRequest(
                                            bytes32 indexed requestId
                                          );
                                        
                                          /**
                                           * @notice Deploy with the address of the LINK token
                                           * @dev Sets the LinkToken address for the imported LinkTokenInterface
                                           * @param _link The address of the LINK token
                                           */
                                          constructor(address _link) Ownable() public {
                                            LinkToken = LinkTokenInterface(_link);
                                          }
                                        
                                          /**
                                           * @notice Called when LINK is sent to the contract via `transferAndCall`
                                           * @dev The data payload's first 2 words will be overwritten by the `_sender` and `_amount`
                                           * values to ensure correctness. Calls oracleRequest.
                                           * @param _sender Address of the sender
                                           * @param _amount Amount of LINK sent (specified in wei)
                                           * @param _data Payload of the transaction
                                           */
                                          function onTokenTransfer(
                                            address _sender,
                                            uint256 _amount,
                                            bytes _data
                                          )
                                            public
                                            onlyLINK
                                            validRequestLength(_data)
                                            permittedFunctionsForLINK(_data)
                                          {
                                            assembly {
                                              // solium-disable-next-line security/no-low-level-calls
                                              mstore(add(_data, 36), _sender) // ensure correct sender is passed
                                              // solium-disable-next-line security/no-low-level-calls
                                              mstore(add(_data, 68), _amount)    // ensure correct amount is passed
                                            }
                                            // solium-disable-next-line security/no-low-level-calls
                                            require(address(this).delegatecall(_data), "Unable to create request"); // calls oracleRequest
                                          }
                                        
                                          /**
                                           * @notice Creates the Chainlink request
                                           * @dev Stores the hash of the params as the on-chain commitment for the request.
                                           * Emits OracleRequest event for the Chainlink node to detect.
                                           * @param _sender The sender of the request
                                           * @param _payment The amount of payment given (specified in wei)
                                           * @param _specId The Job Specification ID
                                           * @param _callbackAddress The callback address for the response
                                           * @param _callbackFunctionId The callback function ID for the response
                                           * @param _nonce The nonce sent by the requester
                                           * @param _dataVersion The specified data version
                                           * @param _data The CBOR payload of the request
                                           */
                                          function oracleRequest(
                                            address _sender,
                                            uint256 _payment,
                                            bytes32 _specId,
                                            address _callbackAddress,
                                            bytes4 _callbackFunctionId,
                                            uint256 _nonce,
                                            uint256 _dataVersion,
                                            bytes _data
                                          )
                                            external
                                            onlyLINK
                                            checkCallbackAddress(_callbackAddress)
                                          {
                                            bytes32 requestId = keccak256(abi.encodePacked(_sender, _nonce));
                                            require(commitments[requestId] == 0, "Must use a unique ID");
                                            uint256 expiration = now.add(EXPIRY_TIME);
                                        
                                            commitments[requestId] = keccak256(
                                              abi.encodePacked(
                                                _payment,
                                                _callbackAddress,
                                                _callbackFunctionId,
                                                expiration
                                              )
                                            );
                                        
                                            emit OracleRequest(
                                              _specId,
                                              _sender,
                                              requestId,
                                              _payment,
                                              _callbackAddress,
                                              _callbackFunctionId,
                                              expiration,
                                              _dataVersion,
                                              _data);
                                          }
                                        
                                          /**
                                           * @notice Called by the Chainlink node to fulfill requests
                                           * @dev Given params must hash back to the commitment stored from `oracleRequest`.
                                           * Will call the callback address' callback function without bubbling up error
                                           * checking in a `require` so that the node can get paid.
                                           * @param _requestId The fulfillment request ID that must match the requester's
                                           * @param _payment The payment amount that will be released for the oracle (specified in wei)
                                           * @param _callbackAddress The callback address to call for fulfillment
                                           * @param _callbackFunctionId The callback function ID to use for fulfillment
                                           * @param _expiration The expiration that the node should respond by before the requester can cancel
                                           * @param _data The data to return to the consuming contract
                                           * @return Status if the external call was successful
                                           */
                                          function fulfillOracleRequest(
                                            bytes32 _requestId,
                                            uint256 _payment,
                                            address _callbackAddress,
                                            bytes4 _callbackFunctionId,
                                            uint256 _expiration,
                                            bytes32 _data
                                          )
                                            external
                                            onlyAuthorizedNode
                                            isValidRequest(_requestId)
                                            returns (bool)
                                          {
                                            bytes32 paramsHash = keccak256(
                                              abi.encodePacked(
                                                _payment,
                                                _callbackAddress,
                                                _callbackFunctionId,
                                                _expiration
                                              )
                                            );
                                            require(commitments[_requestId] == paramsHash, "Params do not match request ID");
                                            withdrawableTokens = withdrawableTokens.add(_payment);
                                            delete commitments[_requestId];
                                            require(gasleft() >= MINIMUM_CONSUMER_GAS_LIMIT, "Must provide consumer enough gas");
                                            // All updates to the oracle's fulfillment should come before calling the
                                            // callback(addr+functionId) as it is untrusted.
                                            // See: https://solidity.readthedocs.io/en/develop/security-considerations.html#use-the-checks-effects-interactions-pattern
                                            return _callbackAddress.call(_callbackFunctionId, _requestId, _data); // solium-disable-line security/no-low-level-calls
                                          }
                                        
                                          /**
                                           * @notice Use this to check if a node is authorized for fulfilling requests
                                           * @param _node The address of the Chainlink node
                                           * @return The authorization status of the node
                                           */
                                          function getAuthorizationStatus(address _node) external view returns (bool) {
                                            return authorizedNodes[_node];
                                          }
                                        
                                          /**
                                           * @notice Sets the fulfillment permission for a given node. Use `true` to allow, `false` to disallow.
                                           * @param _node The address of the Chainlink node
                                           * @param _allowed Bool value to determine if the node can fulfill requests
                                           */
                                          function setFulfillmentPermission(address _node, bool _allowed) external onlyOwner {
                                            authorizedNodes[_node] = _allowed;
                                          }
                                        
                                          /**
                                           * @notice Allows the node operator to withdraw earned LINK to a given address
                                           * @dev The owner of the contract can be another wallet and does not have to be a Chainlink node
                                           * @param _recipient The address to send the LINK token to
                                           * @param _amount The amount to send (specified in wei)
                                           */
                                          function withdraw(address _recipient, uint256 _amount)
                                            external
                                            onlyOwner
                                            hasAvailableFunds(_amount)
                                          {
                                            withdrawableTokens = withdrawableTokens.sub(_amount);
                                            assert(LinkToken.transfer(_recipient, _amount));
                                          }
                                        
                                          /**
                                           * @notice Displays the amount of LINK that is available for the node operator to withdraw
                                           * @dev We use `ONE_FOR_CONSISTENT_GAS_COST` in place of 0 in storage
                                           * @return The amount of withdrawable LINK on the contract
                                           */
                                          function withdrawable() external view onlyOwner returns (uint256) {
                                            return withdrawableTokens.sub(ONE_FOR_CONSISTENT_GAS_COST);
                                          }
                                        
                                          /**
                                           * @notice Allows requesters to cancel requests sent to this oracle contract. Will transfer the LINK
                                           * sent for the request back to the requester's address.
                                           * @dev Given params must hash to a commitment stored on the contract in order for the request to be valid
                                           * Emits CancelOracleRequest event.
                                           * @param _requestId The request ID
                                           * @param _payment The amount of payment given (specified in wei)
                                           * @param _callbackFunc The requester's specified callback address
                                           * @param _expiration The time of the expiration for the request
                                           */
                                          function cancelOracleRequest(
                                            bytes32 _requestId,
                                            uint256 _payment,
                                            bytes4 _callbackFunc,
                                            uint256 _expiration
                                          ) external {
                                            bytes32 paramsHash = keccak256(
                                              abi.encodePacked(
                                                _payment,
                                                msg.sender,
                                                _callbackFunc,
                                                _expiration)
                                            );
                                            require(paramsHash == commitments[_requestId], "Params do not match request ID");
                                            require(_expiration <= now, "Request is not expired");
                                        
                                            delete commitments[_requestId];
                                            emit CancelOracleRequest(_requestId);
                                        
                                            assert(LinkToken.transfer(msg.sender, _payment));
                                          }
                                        
                                          // MODIFIERS
                                        
                                          /**
                                           * @dev Reverts if amount requested is greater than withdrawable balance
                                           * @param _amount The given amount to compare to `withdrawableTokens`
                                           */
                                          modifier hasAvailableFunds(uint256 _amount) {
                                            require(withdrawableTokens >= _amount.add(ONE_FOR_CONSISTENT_GAS_COST), "Amount requested is greater than withdrawable balance");
                                            _;
                                          }
                                        
                                          /**
                                           * @dev Reverts if request ID does not exist
                                           * @param _requestId The given request ID to check in stored `commitments`
                                           */
                                          modifier isValidRequest(bytes32 _requestId) {
                                            require(commitments[_requestId] != 0, "Must have a valid requestId");
                                            _;
                                          }
                                        
                                          /**
                                           * @dev Reverts if `msg.sender` is not authorized to fulfill requests
                                           */
                                          modifier onlyAuthorizedNode() {
                                            require(authorizedNodes[msg.sender] || msg.sender == owner, "Not an authorized node to fulfill requests");
                                            _;
                                          }
                                        
                                          /**
                                           * @dev Reverts if not sent from the LINK token
                                           */
                                          modifier onlyLINK() {
                                            require(msg.sender == address(LinkToken), "Must use LINK token");
                                            _;
                                          }
                                        
                                          /**
                                           * @dev Reverts if the given data does not begin with the `oracleRequest` function selector
                                           * @param _data The data payload of the request
                                           */
                                          modifier permittedFunctionsForLINK(bytes _data) {
                                            bytes4 funcSelector;
                                            assembly {
                                              // solium-disable-next-line security/no-low-level-calls
                                              funcSelector := mload(add(_data, 32))
                                            }
                                            require(funcSelector == this.oracleRequest.selector, "Must use whitelisted functions");
                                            _;
                                          }
                                        
                                          /**
                                           * @dev Reverts if the callback address is the LINK token
                                           * @param _to The callback address
                                           */
                                          modifier checkCallbackAddress(address _to) {
                                            require(_to != address(LinkToken), "Cannot callback to LINK");
                                            _;
                                          }
                                        
                                          /**
                                           * @dev Reverts if the given payload is less than needed to create a request
                                           * @param _data The request payload
                                           */
                                          modifier validRequestLength(bytes _data) {
                                            require(_data.length >= MINIMUM_REQUEST_LENGTH, "Invalid request length");
                                            _;
                                          }
                                        
                                        }

                                        File 5 of 9: Oracle
                                        // File: openzeppelin-solidity/contracts/ownership/Ownable.sol
                                        
                                        pragma solidity ^0.4.24;
                                        
                                        
                                        /**
                                         * @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 OwnershipRenounced(address indexed previousOwner);
                                          event OwnershipTransferred(
                                            address indexed previousOwner,
                                            address indexed newOwner
                                          );
                                        
                                        
                                          /**
                                           * @dev The Ownable constructor sets the original `owner` of the contract to the sender
                                           * account.
                                           */
                                          constructor() 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 relinquish control of the contract.
                                           * @notice Renouncing to ownership will leave the contract without an owner.
                                           * It will not be possible to call the functions with the `onlyOwner`
                                           * modifier anymore.
                                           */
                                          function renounceOwnership() public onlyOwner {
                                            emit OwnershipRenounced(owner);
                                            owner = address(0);
                                          }
                                        
                                          /**
                                           * @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 {
                                            _transferOwnership(_newOwner);
                                          }
                                        
                                          /**
                                           * @dev Transfers control of the contract to a newOwner.
                                           * @param _newOwner The address to transfer ownership to.
                                           */
                                          function _transferOwnership(address _newOwner) internal {
                                            require(_newOwner != address(0));
                                            emit OwnershipTransferred(owner, _newOwner);
                                            owner = _newOwner;
                                          }
                                        }
                                        
                                        // File: openzeppelin-solidity/contracts/math/SafeMath.sol
                                        
                                        pragma solidity ^0.4.24;
                                        
                                        
                                        /**
                                         * @title SafeMath
                                         * @dev Math operations with safety checks that throw on error
                                         */
                                        library SafeMath {
                                        
                                          /**
                                          * @dev Multiplies two numbers, throws on overflow.
                                          */
                                          function mul(uint256 _a, uint256 _b) internal pure returns (uint256 c) {
                                            // Gas optimization: this is cheaper than asserting 'a' not being zero, but the
                                            // benefit is lost if 'b' is also tested.
                                            // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
                                            if (_a == 0) {
                                              return 0;
                                            }
                                        
                                            c = _a * _b;
                                            assert(c / _a == _b);
                                            return c;
                                          }
                                        
                                          /**
                                          * @dev Integer division of two numbers, truncating the quotient.
                                          */
                                          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 _a / _b;
                                          }
                                        
                                          /**
                                          * @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend).
                                          */
                                          function sub(uint256 _a, uint256 _b) internal pure returns (uint256) {
                                            assert(_b <= _a);
                                            return _a - _b;
                                          }
                                        
                                          /**
                                          * @dev Adds two numbers, throws on overflow.
                                          */
                                          function add(uint256 _a, uint256 _b) internal pure returns (uint256 c) {
                                            c = _a + _b;
                                            assert(c >= _a);
                                            return c;
                                          }
                                        }
                                        
                                        // File: contracts/interfaces/ChainlinkRequestInterface.sol
                                        
                                        pragma solidity 0.4.24;
                                        
                                        interface ChainlinkRequestInterface {
                                          function oracleRequest(
                                            address sender,
                                            uint256 payment,
                                            bytes32 id,
                                            address callbackAddress,
                                            bytes4 callbackFunctionId,
                                            uint256 nonce,
                                            uint256 version,
                                            bytes data
                                          ) external;
                                        
                                          function cancelOracleRequest(
                                            bytes32 requestId,
                                            uint256 payment,
                                            bytes4 callbackFunctionId,
                                            uint256 expiration
                                          ) external;
                                        }
                                        
                                        // File: contracts/interfaces/OracleInterface.sol
                                        
                                        pragma solidity 0.4.24;
                                        
                                        interface OracleInterface {
                                          function fulfillOracleRequest(
                                            bytes32 requestId,
                                            uint256 payment,
                                            address callbackAddress,
                                            bytes4 callbackFunctionId,
                                            uint256 expiration,
                                            bytes32 data
                                          ) external returns (bool);
                                          function getAuthorizationStatus(address node) external view returns (bool);
                                          function setFulfillmentPermission(address node, bool allowed) external;
                                          function withdraw(address recipient, uint256 amount) external;
                                          function withdrawable() external view returns (uint256);
                                        }
                                        
                                        // File: contracts/interfaces/LinkTokenInterface.sol
                                        
                                        pragma solidity 0.4.24;
                                        
                                        interface LinkTokenInterface {
                                          function allowance(address owner, address spender) external returns (bool success);
                                          function approve(address spender, uint256 value) external returns (bool success);
                                          function balanceOf(address owner) external returns (uint256 balance);
                                          function decimals() external returns (uint8 decimalPlaces);
                                          function decreaseApproval(address spender, uint256 addedValue) external returns (bool success);
                                          function increaseApproval(address spender, uint256 subtractedValue) external;
                                          function name() external returns (string tokenName);
                                          function symbol() external returns (string tokenSymbol);
                                          function totalSupply() external returns (uint256 totalTokensIssued);
                                          function transfer(address to, uint256 value) external returns (bool success);
                                          function transferAndCall(address to, uint256 value, bytes data) external returns (bool success);
                                          function transferFrom(address from, address to, uint256 value) external returns (bool success);
                                        }
                                        
                                        // File: contracts/Oracle.sol
                                        
                                        pragma solidity 0.4.24;
                                        
                                        
                                        
                                        
                                        
                                        
                                        /**
                                         * @title The Chainlink Oracle contract
                                         * @notice Node operators can deploy this contract to fulfill requests sent to them
                                         */
                                        contract Oracle is ChainlinkRequestInterface, OracleInterface, Ownable {
                                          using SafeMath for uint256;
                                        
                                          uint256 constant public EXPIRY_TIME = 5 minutes;
                                          uint256 constant private MINIMUM_CONSUMER_GAS_LIMIT = 400000;
                                          // We initialize fields to 1 instead of 0 so that the first invocation
                                          // does not cost more gas.
                                          uint256 constant private ONE_FOR_CONSISTENT_GAS_COST = 1;
                                          uint256 constant private SELECTOR_LENGTH = 4;
                                          uint256 constant private EXPECTED_REQUEST_WORDS = 2;
                                          // solium-disable-next-line zeppelin/no-arithmetic-operations
                                          uint256 constant private MINIMUM_REQUEST_LENGTH = SELECTOR_LENGTH + (32 * EXPECTED_REQUEST_WORDS);
                                        
                                          LinkTokenInterface internal LinkToken;
                                          mapping(bytes32 => bytes32) private commitments;
                                          mapping(address => bool) private authorizedNodes;
                                          uint256 private withdrawableTokens = ONE_FOR_CONSISTENT_GAS_COST;
                                        
                                          event OracleRequest(
                                            bytes32 indexed specId,
                                            address requester,
                                            bytes32 requestId,
                                            uint256 payment,
                                            address callbackAddr,
                                            bytes4 callbackFunctionId,
                                            uint256 cancelExpiration,
                                            uint256 dataVersion,
                                            bytes data
                                          );
                                        
                                          event CancelOracleRequest(
                                            bytes32 indexed requestId
                                          );
                                        
                                          /**
                                           * @notice Deploy with the address of the LINK token
                                           * @dev Sets the LinkToken address for the imported LinkTokenInterface
                                           * @param _link The address of the LINK token
                                           */
                                          constructor(address _link) Ownable() public {
                                            LinkToken = LinkTokenInterface(_link);
                                          }
                                        
                                          /**
                                           * @notice Called when LINK is sent to the contract via `transferAndCall`
                                           * @dev The data payload's first 2 words will be overwritten by the `_sender` and `_amount`
                                           * values to ensure correctness. Calls oracleRequest.
                                           * @param _sender Address of the sender
                                           * @param _amount Amount of LINK sent (specified in wei)
                                           * @param _data Payload of the transaction
                                           */
                                          function onTokenTransfer(
                                            address _sender,
                                            uint256 _amount,
                                            bytes _data
                                          )
                                            public
                                            onlyLINK
                                            validRequestLength(_data)
                                            permittedFunctionsForLINK(_data)
                                          {
                                            assembly {
                                              // solium-disable-next-line security/no-low-level-calls
                                              mstore(add(_data, 36), _sender) // ensure correct sender is passed
                                              // solium-disable-next-line security/no-low-level-calls
                                              mstore(add(_data, 68), _amount)    // ensure correct amount is passed
                                            }
                                            // solium-disable-next-line security/no-low-level-calls
                                            require(address(this).delegatecall(_data), "Unable to create request"); // calls oracleRequest
                                          }
                                        
                                          /**
                                           * @notice Creates the Chainlink request
                                           * @dev Stores the hash of the params as the on-chain commitment for the request.
                                           * Emits OracleRequest event for the Chainlink node to detect.
                                           * @param _sender The sender of the request
                                           * @param _payment The amount of payment given (specified in wei)
                                           * @param _specId The Job Specification ID
                                           * @param _callbackAddress The callback address for the response
                                           * @param _callbackFunctionId The callback function ID for the response
                                           * @param _nonce The nonce sent by the requester
                                           * @param _dataVersion The specified data version
                                           * @param _data The CBOR payload of the request
                                           */
                                          function oracleRequest(
                                            address _sender,
                                            uint256 _payment,
                                            bytes32 _specId,
                                            address _callbackAddress,
                                            bytes4 _callbackFunctionId,
                                            uint256 _nonce,
                                            uint256 _dataVersion,
                                            bytes _data
                                          )
                                            external
                                            onlyLINK
                                            checkCallbackAddress(_callbackAddress)
                                          {
                                            bytes32 requestId = keccak256(abi.encodePacked(_sender, _nonce));
                                            require(commitments[requestId] == 0, "Must use a unique ID");
                                            uint256 expiration = now.add(EXPIRY_TIME);
                                        
                                            commitments[requestId] = keccak256(
                                              abi.encodePacked(
                                                _payment,
                                                _callbackAddress,
                                                _callbackFunctionId,
                                                expiration
                                              )
                                            );
                                        
                                            emit OracleRequest(
                                              _specId,
                                              _sender,
                                              requestId,
                                              _payment,
                                              _callbackAddress,
                                              _callbackFunctionId,
                                              expiration,
                                              _dataVersion,
                                              _data);
                                          }
                                        
                                          /**
                                           * @notice Called by the Chainlink node to fulfill requests
                                           * @dev Given params must hash back to the commitment stored from `oracleRequest`.
                                           * Will call the callback address' callback function without bubbling up error
                                           * checking in a `require` so that the node can get paid.
                                           * @param _requestId The fulfillment request ID that must match the requester's
                                           * @param _payment The payment amount that will be released for the oracle (specified in wei)
                                           * @param _callbackAddress The callback address to call for fulfillment
                                           * @param _callbackFunctionId The callback function ID to use for fulfillment
                                           * @param _expiration The expiration that the node should respond by before the requester can cancel
                                           * @param _data The data to return to the consuming contract
                                           * @return Status if the external call was successful
                                           */
                                          function fulfillOracleRequest(
                                            bytes32 _requestId,
                                            uint256 _payment,
                                            address _callbackAddress,
                                            bytes4 _callbackFunctionId,
                                            uint256 _expiration,
                                            bytes32 _data
                                          )
                                            external
                                            onlyAuthorizedNode
                                            isValidRequest(_requestId)
                                            returns (bool)
                                          {
                                            bytes32 paramsHash = keccak256(
                                              abi.encodePacked(
                                                _payment,
                                                _callbackAddress,
                                                _callbackFunctionId,
                                                _expiration
                                              )
                                            );
                                            require(commitments[_requestId] == paramsHash, "Params do not match request ID");
                                            withdrawableTokens = withdrawableTokens.add(_payment);
                                            delete commitments[_requestId];
                                            require(gasleft() >= MINIMUM_CONSUMER_GAS_LIMIT, "Must provide consumer enough gas");
                                            // All updates to the oracle's fulfillment should come before calling the
                                            // callback(addr+functionId) as it is untrusted.
                                            // See: https://solidity.readthedocs.io/en/develop/security-considerations.html#use-the-checks-effects-interactions-pattern
                                            return _callbackAddress.call(_callbackFunctionId, _requestId, _data); // solium-disable-line security/no-low-level-calls
                                          }
                                        
                                          /**
                                           * @notice Use this to check if a node is authorized for fulfilling requests
                                           * @param _node The address of the Chainlink node
                                           * @return The authorization status of the node
                                           */
                                          function getAuthorizationStatus(address _node) external view returns (bool) {
                                            return authorizedNodes[_node];
                                          }
                                        
                                          /**
                                           * @notice Sets the fulfillment permission for a given node. Use `true` to allow, `false` to disallow.
                                           * @param _node The address of the Chainlink node
                                           * @param _allowed Bool value to determine if the node can fulfill requests
                                           */
                                          function setFulfillmentPermission(address _node, bool _allowed) external onlyOwner {
                                            authorizedNodes[_node] = _allowed;
                                          }
                                        
                                          /**
                                           * @notice Allows the node operator to withdraw earned LINK to a given address
                                           * @dev The owner of the contract can be another wallet and does not have to be a Chainlink node
                                           * @param _recipient The address to send the LINK token to
                                           * @param _amount The amount to send (specified in wei)
                                           */
                                          function withdraw(address _recipient, uint256 _amount)
                                            external
                                            onlyOwner
                                            hasAvailableFunds(_amount)
                                          {
                                            withdrawableTokens = withdrawableTokens.sub(_amount);
                                            assert(LinkToken.transfer(_recipient, _amount));
                                          }
                                        
                                          /**
                                           * @notice Displays the amount of LINK that is available for the node operator to withdraw
                                           * @dev We use `ONE_FOR_CONSISTENT_GAS_COST` in place of 0 in storage
                                           * @return The amount of withdrawable LINK on the contract
                                           */
                                          function withdrawable() external view onlyOwner returns (uint256) {
                                            return withdrawableTokens.sub(ONE_FOR_CONSISTENT_GAS_COST);
                                          }
                                        
                                          /**
                                           * @notice Allows requesters to cancel requests sent to this oracle contract. Will transfer the LINK
                                           * sent for the request back to the requester's address.
                                           * @dev Given params must hash to a commitment stored on the contract in order for the request to be valid
                                           * Emits CancelOracleRequest event.
                                           * @param _requestId The request ID
                                           * @param _payment The amount of payment given (specified in wei)
                                           * @param _callbackFunc The requester's specified callback address
                                           * @param _expiration The time of the expiration for the request
                                           */
                                          function cancelOracleRequest(
                                            bytes32 _requestId,
                                            uint256 _payment,
                                            bytes4 _callbackFunc,
                                            uint256 _expiration
                                          ) external {
                                            bytes32 paramsHash = keccak256(
                                              abi.encodePacked(
                                                _payment,
                                                msg.sender,
                                                _callbackFunc,
                                                _expiration)
                                            );
                                            require(paramsHash == commitments[_requestId], "Params do not match request ID");
                                            require(_expiration <= now, "Request is not expired");
                                        
                                            delete commitments[_requestId];
                                            emit CancelOracleRequest(_requestId);
                                        
                                            assert(LinkToken.transfer(msg.sender, _payment));
                                          }
                                        
                                          // MODIFIERS
                                        
                                          /**
                                           * @dev Reverts if amount requested is greater than withdrawable balance
                                           * @param _amount The given amount to compare to `withdrawableTokens`
                                           */
                                          modifier hasAvailableFunds(uint256 _amount) {
                                            require(withdrawableTokens >= _amount.add(ONE_FOR_CONSISTENT_GAS_COST), "Amount requested is greater than withdrawable balance");
                                            _;
                                          }
                                        
                                          /**
                                           * @dev Reverts if request ID does not exist
                                           * @param _requestId The given request ID to check in stored `commitments`
                                           */
                                          modifier isValidRequest(bytes32 _requestId) {
                                            require(commitments[_requestId] != 0, "Must have a valid requestId");
                                            _;
                                          }
                                        
                                          /**
                                           * @dev Reverts if `msg.sender` is not authorized to fulfill requests
                                           */
                                          modifier onlyAuthorizedNode() {
                                            require(authorizedNodes[msg.sender] || msg.sender == owner, "Not an authorized node to fulfill requests");
                                            _;
                                          }
                                        
                                          /**
                                           * @dev Reverts if not sent from the LINK token
                                           */
                                          modifier onlyLINK() {
                                            require(msg.sender == address(LinkToken), "Must use LINK token");
                                            _;
                                          }
                                        
                                          /**
                                           * @dev Reverts if the given data does not begin with the `oracleRequest` function selector
                                           * @param _data The data payload of the request
                                           */
                                          modifier permittedFunctionsForLINK(bytes _data) {
                                            bytes4 funcSelector;
                                            assembly {
                                              // solium-disable-next-line security/no-low-level-calls
                                              funcSelector := mload(add(_data, 32))
                                            }
                                            require(funcSelector == this.oracleRequest.selector, "Must use whitelisted functions");
                                            _;
                                          }
                                        
                                          /**
                                           * @dev Reverts if the callback address is the LINK token
                                           * @param _to The callback address
                                           */
                                          modifier checkCallbackAddress(address _to) {
                                            require(_to != address(LinkToken), "Cannot callback to LINK");
                                            _;
                                          }
                                        
                                          /**
                                           * @dev Reverts if the given payload is less than needed to create a request
                                           * @param _data The request payload
                                           */
                                          modifier validRequestLength(bytes _data) {
                                            require(_data.length >= MINIMUM_REQUEST_LENGTH, "Invalid request length");
                                            _;
                                          }
                                        
                                        }

                                        File 6 of 9: Oracle
                                        /*                                                                                           
                                        *      ___ ___       ___         ___                                                             
                                        *      `MM `MMb     dMM'         `MM                                                             
                                        *       MM  MMM.   ,PMM           MM                                                             
                                        *   ____MM  M`Mb   d'MM    ___    MM   __   ____  ___  __   ____         _____  ___  __   __     
                                        *  6MMMMMM  M YM. ,P MM  6MMMMb   MM   d'  6MMMMb `MM 6MM  6MMMMb\      6MMMMMb `MM 6MM  6MMbMMM 
                                        * 6M'  `MM  M `Mb d' MM 8M'  `Mb  MM  d'  6M'  `Mb MM69 " MM'    `     6M'   `Mb MM69 " 6M'`Mb   
                                        * MM    MM  M  YM.P  MM     ,oMM  MM d'   MM    MM MM'    YM.          MM     MM MM'    MM  MM   
                                        * MM    MM  M  `Mb'  MM ,6MM9'MM  MMdM.   MMMMMMMM MM      YMMMMb      MM     MM MM     YM.,M9   
                                        * MM    MM  M   YP   MM MM'   MM  MMPYM.  MM       MM          `Mb     MM     MM MM      YMM9    
                                        * YM.  ,MM  M   `'   MM MM.  ,MM  MM  YM. YM    d9 MM     L    ,MM 68b YM.   ,M9 MM     (M       
                                        *  YMMMMMM__M_      _MM_`YMMM9'Yb_MM_  YM._YMMMM9 _MM_    MYMMMM9  Y89  YMMMMM9 _MM_     YMMMMb. 
                                        *                                                                                       6M    Yb 
                                        *                                                                                       YM.   d9 
                                        *                                                                                        YMMMM9  
                                        */
                                        
                                        pragma solidity 0.4.24;
                                        
                                        /**
                                         * @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 OwnershipRenounced(address indexed previousOwner);
                                          event OwnershipTransferred(
                                            address indexed previousOwner,
                                            address indexed newOwner
                                          );
                                        
                                        
                                          /**
                                           * @dev The Ownable constructor sets the original `owner` of the contract to the sender
                                           * account.
                                           */
                                          constructor() 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 relinquish control of the contract.
                                           * @notice Renouncing to ownership will leave the contract without an owner.
                                           * It will not be possible to call the functions with the `onlyOwner`
                                           * modifier anymore.
                                           */
                                          function renounceOwnership() public onlyOwner {
                                            emit OwnershipRenounced(owner);
                                            owner = address(0);
                                          }
                                        
                                          /**
                                           * @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 {
                                            _transferOwnership(_newOwner);
                                          }
                                        
                                          /**
                                           * @dev Transfers control of the contract to a newOwner.
                                           * @param _newOwner The address to transfer ownership to.
                                           */
                                          function _transferOwnership(address _newOwner) internal {
                                            require(_newOwner != address(0));
                                            emit OwnershipTransferred(owner, _newOwner);
                                            owner = _newOwner;
                                          }
                                        }
                                        
                                        // File: openzeppelin-solidity/contracts/math/SafeMath.sol
                                        
                                        pragma solidity ^0.4.24;
                                        
                                        
                                        /**
                                         * @title SafeMath
                                         * @dev Math operations with safety checks that throw on error
                                         */
                                        library SafeMath {
                                        
                                          /**
                                          * @dev Multiplies two numbers, throws on overflow.
                                          */
                                          function mul(uint256 _a, uint256 _b) internal pure returns (uint256 c) {
                                            // Gas optimization: this is cheaper than asserting 'a' not being zero, but the
                                            // benefit is lost if 'b' is also tested.
                                            // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
                                            if (_a == 0) {
                                              return 0;
                                            }
                                        
                                            c = _a * _b;
                                            assert(c / _a == _b);
                                            return c;
                                          }
                                        
                                          /**
                                          * @dev Integer division of two numbers, truncating the quotient.
                                          */
                                          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 _a / _b;
                                          }
                                        
                                          /**
                                          * @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend).
                                          */
                                          function sub(uint256 _a, uint256 _b) internal pure returns (uint256) {
                                            assert(_b <= _a);
                                            return _a - _b;
                                          }
                                        
                                          /**
                                          * @dev Adds two numbers, throws on overflow.
                                          */
                                          function add(uint256 _a, uint256 _b) internal pure returns (uint256 c) {
                                            c = _a + _b;
                                            assert(c >= _a);
                                            return c;
                                          }
                                        }
                                        
                                        // File: contracts/interfaces/ChainlinkRequestInterface.sol
                                        
                                        pragma solidity 0.4.24;
                                        
                                        interface ChainlinkRequestInterface {
                                          function oracleRequest(
                                            address sender,
                                            uint256 payment,
                                            bytes32 id,
                                            address callbackAddress,
                                            bytes4 callbackFunctionId,
                                            uint256 nonce,
                                            uint256 version,
                                            bytes data
                                          ) external;
                                        
                                          function cancelOracleRequest(
                                            bytes32 requestId,
                                            uint256 payment,
                                            bytes4 callbackFunctionId,
                                            uint256 expiration
                                          ) external;
                                        }
                                        
                                        // File: contracts/interfaces/OracleInterface.sol
                                        
                                        pragma solidity 0.4.24;
                                        
                                        interface OracleInterface {
                                          function fulfillOracleRequest(
                                            bytes32 requestId,
                                            uint256 payment,
                                            address callbackAddress,
                                            bytes4 callbackFunctionId,
                                            uint256 expiration,
                                            bytes32 data
                                          ) external returns (bool);
                                          function getAuthorizationStatus(address node) external view returns (bool);
                                          function setFulfillmentPermission(address node, bool allowed) external;
                                          function withdraw(address recipient, uint256 amount) external;
                                          function withdrawable() external view returns (uint256);
                                        }
                                        
                                        // File: contracts/interfaces/LinkTokenInterface.sol
                                        
                                        pragma solidity 0.4.24;
                                        
                                        interface LinkTokenInterface {
                                          function allowance(address owner, address spender) external returns (bool success);
                                          function approve(address spender, uint256 value) external returns (bool success);
                                          function balanceOf(address owner) external returns (uint256 balance);
                                          function decimals() external returns (uint8 decimalPlaces);
                                          function decreaseApproval(address spender, uint256 addedValue) external returns (bool success);
                                          function increaseApproval(address spender, uint256 subtractedValue) external;
                                          function name() external returns (string tokenName);
                                          function symbol() external returns (string tokenSymbol);
                                          function totalSupply() external returns (uint256 totalTokensIssued);
                                          function transfer(address to, uint256 value) external returns (bool success);
                                          function transferAndCall(address to, uint256 value, bytes data) external returns (bool success);
                                          function transferFrom(address from, address to, uint256 value) external returns (bool success);
                                        }
                                        
                                        // File: contracts/Oracle.sol
                                        
                                        pragma solidity 0.4.24;
                                        
                                        
                                        
                                        
                                        
                                        
                                        /**
                                         * @title The Chainlink Oracle contract
                                         * @notice Node operators can deploy this contract to fulfill requests sent to them
                                         */
                                        contract Oracle is ChainlinkRequestInterface, OracleInterface, Ownable {
                                          using SafeMath for uint256;
                                        
                                          uint256 constant public EXPIRY_TIME = 5 minutes;
                                          uint256 constant private MINIMUM_CONSUMER_GAS_LIMIT = 400000;
                                          // We initialize fields to 1 instead of 0 so that the first invocation
                                          // does not cost more gas.
                                          uint256 constant private ONE_FOR_CONSISTENT_GAS_COST = 1;
                                          uint256 constant private SELECTOR_LENGTH = 4;
                                          uint256 constant private EXPECTED_REQUEST_WORDS = 2;
                                          // solium-disable-next-line zeppelin/no-arithmetic-operations
                                          uint256 constant private MINIMUM_REQUEST_LENGTH = SELECTOR_LENGTH + (32 * EXPECTED_REQUEST_WORDS);
                                        
                                          LinkTokenInterface internal LinkToken;
                                          mapping(bytes32 => bytes32) private commitments;
                                          mapping(address => bool) private authorizedNodes;
                                          uint256 private withdrawableTokens = ONE_FOR_CONSISTENT_GAS_COST;
                                        
                                          event OracleRequest(
                                            bytes32 indexed specId,
                                            address requester,
                                            bytes32 requestId,
                                            uint256 payment,
                                            address callbackAddr,
                                            bytes4 callbackFunctionId,
                                            uint256 cancelExpiration,
                                            uint256 dataVersion,
                                            bytes data
                                          );
                                        
                                          event CancelOracleRequest(
                                            bytes32 indexed requestId
                                          );
                                        
                                          /**
                                           * @notice Deploy with the address of the LINK token
                                           * @dev Sets the LinkToken address for the imported LinkTokenInterface
                                           * @param _link The address of the LINK token
                                           */
                                          constructor(address _link) Ownable() public {
                                            LinkToken = LinkTokenInterface(_link);
                                          }
                                        
                                          /**
                                           * @notice Called when LINK is sent to the contract via `transferAndCall`
                                           * @dev The data payload's first 2 words will be overwritten by the `_sender` and `_amount`
                                           * values to ensure correctness. Calls oracleRequest.
                                           * @param _sender Address of the sender
                                           * @param _amount Amount of LINK sent (specified in wei)
                                           * @param _data Payload of the transaction
                                           */
                                          function onTokenTransfer(
                                            address _sender,
                                            uint256 _amount,
                                            bytes _data
                                          )
                                            public
                                            onlyLINK
                                            validRequestLength(_data)
                                            permittedFunctionsForLINK(_data)
                                          {
                                            assembly {
                                              // solium-disable-next-line security/no-low-level-calls
                                              mstore(add(_data, 36), _sender) // ensure correct sender is passed
                                              // solium-disable-next-line security/no-low-level-calls
                                              mstore(add(_data, 68), _amount)    // ensure correct amount is passed
                                            }
                                            // solium-disable-next-line security/no-low-level-calls
                                            require(address(this).delegatecall(_data), "Unable to create request"); // calls oracleRequest
                                          }
                                        
                                          /**
                                           * @notice Creates the Chainlink request
                                           * @dev Stores the hash of the params as the on-chain commitment for the request.
                                           * Emits OracleRequest event for the Chainlink node to detect.
                                           * @param _sender The sender of the request
                                           * @param _payment The amount of payment given (specified in wei)
                                           * @param _specId The Job Specification ID
                                           * @param _callbackAddress The callback address for the response
                                           * @param _callbackFunctionId The callback function ID for the response
                                           * @param _nonce The nonce sent by the requester
                                           * @param _dataVersion The specified data version
                                           * @param _data The CBOR payload of the request
                                           */
                                          function oracleRequest(
                                            address _sender,
                                            uint256 _payment,
                                            bytes32 _specId,
                                            address _callbackAddress,
                                            bytes4 _callbackFunctionId,
                                            uint256 _nonce,
                                            uint256 _dataVersion,
                                            bytes _data
                                          )
                                            external
                                            onlyLINK
                                            checkCallbackAddress(_callbackAddress)
                                          {
                                            bytes32 requestId = keccak256(abi.encodePacked(_sender, _nonce));
                                            require(commitments[requestId] == 0, "Must use a unique ID");
                                            uint256 expiration = now.add(EXPIRY_TIME);
                                        
                                            commitments[requestId] = keccak256(
                                              abi.encodePacked(
                                                _payment,
                                                _callbackAddress,
                                                _callbackFunctionId,
                                                expiration
                                              )
                                            );
                                        
                                            emit OracleRequest(
                                              _specId,
                                              _sender,
                                              requestId,
                                              _payment,
                                              _callbackAddress,
                                              _callbackFunctionId,
                                              expiration,
                                              _dataVersion,
                                              _data);
                                          }
                                        
                                          /**
                                           * @notice Called by the Chainlink node to fulfill requests
                                           * @dev Given params must hash back to the commitment stored from `oracleRequest`.
                                           * Will call the callback address' callback function without bubbling up error
                                           * checking in a `require` so that the node can get paid.
                                           * @param _requestId The fulfillment request ID that must match the requester's
                                           * @param _payment The payment amount that will be released for the oracle (specified in wei)
                                           * @param _callbackAddress The callback address to call for fulfillment
                                           * @param _callbackFunctionId The callback function ID to use for fulfillment
                                           * @param _expiration The expiration that the node should respond by before the requester can cancel
                                           * @param _data The data to return to the consuming contract
                                           * @return Status if the external call was successful
                                           */
                                          function fulfillOracleRequest(
                                            bytes32 _requestId,
                                            uint256 _payment,
                                            address _callbackAddress,
                                            bytes4 _callbackFunctionId,
                                            uint256 _expiration,
                                            bytes32 _data
                                          )
                                            external
                                            onlyAuthorizedNode
                                            isValidRequest(_requestId)
                                            returns (bool)
                                          {
                                            bytes32 paramsHash = keccak256(
                                              abi.encodePacked(
                                                _payment,
                                                _callbackAddress,
                                                _callbackFunctionId,
                                                _expiration
                                              )
                                            );
                                            require(commitments[_requestId] == paramsHash, "Params do not match request ID");
                                            withdrawableTokens = withdrawableTokens.add(_payment);
                                            delete commitments[_requestId];
                                            require(gasleft() >= MINIMUM_CONSUMER_GAS_LIMIT, "Must provide consumer enough gas");
                                            // All updates to the oracle's fulfillment should come before calling the
                                            // callback(addr+functionId) as it is untrusted.
                                            // See: https://solidity.readthedocs.io/en/develop/security-considerations.html#use-the-checks-effects-interactions-pattern
                                            return _callbackAddress.call(_callbackFunctionId, _requestId, _data); // solium-disable-line security/no-low-level-calls
                                          }
                                        
                                          /**
                                           * @notice Use this to check if a node is authorized for fulfilling requests
                                           * @param _node The address of the Chainlink node
                                           * @return The authorization status of the node
                                           */
                                          function getAuthorizationStatus(address _node) external view returns (bool) {
                                            return authorizedNodes[_node];
                                          }
                                        
                                          /**
                                           * @notice Sets the fulfillment permission for a given node. Use `true` to allow, `false` to disallow.
                                           * @param _node The address of the Chainlink node
                                           * @param _allowed Bool value to determine if the node can fulfill requests
                                           */
                                          function setFulfillmentPermission(address _node, bool _allowed) external onlyOwner {
                                            authorizedNodes[_node] = _allowed;
                                          }
                                        
                                          /**
                                           * @notice Allows the node operator to withdraw earned LINK to a given address
                                           * @dev The owner of the contract can be another wallet and does not have to be a Chainlink node
                                           * @param _recipient The address to send the LINK token to
                                           * @param _amount The amount to send (specified in wei)
                                           */
                                          function withdraw(address _recipient, uint256 _amount)
                                            external
                                            onlyOwner
                                            hasAvailableFunds(_amount)
                                          {
                                            withdrawableTokens = withdrawableTokens.sub(_amount);
                                            assert(LinkToken.transfer(_recipient, _amount));
                                          }
                                        
                                          /**
                                           * @notice Displays the amount of LINK that is available for the node operator to withdraw
                                           * @dev We use `ONE_FOR_CONSISTENT_GAS_COST` in place of 0 in storage
                                           * @return The amount of withdrawable LINK on the contract
                                           */
                                          function withdrawable() external view onlyOwner returns (uint256) {
                                            return withdrawableTokens.sub(ONE_FOR_CONSISTENT_GAS_COST);
                                          }
                                        
                                          /**
                                           * @notice Allows requesters to cancel requests sent to this oracle contract. Will transfer the LINK
                                           * sent for the request back to the requester's address.
                                           * @dev Given params must hash to a commitment stored on the contract in order for the request to be valid
                                           * Emits CancelOracleRequest event.
                                           * @param _requestId The request ID
                                           * @param _payment The amount of payment given (specified in wei)
                                           * @param _callbackFunc The requester's specified callback address
                                           * @param _expiration The time of the expiration for the request
                                           */
                                          function cancelOracleRequest(
                                            bytes32 _requestId,
                                            uint256 _payment,
                                            bytes4 _callbackFunc,
                                            uint256 _expiration
                                          ) external {
                                            bytes32 paramsHash = keccak256(
                                              abi.encodePacked(
                                                _payment,
                                                msg.sender,
                                                _callbackFunc,
                                                _expiration)
                                            );
                                            require(paramsHash == commitments[_requestId], "Params do not match request ID");
                                            require(_expiration <= now, "Request is not expired");
                                        
                                            delete commitments[_requestId];
                                            emit CancelOracleRequest(_requestId);
                                        
                                            assert(LinkToken.transfer(msg.sender, _payment));
                                          }
                                        
                                          // MODIFIERS
                                        
                                          /**
                                           * @dev Reverts if amount requested is greater than withdrawable balance
                                           * @param _amount The given amount to compare to `withdrawableTokens`
                                           */
                                          modifier hasAvailableFunds(uint256 _amount) {
                                            require(withdrawableTokens >= _amount.add(ONE_FOR_CONSISTENT_GAS_COST), "Amount requested is greater than withdrawable balance");
                                            _;
                                          }
                                        
                                          /**
                                           * @dev Reverts if request ID does not exist
                                           * @param _requestId The given request ID to check in stored `commitments`
                                           */
                                          modifier isValidRequest(bytes32 _requestId) {
                                            require(commitments[_requestId] != 0, "Must have a valid requestId");
                                            _;
                                          }
                                        
                                          /**
                                           * @dev Reverts if `msg.sender` is not authorized to fulfill requests
                                           */
                                          modifier onlyAuthorizedNode() {
                                            require(authorizedNodes[msg.sender] || msg.sender == owner, "Not an authorized node to fulfill requests");
                                            _;
                                          }
                                        
                                          /**
                                           * @dev Reverts if not sent from the LINK token
                                           */
                                          modifier onlyLINK() {
                                            require(msg.sender == address(LinkToken), "Must use LINK token");
                                            _;
                                          }
                                        
                                          /**
                                           * @dev Reverts if the given data does not begin with the `oracleRequest` function selector
                                           * @param _data The data payload of the request
                                           */
                                          modifier permittedFunctionsForLINK(bytes _data) {
                                            bytes4 funcSelector;
                                            assembly {
                                              // solium-disable-next-line security/no-low-level-calls
                                              funcSelector := mload(add(_data, 32))
                                            }
                                            require(funcSelector == this.oracleRequest.selector, "Must use whitelisted functions");
                                            _;
                                          }
                                        
                                          /**
                                           * @dev Reverts if the callback address is the LINK token
                                           * @param _to The callback address
                                           */
                                          modifier checkCallbackAddress(address _to) {
                                            require(_to != address(LinkToken), "Cannot callback to LINK");
                                            _;
                                          }
                                        
                                          /**
                                           * @dev Reverts if the given payload is less than needed to create a request
                                           * @param _data The request payload
                                           */
                                          modifier validRequestLength(bytes _data) {
                                            require(_data.length >= MINIMUM_REQUEST_LENGTH, "Invalid request length");
                                            _;
                                          }
                                        
                                        }

                                        File 7 of 9: Oracle
                                        // File: openzeppelin-solidity/contracts/ownership/Ownable.sol
                                        
                                        pragma solidity ^0.4.24;
                                        
                                        
                                        /**
                                         * @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 OwnershipRenounced(address indexed previousOwner);
                                          event OwnershipTransferred(
                                            address indexed previousOwner,
                                            address indexed newOwner
                                          );
                                        
                                        
                                          /**
                                           * @dev The Ownable constructor sets the original `owner` of the contract to the sender
                                           * account.
                                           */
                                          constructor() 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 relinquish control of the contract.
                                           * @notice Renouncing to ownership will leave the contract without an owner.
                                           * It will not be possible to call the functions with the `onlyOwner`
                                           * modifier anymore.
                                           */
                                          function renounceOwnership() public onlyOwner {
                                            emit OwnershipRenounced(owner);
                                            owner = address(0);
                                          }
                                        
                                          /**
                                           * @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 {
                                            _transferOwnership(_newOwner);
                                          }
                                        
                                          /**
                                           * @dev Transfers control of the contract to a newOwner.
                                           * @param _newOwner The address to transfer ownership to.
                                           */
                                          function _transferOwnership(address _newOwner) internal {
                                            require(_newOwner != address(0));
                                            emit OwnershipTransferred(owner, _newOwner);
                                            owner = _newOwner;
                                          }
                                        }
                                        
                                        // File: openzeppelin-solidity/contracts/math/SafeMath.sol
                                        
                                        pragma solidity ^0.4.24;
                                        
                                        
                                        /**
                                         * @title SafeMath
                                         * @dev Math operations with safety checks that throw on error
                                         */
                                        library SafeMath {
                                        
                                          /**
                                          * @dev Multiplies two numbers, throws on overflow.
                                          */
                                          function mul(uint256 _a, uint256 _b) internal pure returns (uint256 c) {
                                            // Gas optimization: this is cheaper than asserting 'a' not being zero, but the
                                            // benefit is lost if 'b' is also tested.
                                            // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
                                            if (_a == 0) {
                                              return 0;
                                            }
                                        
                                            c = _a * _b;
                                            assert(c / _a == _b);
                                            return c;
                                          }
                                        
                                          /**
                                          * @dev Integer division of two numbers, truncating the quotient.
                                          */
                                          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 _a / _b;
                                          }
                                        
                                          /**
                                          * @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend).
                                          */
                                          function sub(uint256 _a, uint256 _b) internal pure returns (uint256) {
                                            assert(_b <= _a);
                                            return _a - _b;
                                          }
                                        
                                          /**
                                          * @dev Adds two numbers, throws on overflow.
                                          */
                                          function add(uint256 _a, uint256 _b) internal pure returns (uint256 c) {
                                            c = _a + _b;
                                            assert(c >= _a);
                                            return c;
                                          }
                                        }
                                        
                                        // File: contracts/interfaces/ChainlinkRequestInterface.sol
                                        
                                        pragma solidity 0.4.24;
                                        
                                        interface ChainlinkRequestInterface {
                                          function oracleRequest(
                                            address sender,
                                            uint256 payment,
                                            bytes32 id,
                                            address callbackAddress,
                                            bytes4 callbackFunctionId,
                                            uint256 nonce,
                                            uint256 version,
                                            bytes data
                                          ) external;
                                        
                                          function cancelOracleRequest(
                                            bytes32 requestId,
                                            uint256 payment,
                                            bytes4 callbackFunctionId,
                                            uint256 expiration
                                          ) external;
                                        }
                                        
                                        // File: contracts/interfaces/OracleInterface.sol
                                        
                                        pragma solidity 0.4.24;
                                        
                                        interface OracleInterface {
                                          function fulfillOracleRequest(
                                            bytes32 requestId,
                                            uint256 payment,
                                            address callbackAddress,
                                            bytes4 callbackFunctionId,
                                            uint256 expiration,
                                            bytes32 data
                                          ) external returns (bool);
                                          function getAuthorizationStatus(address node) external view returns (bool);
                                          function setFulfillmentPermission(address node, bool allowed) external;
                                          function withdraw(address recipient, uint256 amount) external;
                                          function withdrawable() external view returns (uint256);
                                        }
                                        
                                        // File: contracts/interfaces/LinkTokenInterface.sol
                                        
                                        pragma solidity 0.4.24;
                                        
                                        interface LinkTokenInterface {
                                          function allowance(address owner, address spender) external returns (bool success);
                                          function approve(address spender, uint256 value) external returns (bool success);
                                          function balanceOf(address owner) external returns (uint256 balance);
                                          function decimals() external returns (uint8 decimalPlaces);
                                          function decreaseApproval(address spender, uint256 addedValue) external returns (bool success);
                                          function increaseApproval(address spender, uint256 subtractedValue) external;
                                          function name() external returns (string tokenName);
                                          function symbol() external returns (string tokenSymbol);
                                          function totalSupply() external returns (uint256 totalTokensIssued);
                                          function transfer(address to, uint256 value) external returns (bool success);
                                          function transferAndCall(address to, uint256 value, bytes data) external returns (bool success);
                                          function transferFrom(address from, address to, uint256 value) external returns (bool success);
                                        }
                                        
                                        // File: contracts/Oracle.sol
                                        
                                        pragma solidity 0.4.24;
                                        
                                        
                                        
                                        
                                        
                                        
                                        /**
                                         * @title The Chainlink Oracle contract
                                         * @notice Node operators can deploy this contract to fulfill requests sent to them
                                         */
                                        contract Oracle is ChainlinkRequestInterface, OracleInterface, Ownable {
                                          using SafeMath for uint256;
                                        
                                          uint256 constant public EXPIRY_TIME = 5 minutes;
                                          uint256 constant private MINIMUM_CONSUMER_GAS_LIMIT = 400000;
                                          // We initialize fields to 1 instead of 0 so that the first invocation
                                          // does not cost more gas.
                                          uint256 constant private ONE_FOR_CONSISTENT_GAS_COST = 1;
                                          uint256 constant private SELECTOR_LENGTH = 4;
                                          uint256 constant private EXPECTED_REQUEST_WORDS = 2;
                                          // solium-disable-next-line zeppelin/no-arithmetic-operations
                                          uint256 constant private MINIMUM_REQUEST_LENGTH = SELECTOR_LENGTH + (32 * EXPECTED_REQUEST_WORDS);
                                        
                                          LinkTokenInterface internal LinkToken;
                                          mapping(bytes32 => bytes32) private commitments;
                                          mapping(address => bool) private authorizedNodes;
                                          uint256 private withdrawableTokens = ONE_FOR_CONSISTENT_GAS_COST;
                                        
                                          event OracleRequest(
                                            bytes32 indexed specId,
                                            address requester,
                                            bytes32 requestId,
                                            uint256 payment,
                                            address callbackAddr,
                                            bytes4 callbackFunctionId,
                                            uint256 cancelExpiration,
                                            uint256 dataVersion,
                                            bytes data
                                          );
                                        
                                          event CancelOracleRequest(
                                            bytes32 indexed requestId
                                          );
                                        
                                          /**
                                           * @notice Deploy with the address of the LINK token
                                           * @dev Sets the LinkToken address for the imported LinkTokenInterface
                                           * @param _link The address of the LINK token
                                           */
                                          constructor(address _link) Ownable() public {
                                            LinkToken = LinkTokenInterface(_link);
                                          }
                                        
                                          /**
                                           * @notice Called when LINK is sent to the contract via `transferAndCall`
                                           * @dev The data payload's first 2 words will be overwritten by the `_sender` and `_amount`
                                           * values to ensure correctness. Calls oracleRequest.
                                           * @param _sender Address of the sender
                                           * @param _amount Amount of LINK sent (specified in wei)
                                           * @param _data Payload of the transaction
                                           */
                                          function onTokenTransfer(
                                            address _sender,
                                            uint256 _amount,
                                            bytes _data
                                          )
                                            public
                                            onlyLINK
                                            validRequestLength(_data)
                                            permittedFunctionsForLINK(_data)
                                          {
                                            assembly {
                                              // solium-disable-next-line security/no-low-level-calls
                                              mstore(add(_data, 36), _sender) // ensure correct sender is passed
                                              // solium-disable-next-line security/no-low-level-calls
                                              mstore(add(_data, 68), _amount)    // ensure correct amount is passed
                                            }
                                            // solium-disable-next-line security/no-low-level-calls
                                            require(address(this).delegatecall(_data), "Unable to create request"); // calls oracleRequest
                                          }
                                        
                                          /**
                                           * @notice Creates the Chainlink request
                                           * @dev Stores the hash of the params as the on-chain commitment for the request.
                                           * Emits OracleRequest event for the Chainlink node to detect.
                                           * @param _sender The sender of the request
                                           * @param _payment The amount of payment given (specified in wei)
                                           * @param _specId The Job Specification ID
                                           * @param _callbackAddress The callback address for the response
                                           * @param _callbackFunctionId The callback function ID for the response
                                           * @param _nonce The nonce sent by the requester
                                           * @param _dataVersion The specified data version
                                           * @param _data The CBOR payload of the request
                                           */
                                          function oracleRequest(
                                            address _sender,
                                            uint256 _payment,
                                            bytes32 _specId,
                                            address _callbackAddress,
                                            bytes4 _callbackFunctionId,
                                            uint256 _nonce,
                                            uint256 _dataVersion,
                                            bytes _data
                                          )
                                            external
                                            onlyLINK
                                            checkCallbackAddress(_callbackAddress)
                                          {
                                            bytes32 requestId = keccak256(abi.encodePacked(_sender, _nonce));
                                            require(commitments[requestId] == 0, "Must use a unique ID");
                                            uint256 expiration = now.add(EXPIRY_TIME);
                                        
                                            commitments[requestId] = keccak256(
                                              abi.encodePacked(
                                                _payment,
                                                _callbackAddress,
                                                _callbackFunctionId,
                                                expiration
                                              )
                                            );
                                        
                                            emit OracleRequest(
                                              _specId,
                                              _sender,
                                              requestId,
                                              _payment,
                                              _callbackAddress,
                                              _callbackFunctionId,
                                              expiration,
                                              _dataVersion,
                                              _data);
                                          }
                                        
                                          /**
                                           * @notice Called by the Chainlink node to fulfill requests
                                           * @dev Given params must hash back to the commitment stored from `oracleRequest`.
                                           * Will call the callback address' callback function without bubbling up error
                                           * checking in a `require` so that the node can get paid.
                                           * @param _requestId The fulfillment request ID that must match the requester's
                                           * @param _payment The payment amount that will be released for the oracle (specified in wei)
                                           * @param _callbackAddress The callback address to call for fulfillment
                                           * @param _callbackFunctionId The callback function ID to use for fulfillment
                                           * @param _expiration The expiration that the node should respond by before the requester can cancel
                                           * @param _data The data to return to the consuming contract
                                           * @return Status if the external call was successful
                                           */
                                          function fulfillOracleRequest(
                                            bytes32 _requestId,
                                            uint256 _payment,
                                            address _callbackAddress,
                                            bytes4 _callbackFunctionId,
                                            uint256 _expiration,
                                            bytes32 _data
                                          )
                                            external
                                            onlyAuthorizedNode
                                            isValidRequest(_requestId)
                                            returns (bool)
                                          {
                                            bytes32 paramsHash = keccak256(
                                              abi.encodePacked(
                                                _payment,
                                                _callbackAddress,
                                                _callbackFunctionId,
                                                _expiration
                                              )
                                            );
                                            require(commitments[_requestId] == paramsHash, "Params do not match request ID");
                                            withdrawableTokens = withdrawableTokens.add(_payment);
                                            delete commitments[_requestId];
                                            require(gasleft() >= MINIMUM_CONSUMER_GAS_LIMIT, "Must provide consumer enough gas");
                                            // All updates to the oracle's fulfillment should come before calling the
                                            // callback(addr+functionId) as it is untrusted.
                                            // See: https://solidity.readthedocs.io/en/develop/security-considerations.html#use-the-checks-effects-interactions-pattern
                                            return _callbackAddress.call(_callbackFunctionId, _requestId, _data); // solium-disable-line security/no-low-level-calls
                                          }
                                        
                                          /**
                                           * @notice Use this to check if a node is authorized for fulfilling requests
                                           * @param _node The address of the Chainlink node
                                           * @return The authorization status of the node
                                           */
                                          function getAuthorizationStatus(address _node) external view returns (bool) {
                                            return authorizedNodes[_node];
                                          }
                                        
                                          /**
                                           * @notice Sets the fulfillment permission for a given node. Use `true` to allow, `false` to disallow.
                                           * @param _node The address of the Chainlink node
                                           * @param _allowed Bool value to determine if the node can fulfill requests
                                           */
                                          function setFulfillmentPermission(address _node, bool _allowed) external onlyOwner {
                                            authorizedNodes[_node] = _allowed;
                                          }
                                        
                                          /**
                                           * @notice Allows the node operator to withdraw earned LINK to a given address
                                           * @dev The owner of the contract can be another wallet and does not have to be a Chainlink node
                                           * @param _recipient The address to send the LINK token to
                                           * @param _amount The amount to send (specified in wei)
                                           */
                                          function withdraw(address _recipient, uint256 _amount)
                                            external
                                            onlyOwner
                                            hasAvailableFunds(_amount)
                                          {
                                            withdrawableTokens = withdrawableTokens.sub(_amount);
                                            assert(LinkToken.transfer(_recipient, _amount));
                                          }
                                        
                                          /**
                                           * @notice Displays the amount of LINK that is available for the node operator to withdraw
                                           * @dev We use `ONE_FOR_CONSISTENT_GAS_COST` in place of 0 in storage
                                           * @return The amount of withdrawable LINK on the contract
                                           */
                                          function withdrawable() external view onlyOwner returns (uint256) {
                                            return withdrawableTokens.sub(ONE_FOR_CONSISTENT_GAS_COST);
                                          }
                                        
                                          /**
                                           * @notice Allows requesters to cancel requests sent to this oracle contract. Will transfer the LINK
                                           * sent for the request back to the requester's address.
                                           * @dev Given params must hash to a commitment stored on the contract in order for the request to be valid
                                           * Emits CancelOracleRequest event.
                                           * @param _requestId The request ID
                                           * @param _payment The amount of payment given (specified in wei)
                                           * @param _callbackFunc The requester's specified callback address
                                           * @param _expiration The time of the expiration for the request
                                           */
                                          function cancelOracleRequest(
                                            bytes32 _requestId,
                                            uint256 _payment,
                                            bytes4 _callbackFunc,
                                            uint256 _expiration
                                          ) external {
                                            bytes32 paramsHash = keccak256(
                                              abi.encodePacked(
                                                _payment,
                                                msg.sender,
                                                _callbackFunc,
                                                _expiration)
                                            );
                                            require(paramsHash == commitments[_requestId], "Params do not match request ID");
                                            require(_expiration <= now, "Request is not expired");
                                        
                                            delete commitments[_requestId];
                                            emit CancelOracleRequest(_requestId);
                                        
                                            assert(LinkToken.transfer(msg.sender, _payment));
                                          }
                                        
                                          // MODIFIERS
                                        
                                          /**
                                           * @dev Reverts if amount requested is greater than withdrawable balance
                                           * @param _amount The given amount to compare to `withdrawableTokens`
                                           */
                                          modifier hasAvailableFunds(uint256 _amount) {
                                            require(withdrawableTokens >= _amount.add(ONE_FOR_CONSISTENT_GAS_COST), "Amount requested is greater than withdrawable balance");
                                            _;
                                          }
                                        
                                          /**
                                           * @dev Reverts if request ID does not exist
                                           * @param _requestId The given request ID to check in stored `commitments`
                                           */
                                          modifier isValidRequest(bytes32 _requestId) {
                                            require(commitments[_requestId] != 0, "Must have a valid requestId");
                                            _;
                                          }
                                        
                                          /**
                                           * @dev Reverts if `msg.sender` is not authorized to fulfill requests
                                           */
                                          modifier onlyAuthorizedNode() {
                                            require(authorizedNodes[msg.sender] || msg.sender == owner, "Not an authorized node to fulfill requests");
                                            _;
                                          }
                                        
                                          /**
                                           * @dev Reverts if not sent from the LINK token
                                           */
                                          modifier onlyLINK() {
                                            require(msg.sender == address(LinkToken), "Must use LINK token");
                                            _;
                                          }
                                        
                                          /**
                                           * @dev Reverts if the given data does not begin with the `oracleRequest` function selector
                                           * @param _data The data payload of the request
                                           */
                                          modifier permittedFunctionsForLINK(bytes _data) {
                                            bytes4 funcSelector;
                                            assembly {
                                              // solium-disable-next-line security/no-low-level-calls
                                              funcSelector := mload(add(_data, 32))
                                            }
                                            require(funcSelector == this.oracleRequest.selector, "Must use whitelisted functions");
                                            _;
                                          }
                                        
                                          /**
                                           * @dev Reverts if the callback address is the LINK token
                                           * @param _to The callback address
                                           */
                                          modifier checkCallbackAddress(address _to) {
                                            require(_to != address(LinkToken), "Cannot callback to LINK");
                                            _;
                                          }
                                        
                                          /**
                                           * @dev Reverts if the given payload is less than needed to create a request
                                           * @param _data The request payload
                                           */
                                          modifier validRequestLength(bytes _data) {
                                            require(_data.length >= MINIMUM_REQUEST_LENGTH, "Invalid request length");
                                            _;
                                          }
                                        
                                        }

                                        File 8 of 9: Oracle
                                        // File: openzeppelin-solidity/contracts/ownership/Ownable.sol
                                        
                                        pragma solidity ^0.4.24;
                                        
                                        
                                        /**
                                         * @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 OwnershipRenounced(address indexed previousOwner);
                                          event OwnershipTransferred(
                                            address indexed previousOwner,
                                            address indexed newOwner
                                          );
                                        
                                        
                                          /**
                                           * @dev The Ownable constructor sets the original `owner` of the contract to the sender
                                           * account.
                                           */
                                          constructor() 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 relinquish control of the contract.
                                           * @notice Renouncing to ownership will leave the contract without an owner.
                                           * It will not be possible to call the functions with the `onlyOwner`
                                           * modifier anymore.
                                           */
                                          function renounceOwnership() public onlyOwner {
                                            emit OwnershipRenounced(owner);
                                            owner = address(0);
                                          }
                                        
                                          /**
                                           * @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 {
                                            _transferOwnership(_newOwner);
                                          }
                                        
                                          /**
                                           * @dev Transfers control of the contract to a newOwner.
                                           * @param _newOwner The address to transfer ownership to.
                                           */
                                          function _transferOwnership(address _newOwner) internal {
                                            require(_newOwner != address(0));
                                            emit OwnershipTransferred(owner, _newOwner);
                                            owner = _newOwner;
                                          }
                                        }
                                        
                                        // File: openzeppelin-solidity/contracts/math/SafeMath.sol
                                        
                                        pragma solidity ^0.4.24;
                                        
                                        
                                        /**
                                         * @title SafeMath
                                         * @dev Math operations with safety checks that throw on error
                                         */
                                        library SafeMath {
                                        
                                          /**
                                          * @dev Multiplies two numbers, throws on overflow.
                                          */
                                          function mul(uint256 _a, uint256 _b) internal pure returns (uint256 c) {
                                            // Gas optimization: this is cheaper than asserting 'a' not being zero, but the
                                            // benefit is lost if 'b' is also tested.
                                            // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
                                            if (_a == 0) {
                                              return 0;
                                            }
                                        
                                            c = _a * _b;
                                            assert(c / _a == _b);
                                            return c;
                                          }
                                        
                                          /**
                                          * @dev Integer division of two numbers, truncating the quotient.
                                          */
                                          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 _a / _b;
                                          }
                                        
                                          /**
                                          * @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend).
                                          */
                                          function sub(uint256 _a, uint256 _b) internal pure returns (uint256) {
                                            assert(_b <= _a);
                                            return _a - _b;
                                          }
                                        
                                          /**
                                          * @dev Adds two numbers, throws on overflow.
                                          */
                                          function add(uint256 _a, uint256 _b) internal pure returns (uint256 c) {
                                            c = _a + _b;
                                            assert(c >= _a);
                                            return c;
                                          }
                                        }
                                        
                                        // File: contracts/interfaces/ChainlinkRequestInterface.sol
                                        
                                        pragma solidity 0.4.24;
                                        
                                        interface ChainlinkRequestInterface {
                                          function oracleRequest(
                                            address sender,
                                            uint256 payment,
                                            bytes32 id,
                                            address callbackAddress,
                                            bytes4 callbackFunctionId,
                                            uint256 nonce,
                                            uint256 version,
                                            bytes data
                                          ) external;
                                        
                                          function cancelOracleRequest(
                                            bytes32 requestId,
                                            uint256 payment,
                                            bytes4 callbackFunctionId,
                                            uint256 expiration
                                          ) external;
                                        }
                                        
                                        // File: contracts/interfaces/OracleInterface.sol
                                        
                                        pragma solidity 0.4.24;
                                        
                                        interface OracleInterface {
                                          function fulfillOracleRequest(
                                            bytes32 requestId,
                                            uint256 payment,
                                            address callbackAddress,
                                            bytes4 callbackFunctionId,
                                            uint256 expiration,
                                            bytes32 data
                                          ) external returns (bool);
                                          function getAuthorizationStatus(address node) external view returns (bool);
                                          function setFulfillmentPermission(address node, bool allowed) external;
                                          function withdraw(address recipient, uint256 amount) external;
                                          function withdrawable() external view returns (uint256);
                                        }
                                        
                                        // File: contracts/interfaces/LinkTokenInterface.sol
                                        
                                        pragma solidity 0.4.24;
                                        
                                        interface LinkTokenInterface {
                                          function allowance(address owner, address spender) external returns (bool success);
                                          function approve(address spender, uint256 value) external returns (bool success);
                                          function balanceOf(address owner) external returns (uint256 balance);
                                          function decimals() external returns (uint8 decimalPlaces);
                                          function decreaseApproval(address spender, uint256 addedValue) external returns (bool success);
                                          function increaseApproval(address spender, uint256 subtractedValue) external;
                                          function name() external returns (string tokenName);
                                          function symbol() external returns (string tokenSymbol);
                                          function totalSupply() external returns (uint256 totalTokensIssued);
                                          function transfer(address to, uint256 value) external returns (bool success);
                                          function transferAndCall(address to, uint256 value, bytes data) external returns (bool success);
                                          function transferFrom(address from, address to, uint256 value) external returns (bool success);
                                        }
                                        
                                        // File: contracts/Oracle.sol
                                        
                                        pragma solidity 0.4.24;
                                        
                                        
                                        
                                        
                                        
                                        
                                        /**
                                         * @title The Chainlink Oracle contract
                                         * @notice Node operators can deploy this contract to fulfill requests sent to them
                                         */
                                        contract Oracle is ChainlinkRequestInterface, OracleInterface, Ownable {
                                          using SafeMath for uint256;
                                        
                                          uint256 constant public EXPIRY_TIME = 5 minutes;
                                          uint256 constant private MINIMUM_CONSUMER_GAS_LIMIT = 400000;
                                          // We initialize fields to 1 instead of 0 so that the first invocation
                                          // does not cost more gas.
                                          uint256 constant private ONE_FOR_CONSISTENT_GAS_COST = 1;
                                          uint256 constant private SELECTOR_LENGTH = 4;
                                          uint256 constant private EXPECTED_REQUEST_WORDS = 2;
                                          // solium-disable-next-line zeppelin/no-arithmetic-operations
                                          uint256 constant private MINIMUM_REQUEST_LENGTH = SELECTOR_LENGTH + (32 * EXPECTED_REQUEST_WORDS);
                                        
                                          LinkTokenInterface internal LinkToken;
                                          mapping(bytes32 => bytes32) private commitments;
                                          mapping(address => bool) private authorizedNodes;
                                          uint256 private withdrawableTokens = ONE_FOR_CONSISTENT_GAS_COST;
                                        
                                          event OracleRequest(
                                            bytes32 indexed specId,
                                            address requester,
                                            bytes32 requestId,
                                            uint256 payment,
                                            address callbackAddr,
                                            bytes4 callbackFunctionId,
                                            uint256 cancelExpiration,
                                            uint256 dataVersion,
                                            bytes data
                                          );
                                        
                                          event CancelOracleRequest(
                                            bytes32 indexed requestId
                                          );
                                        
                                          /**
                                           * @notice Deploy with the address of the LINK token
                                           * @dev Sets the LinkToken address for the imported LinkTokenInterface
                                           * @param _link The address of the LINK token
                                           */
                                          constructor(address _link) Ownable() public {
                                            LinkToken = LinkTokenInterface(_link);
                                          }
                                        
                                          /**
                                           * @notice Called when LINK is sent to the contract via `transferAndCall`
                                           * @dev The data payload's first 2 words will be overwritten by the `_sender` and `_amount`
                                           * values to ensure correctness. Calls oracleRequest.
                                           * @param _sender Address of the sender
                                           * @param _amount Amount of LINK sent (specified in wei)
                                           * @param _data Payload of the transaction
                                           */
                                          function onTokenTransfer(
                                            address _sender,
                                            uint256 _amount,
                                            bytes _data
                                          )
                                            public
                                            onlyLINK
                                            validRequestLength(_data)
                                            permittedFunctionsForLINK(_data)
                                          {
                                            assembly {
                                              // solium-disable-next-line security/no-low-level-calls
                                              mstore(add(_data, 36), _sender) // ensure correct sender is passed
                                              // solium-disable-next-line security/no-low-level-calls
                                              mstore(add(_data, 68), _amount)    // ensure correct amount is passed
                                            }
                                            // solium-disable-next-line security/no-low-level-calls
                                            require(address(this).delegatecall(_data), "Unable to create request"); // calls oracleRequest
                                          }
                                        
                                          /**
                                           * @notice Creates the Chainlink request
                                           * @dev Stores the hash of the params as the on-chain commitment for the request.
                                           * Emits OracleRequest event for the Chainlink node to detect.
                                           * @param _sender The sender of the request
                                           * @param _payment The amount of payment given (specified in wei)
                                           * @param _specId The Job Specification ID
                                           * @param _callbackAddress The callback address for the response
                                           * @param _callbackFunctionId The callback function ID for the response
                                           * @param _nonce The nonce sent by the requester
                                           * @param _dataVersion The specified data version
                                           * @param _data The CBOR payload of the request
                                           */
                                          function oracleRequest(
                                            address _sender,
                                            uint256 _payment,
                                            bytes32 _specId,
                                            address _callbackAddress,
                                            bytes4 _callbackFunctionId,
                                            uint256 _nonce,
                                            uint256 _dataVersion,
                                            bytes _data
                                          )
                                            external
                                            onlyLINK
                                            checkCallbackAddress(_callbackAddress)
                                          {
                                            bytes32 requestId = keccak256(abi.encodePacked(_sender, _nonce));
                                            require(commitments[requestId] == 0, "Must use a unique ID");
                                            uint256 expiration = now.add(EXPIRY_TIME);
                                        
                                            commitments[requestId] = keccak256(
                                              abi.encodePacked(
                                                _payment,
                                                _callbackAddress,
                                                _callbackFunctionId,
                                                expiration
                                              )
                                            );
                                        
                                            emit OracleRequest(
                                              _specId,
                                              _sender,
                                              requestId,
                                              _payment,
                                              _callbackAddress,
                                              _callbackFunctionId,
                                              expiration,
                                              _dataVersion,
                                              _data);
                                          }
                                        
                                          /**
                                           * @notice Called by the Chainlink node to fulfill requests
                                           * @dev Given params must hash back to the commitment stored from `oracleRequest`.
                                           * Will call the callback address' callback function without bubbling up error
                                           * checking in a `require` so that the node can get paid.
                                           * @param _requestId The fulfillment request ID that must match the requester's
                                           * @param _payment The payment amount that will be released for the oracle (specified in wei)
                                           * @param _callbackAddress The callback address to call for fulfillment
                                           * @param _callbackFunctionId The callback function ID to use for fulfillment
                                           * @param _expiration The expiration that the node should respond by before the requester can cancel
                                           * @param _data The data to return to the consuming contract
                                           * @return Status if the external call was successful
                                           */
                                          function fulfillOracleRequest(
                                            bytes32 _requestId,
                                            uint256 _payment,
                                            address _callbackAddress,
                                            bytes4 _callbackFunctionId,
                                            uint256 _expiration,
                                            bytes32 _data
                                          )
                                            external
                                            onlyAuthorizedNode
                                            isValidRequest(_requestId)
                                            returns (bool)
                                          {
                                            bytes32 paramsHash = keccak256(
                                              abi.encodePacked(
                                                _payment,
                                                _callbackAddress,
                                                _callbackFunctionId,
                                                _expiration
                                              )
                                            );
                                            require(commitments[_requestId] == paramsHash, "Params do not match request ID");
                                            withdrawableTokens = withdrawableTokens.add(_payment);
                                            delete commitments[_requestId];
                                            require(gasleft() >= MINIMUM_CONSUMER_GAS_LIMIT, "Must provide consumer enough gas");
                                            // All updates to the oracle's fulfillment should come before calling the
                                            // callback(addr+functionId) as it is untrusted.
                                            // See: https://solidity.readthedocs.io/en/develop/security-considerations.html#use-the-checks-effects-interactions-pattern
                                            return _callbackAddress.call(_callbackFunctionId, _requestId, _data); // solium-disable-line security/no-low-level-calls
                                          }
                                        
                                          /**
                                           * @notice Use this to check if a node is authorized for fulfilling requests
                                           * @param _node The address of the Chainlink node
                                           * @return The authorization status of the node
                                           */
                                          function getAuthorizationStatus(address _node) external view returns (bool) {
                                            return authorizedNodes[_node];
                                          }
                                        
                                          /**
                                           * @notice Sets the fulfillment permission for a given node. Use `true` to allow, `false` to disallow.
                                           * @param _node The address of the Chainlink node
                                           * @param _allowed Bool value to determine if the node can fulfill requests
                                           */
                                          function setFulfillmentPermission(address _node, bool _allowed) external onlyOwner {
                                            authorizedNodes[_node] = _allowed;
                                          }
                                        
                                          /**
                                           * @notice Allows the node operator to withdraw earned LINK to a given address
                                           * @dev The owner of the contract can be another wallet and does not have to be a Chainlink node
                                           * @param _recipient The address to send the LINK token to
                                           * @param _amount The amount to send (specified in wei)
                                           */
                                          function withdraw(address _recipient, uint256 _amount)
                                            external
                                            onlyOwner
                                            hasAvailableFunds(_amount)
                                          {
                                            withdrawableTokens = withdrawableTokens.sub(_amount);
                                            assert(LinkToken.transfer(_recipient, _amount));
                                          }
                                        
                                          /**
                                           * @notice Displays the amount of LINK that is available for the node operator to withdraw
                                           * @dev We use `ONE_FOR_CONSISTENT_GAS_COST` in place of 0 in storage
                                           * @return The amount of withdrawable LINK on the contract
                                           */
                                          function withdrawable() external view onlyOwner returns (uint256) {
                                            return withdrawableTokens.sub(ONE_FOR_CONSISTENT_GAS_COST);
                                          }
                                        
                                          /**
                                           * @notice Allows requesters to cancel requests sent to this oracle contract. Will transfer the LINK
                                           * sent for the request back to the requester's address.
                                           * @dev Given params must hash to a commitment stored on the contract in order for the request to be valid
                                           * Emits CancelOracleRequest event.
                                           * @param _requestId The request ID
                                           * @param _payment The amount of payment given (specified in wei)
                                           * @param _callbackFunc The requester's specified callback address
                                           * @param _expiration The time of the expiration for the request
                                           */
                                          function cancelOracleRequest(
                                            bytes32 _requestId,
                                            uint256 _payment,
                                            bytes4 _callbackFunc,
                                            uint256 _expiration
                                          ) external {
                                            bytes32 paramsHash = keccak256(
                                              abi.encodePacked(
                                                _payment,
                                                msg.sender,
                                                _callbackFunc,
                                                _expiration)
                                            );
                                            require(paramsHash == commitments[_requestId], "Params do not match request ID");
                                            require(_expiration <= now, "Request is not expired");
                                        
                                            delete commitments[_requestId];
                                            emit CancelOracleRequest(_requestId);
                                        
                                            assert(LinkToken.transfer(msg.sender, _payment));
                                          }
                                        
                                          // MODIFIERS
                                        
                                          /**
                                           * @dev Reverts if amount requested is greater than withdrawable balance
                                           * @param _amount The given amount to compare to `withdrawableTokens`
                                           */
                                          modifier hasAvailableFunds(uint256 _amount) {
                                            require(withdrawableTokens >= _amount.add(ONE_FOR_CONSISTENT_GAS_COST), "Amount requested is greater than withdrawable balance");
                                            _;
                                          }
                                        
                                          /**
                                           * @dev Reverts if request ID does not exist
                                           * @param _requestId The given request ID to check in stored `commitments`
                                           */
                                          modifier isValidRequest(bytes32 _requestId) {
                                            require(commitments[_requestId] != 0, "Must have a valid requestId");
                                            _;
                                          }
                                        
                                          /**
                                           * @dev Reverts if `msg.sender` is not authorized to fulfill requests
                                           */
                                          modifier onlyAuthorizedNode() {
                                            require(authorizedNodes[msg.sender] || msg.sender == owner, "Not an authorized node to fulfill requests");
                                            _;
                                          }
                                        
                                          /**
                                           * @dev Reverts if not sent from the LINK token
                                           */
                                          modifier onlyLINK() {
                                            require(msg.sender == address(LinkToken), "Must use LINK token");
                                            _;
                                          }
                                        
                                          /**
                                           * @dev Reverts if the given data does not begin with the `oracleRequest` function selector
                                           * @param _data The data payload of the request
                                           */
                                          modifier permittedFunctionsForLINK(bytes _data) {
                                            bytes4 funcSelector;
                                            assembly {
                                              // solium-disable-next-line security/no-low-level-calls
                                              funcSelector := mload(add(_data, 32))
                                            }
                                            require(funcSelector == this.oracleRequest.selector, "Must use whitelisted functions");
                                            _;
                                          }
                                        
                                          /**
                                           * @dev Reverts if the callback address is the LINK token
                                           * @param _to The callback address
                                           */
                                          modifier checkCallbackAddress(address _to) {
                                            require(_to != address(LinkToken), "Cannot callback to LINK");
                                            _;
                                          }
                                        
                                          /**
                                           * @dev Reverts if the given payload is less than needed to create a request
                                           * @param _data The request payload
                                           */
                                          modifier validRequestLength(bytes _data) {
                                            require(_data.length >= MINIMUM_REQUEST_LENGTH, "Invalid request length");
                                            _;
                                          }
                                        
                                        }

                                        File 9 of 9: Oracle
                                        // File: openzeppelin-solidity/contracts/ownership/Ownable.sol
                                        
                                        pragma solidity ^0.4.24;
                                        
                                        
                                        /**
                                         * @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 OwnershipRenounced(address indexed previousOwner);
                                          event OwnershipTransferred(
                                            address indexed previousOwner,
                                            address indexed newOwner
                                          );
                                        
                                        
                                          /**
                                           * @dev The Ownable constructor sets the original `owner` of the contract to the sender
                                           * account.
                                           */
                                          constructor() 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 relinquish control of the contract.
                                           * @notice Renouncing to ownership will leave the contract without an owner.
                                           * It will not be possible to call the functions with the `onlyOwner`
                                           * modifier anymore.
                                           */
                                          function renounceOwnership() public onlyOwner {
                                            emit OwnershipRenounced(owner);
                                            owner = address(0);
                                          }
                                        
                                          /**
                                           * @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 {
                                            _transferOwnership(_newOwner);
                                          }
                                        
                                          /**
                                           * @dev Transfers control of the contract to a newOwner.
                                           * @param _newOwner The address to transfer ownership to.
                                           */
                                          function _transferOwnership(address _newOwner) internal {
                                            require(_newOwner != address(0));
                                            emit OwnershipTransferred(owner, _newOwner);
                                            owner = _newOwner;
                                          }
                                        }
                                        
                                        // File: openzeppelin-solidity/contracts/math/SafeMath.sol
                                        
                                        pragma solidity ^0.4.24;
                                        
                                        
                                        /**
                                         * @title SafeMath
                                         * @dev Math operations with safety checks that throw on error
                                         */
                                        library SafeMath {
                                        
                                          /**
                                          * @dev Multiplies two numbers, throws on overflow.
                                          */
                                          function mul(uint256 _a, uint256 _b) internal pure returns (uint256 c) {
                                            // Gas optimization: this is cheaper than asserting 'a' not being zero, but the
                                            // benefit is lost if 'b' is also tested.
                                            // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
                                            if (_a == 0) {
                                              return 0;
                                            }
                                        
                                            c = _a * _b;
                                            assert(c / _a == _b);
                                            return c;
                                          }
                                        
                                          /**
                                          * @dev Integer division of two numbers, truncating the quotient.
                                          */
                                          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 _a / _b;
                                          }
                                        
                                          /**
                                          * @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend).
                                          */
                                          function sub(uint256 _a, uint256 _b) internal pure returns (uint256) {
                                            assert(_b <= _a);
                                            return _a - _b;
                                          }
                                        
                                          /**
                                          * @dev Adds two numbers, throws on overflow.
                                          */
                                          function add(uint256 _a, uint256 _b) internal pure returns (uint256 c) {
                                            c = _a + _b;
                                            assert(c >= _a);
                                            return c;
                                          }
                                        }
                                        
                                        // File: contracts/interfaces/ChainlinkRequestInterface.sol
                                        
                                        pragma solidity 0.4.24;
                                        
                                        interface ChainlinkRequestInterface {
                                          function oracleRequest(
                                            address sender,
                                            uint256 payment,
                                            bytes32 id,
                                            address callbackAddress,
                                            bytes4 callbackFunctionId,
                                            uint256 nonce,
                                            uint256 version,
                                            bytes data
                                          ) external;
                                        
                                          function cancelOracleRequest(
                                            bytes32 requestId,
                                            uint256 payment,
                                            bytes4 callbackFunctionId,
                                            uint256 expiration
                                          ) external;
                                        }
                                        
                                        // File: contracts/interfaces/OracleInterface.sol
                                        
                                        pragma solidity 0.4.24;
                                        
                                        interface OracleInterface {
                                          function fulfillOracleRequest(
                                            bytes32 requestId,
                                            uint256 payment,
                                            address callbackAddress,
                                            bytes4 callbackFunctionId,
                                            uint256 expiration,
                                            bytes32 data
                                          ) external returns (bool);
                                          function getAuthorizationStatus(address node) external view returns (bool);
                                          function setFulfillmentPermission(address node, bool allowed) external;
                                          function withdraw(address recipient, uint256 amount) external;
                                          function withdrawable() external view returns (uint256);
                                        }
                                        
                                        // File: contracts/interfaces/LinkTokenInterface.sol
                                        
                                        pragma solidity 0.4.24;
                                        
                                        interface LinkTokenInterface {
                                          function allowance(address owner, address spender) external returns (bool success);
                                          function approve(address spender, uint256 value) external returns (bool success);
                                          function balanceOf(address owner) external returns (uint256 balance);
                                          function decimals() external returns (uint8 decimalPlaces);
                                          function decreaseApproval(address spender, uint256 addedValue) external returns (bool success);
                                          function increaseApproval(address spender, uint256 subtractedValue) external;
                                          function name() external returns (string tokenName);
                                          function symbol() external returns (string tokenSymbol);
                                          function totalSupply() external returns (uint256 totalTokensIssued);
                                          function transfer(address to, uint256 value) external returns (bool success);
                                          function transferAndCall(address to, uint256 value, bytes data) external returns (bool success);
                                          function transferFrom(address from, address to, uint256 value) external returns (bool success);
                                        }
                                        
                                        // File: contracts/Oracle.sol
                                        
                                        pragma solidity 0.4.24;
                                        
                                        
                                        
                                        
                                        
                                        
                                        /**
                                         * @title The Chainlink Oracle contract
                                         * @notice Node operators can deploy this contract to fulfill requests sent to them
                                         */
                                        contract Oracle is ChainlinkRequestInterface, OracleInterface, Ownable {
                                          using SafeMath for uint256;
                                        
                                          uint256 constant public EXPIRY_TIME = 5 minutes;
                                          uint256 constant private MINIMUM_CONSUMER_GAS_LIMIT = 400000;
                                          // We initialize fields to 1 instead of 0 so that the first invocation
                                          // does not cost more gas.
                                          uint256 constant private ONE_FOR_CONSISTENT_GAS_COST = 1;
                                          uint256 constant private SELECTOR_LENGTH = 4;
                                          uint256 constant private EXPECTED_REQUEST_WORDS = 2;
                                          // solium-disable-next-line zeppelin/no-arithmetic-operations
                                          uint256 constant private MINIMUM_REQUEST_LENGTH = SELECTOR_LENGTH + (32 * EXPECTED_REQUEST_WORDS);
                                        
                                          LinkTokenInterface internal LinkToken;
                                          mapping(bytes32 => bytes32) private commitments;
                                          mapping(address => bool) private authorizedNodes;
                                          uint256 private withdrawableTokens = ONE_FOR_CONSISTENT_GAS_COST;
                                        
                                          event OracleRequest(
                                            bytes32 indexed specId,
                                            address requester,
                                            bytes32 requestId,
                                            uint256 payment,
                                            address callbackAddr,
                                            bytes4 callbackFunctionId,
                                            uint256 cancelExpiration,
                                            uint256 dataVersion,
                                            bytes data
                                          );
                                        
                                          event CancelOracleRequest(
                                            bytes32 indexed requestId
                                          );
                                        
                                          /**
                                           * @notice Deploy with the address of the LINK token
                                           * @dev Sets the LinkToken address for the imported LinkTokenInterface
                                           * @param _link The address of the LINK token
                                           */
                                          constructor(address _link) Ownable() public {
                                            LinkToken = LinkTokenInterface(_link);
                                          }
                                        
                                          /**
                                           * @notice Called when LINK is sent to the contract via `transferAndCall`
                                           * @dev The data payload's first 2 words will be overwritten by the `_sender` and `_amount`
                                           * values to ensure correctness. Calls oracleRequest.
                                           * @param _sender Address of the sender
                                           * @param _amount Amount of LINK sent (specified in wei)
                                           * @param _data Payload of the transaction
                                           */
                                          function onTokenTransfer(
                                            address _sender,
                                            uint256 _amount,
                                            bytes _data
                                          )
                                            public
                                            onlyLINK
                                            validRequestLength(_data)
                                            permittedFunctionsForLINK(_data)
                                          {
                                            assembly {
                                              // solium-disable-next-line security/no-low-level-calls
                                              mstore(add(_data, 36), _sender) // ensure correct sender is passed
                                              // solium-disable-next-line security/no-low-level-calls
                                              mstore(add(_data, 68), _amount)    // ensure correct amount is passed
                                            }
                                            // solium-disable-next-line security/no-low-level-calls
                                            require(address(this).delegatecall(_data), "Unable to create request"); // calls oracleRequest
                                          }
                                        
                                          /**
                                           * @notice Creates the Chainlink request
                                           * @dev Stores the hash of the params as the on-chain commitment for the request.
                                           * Emits OracleRequest event for the Chainlink node to detect.
                                           * @param _sender The sender of the request
                                           * @param _payment The amount of payment given (specified in wei)
                                           * @param _specId The Job Specification ID
                                           * @param _callbackAddress The callback address for the response
                                           * @param _callbackFunctionId The callback function ID for the response
                                           * @param _nonce The nonce sent by the requester
                                           * @param _dataVersion The specified data version
                                           * @param _data The CBOR payload of the request
                                           */
                                          function oracleRequest(
                                            address _sender,
                                            uint256 _payment,
                                            bytes32 _specId,
                                            address _callbackAddress,
                                            bytes4 _callbackFunctionId,
                                            uint256 _nonce,
                                            uint256 _dataVersion,
                                            bytes _data
                                          )
                                            external
                                            onlyLINK
                                            checkCallbackAddress(_callbackAddress)
                                          {
                                            bytes32 requestId = keccak256(abi.encodePacked(_sender, _nonce));
                                            require(commitments[requestId] == 0, "Must use a unique ID");
                                            uint256 expiration = now.add(EXPIRY_TIME);
                                        
                                            commitments[requestId] = keccak256(
                                              abi.encodePacked(
                                                _payment,
                                                _callbackAddress,
                                                _callbackFunctionId,
                                                expiration
                                              )
                                            );
                                        
                                            emit OracleRequest(
                                              _specId,
                                              _sender,
                                              requestId,
                                              _payment,
                                              _callbackAddress,
                                              _callbackFunctionId,
                                              expiration,
                                              _dataVersion,
                                              _data);
                                          }
                                        
                                          /**
                                           * @notice Called by the Chainlink node to fulfill requests
                                           * @dev Given params must hash back to the commitment stored from `oracleRequest`.
                                           * Will call the callback address' callback function without bubbling up error
                                           * checking in a `require` so that the node can get paid.
                                           * @param _requestId The fulfillment request ID that must match the requester's
                                           * @param _payment The payment amount that will be released for the oracle (specified in wei)
                                           * @param _callbackAddress The callback address to call for fulfillment
                                           * @param _callbackFunctionId The callback function ID to use for fulfillment
                                           * @param _expiration The expiration that the node should respond by before the requester can cancel
                                           * @param _data The data to return to the consuming contract
                                           * @return Status if the external call was successful
                                           */
                                          function fulfillOracleRequest(
                                            bytes32 _requestId,
                                            uint256 _payment,
                                            address _callbackAddress,
                                            bytes4 _callbackFunctionId,
                                            uint256 _expiration,
                                            bytes32 _data
                                          )
                                            external
                                            onlyAuthorizedNode
                                            isValidRequest(_requestId)
                                            returns (bool)
                                          {
                                            bytes32 paramsHash = keccak256(
                                              abi.encodePacked(
                                                _payment,
                                                _callbackAddress,
                                                _callbackFunctionId,
                                                _expiration
                                              )
                                            );
                                            require(commitments[_requestId] == paramsHash, "Params do not match request ID");
                                            withdrawableTokens = withdrawableTokens.add(_payment);
                                            delete commitments[_requestId];
                                            require(gasleft() >= MINIMUM_CONSUMER_GAS_LIMIT, "Must provide consumer enough gas");
                                            // All updates to the oracle's fulfillment should come before calling the
                                            // callback(addr+functionId) as it is untrusted.
                                            // See: https://solidity.readthedocs.io/en/develop/security-considerations.html#use-the-checks-effects-interactions-pattern
                                            return _callbackAddress.call(_callbackFunctionId, _requestId, _data); // solium-disable-line security/no-low-level-calls
                                          }
                                        
                                          /**
                                           * @notice Use this to check if a node is authorized for fulfilling requests
                                           * @param _node The address of the Chainlink node
                                           * @return The authorization status of the node
                                           */
                                          function getAuthorizationStatus(address _node) external view returns (bool) {
                                            return authorizedNodes[_node];
                                          }
                                        
                                          /**
                                           * @notice Sets the fulfillment permission for a given node. Use `true` to allow, `false` to disallow.
                                           * @param _node The address of the Chainlink node
                                           * @param _allowed Bool value to determine if the node can fulfill requests
                                           */
                                          function setFulfillmentPermission(address _node, bool _allowed) external onlyOwner {
                                            authorizedNodes[_node] = _allowed;
                                          }
                                        
                                          /**
                                           * @notice Allows the node operator to withdraw earned LINK to a given address
                                           * @dev The owner of the contract can be another wallet and does not have to be a Chainlink node
                                           * @param _recipient The address to send the LINK token to
                                           * @param _amount The amount to send (specified in wei)
                                           */
                                          function withdraw(address _recipient, uint256 _amount)
                                            external
                                            onlyOwner
                                            hasAvailableFunds(_amount)
                                          {
                                            withdrawableTokens = withdrawableTokens.sub(_amount);
                                            assert(LinkToken.transfer(_recipient, _amount));
                                          }
                                        
                                          /**
                                           * @notice Displays the amount of LINK that is available for the node operator to withdraw
                                           * @dev We use `ONE_FOR_CONSISTENT_GAS_COST` in place of 0 in storage
                                           * @return The amount of withdrawable LINK on the contract
                                           */
                                          function withdrawable() external view onlyOwner returns (uint256) {
                                            return withdrawableTokens.sub(ONE_FOR_CONSISTENT_GAS_COST);
                                          }
                                        
                                          /**
                                           * @notice Allows requesters to cancel requests sent to this oracle contract. Will transfer the LINK
                                           * sent for the request back to the requester's address.
                                           * @dev Given params must hash to a commitment stored on the contract in order for the request to be valid
                                           * Emits CancelOracleRequest event.
                                           * @param _requestId The request ID
                                           * @param _payment The amount of payment given (specified in wei)
                                           * @param _callbackFunc The requester's specified callback address
                                           * @param _expiration The time of the expiration for the request
                                           */
                                          function cancelOracleRequest(
                                            bytes32 _requestId,
                                            uint256 _payment,
                                            bytes4 _callbackFunc,
                                            uint256 _expiration
                                          ) external {
                                            bytes32 paramsHash = keccak256(
                                              abi.encodePacked(
                                                _payment,
                                                msg.sender,
                                                _callbackFunc,
                                                _expiration)
                                            );
                                            require(paramsHash == commitments[_requestId], "Params do not match request ID");
                                            require(_expiration <= now, "Request is not expired");
                                        
                                            delete commitments[_requestId];
                                            emit CancelOracleRequest(_requestId);
                                        
                                            assert(LinkToken.transfer(msg.sender, _payment));
                                          }
                                        
                                          // MODIFIERS
                                        
                                          /**
                                           * @dev Reverts if amount requested is greater than withdrawable balance
                                           * @param _amount The given amount to compare to `withdrawableTokens`
                                           */
                                          modifier hasAvailableFunds(uint256 _amount) {
                                            require(withdrawableTokens >= _amount.add(ONE_FOR_CONSISTENT_GAS_COST), "Amount requested is greater than withdrawable balance");
                                            _;
                                          }
                                        
                                          /**
                                           * @dev Reverts if request ID does not exist
                                           * @param _requestId The given request ID to check in stored `commitments`
                                           */
                                          modifier isValidRequest(bytes32 _requestId) {
                                            require(commitments[_requestId] != 0, "Must have a valid requestId");
                                            _;
                                          }
                                        
                                          /**
                                           * @dev Reverts if `msg.sender` is not authorized to fulfill requests
                                           */
                                          modifier onlyAuthorizedNode() {
                                            require(authorizedNodes[msg.sender] || msg.sender == owner, "Not an authorized node to fulfill requests");
                                            _;
                                          }
                                        
                                          /**
                                           * @dev Reverts if not sent from the LINK token
                                           */
                                          modifier onlyLINK() {
                                            require(msg.sender == address(LinkToken), "Must use LINK token");
                                            _;
                                          }
                                        
                                          /**
                                           * @dev Reverts if the given data does not begin with the `oracleRequest` function selector
                                           * @param _data The data payload of the request
                                           */
                                          modifier permittedFunctionsForLINK(bytes _data) {
                                            bytes4 funcSelector;
                                            assembly {
                                              // solium-disable-next-line security/no-low-level-calls
                                              funcSelector := mload(add(_data, 32))
                                            }
                                            require(funcSelector == this.oracleRequest.selector, "Must use whitelisted functions");
                                            _;
                                          }
                                        
                                          /**
                                           * @dev Reverts if the callback address is the LINK token
                                           * @param _to The callback address
                                           */
                                          modifier checkCallbackAddress(address _to) {
                                            require(_to != address(LinkToken), "Cannot callback to LINK");
                                            _;
                                          }
                                        
                                          /**
                                           * @dev Reverts if the given payload is less than needed to create a request
                                           * @param _data The request payload
                                           */
                                          modifier validRequestLength(bytes _data) {
                                            require(_data.length >= MINIMUM_REQUEST_LENGTH, "Invalid request length");
                                            _;
                                          }
                                        
                                        }