Forkchoice Ethereum Mainnet

Address Contract Partially Verified

Address 0x0563fC575D5219C48E2Dfc20368FA4179cDF320D
Balance 0 ETH
Nonce 1
Code Size 10594 bytes
Indexed Transactions 0 (1 on-chain, 0.8% indexed)
External Etherscan · Sourcify

Contract Bytecode

10594 bytes
0x608060405234801561001057600080fd5b50600436106100b45760003560e01c80638da5cb5b116100715780638da5cb5b146103425780638dc654a21461034a5780638f32d59b14610352578063a4c0ed361461035a578063af52c98114610413578063f2fde38b14610523576100b4565b8063165d35e1146100b95780633a4a660b146100dd57806340429946146100fc5780636a9705b4146101ab5780636ee4d553146101e2578063834b55e01461021b575b600080fd5b6100c1610549565b604080516001600160a01b039092168252519081900360200190f35b6100fa600480360360208110156100f357600080fd5b5035610559565b005b6100fa600480360361010081101561011357600080fd5b6001600160a01b038235811692602081013592604082013592606083013516916001600160e01b03196080820135169160a08201359160c081013591810190610100810160e0820135600160201b81111561016d57600080fd5b82018360208201111561017f57600080fd5b803590602001918460018302840111600160201b831117156101a057600080fd5b509092509050610680565b6101ce600480360360408110156101c157600080fd5b5080359060200135610a0b565b604080519115158252519081900360200190f35b6100fa600480360360808110156101f857600080fd5b508035906020810135906001600160e01b03196040820135169060600135610dba565b6103306004803603608081101561023157600080fd5b81359190810190604081016020820135600160201b81111561025257600080fd5b82018360208201111561026457600080fd5b803590602001918460208302840111600160201b8311171561028557600080fd5b919390929091602081019035600160201b8111156102a257600080fd5b8201836020820111156102b457600080fd5b803590602001918460208302840111600160201b831117156102d557600080fd5b919390929091602081019035600160201b8111156102f257600080fd5b82018360208201111561030457600080fd5b803590602001918460208302840111600160201b8311171561032557600080fd5b50909250905061102a565b60408051918252519081900360200190f35b6100c16113b1565b6100fa6113c0565b6101ce611556565b6100fa6004803603606081101561037057600080fd5b6001600160a01b0382351691602081013591810190606081016040820135600160201b81111561039f57600080fd5b8201836020820111156103b157600080fd5b803590602001918460018302840111600160201b831117156103d257600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550611567945050505050565b6104306004803603602081101561042957600080fd5b503561178b565b60405180878152602001868152602001858152602001806020018060200180602001848103845287818151815260200191508051906020019060200280838360005b8381101561048a578181015183820152602001610472565b50505050905001848103835286818151815260200191508051906020019060200280838360005b838110156104c95781810151838201526020016104b1565b50505050905001848103825285818151815260200191508051906020019060200280838360005b838110156105085781810151838201526020016104f0565b50505050905001995050505050505050505060405180910390f35b6100fa6004803603602081101561053957600080fd5b50356001600160a01b03166118d7565b6000610553611927565b90505b90565b610561611556565b6105a0576040805162461bcd60e51b815260206004820181905260248201526000805160206128e6833981519152604482015290519081900360640190fd5b600081815260086020526040902060020154819015610606576040805162461bcd60e51b815260206004820152601a60248201527f43616e6e6f742064656c657465207768696c6520616374697665000000000000604482015290519081900360640190fd5b600082815260086020526040812081815560018101829055600281018290559061063360038301826126c8565b6106416004830160006126c8565b61064f6005830160006126c8565b505060405182907f227c06e698a75d1029f6c20a48aca0d218abffbdf5ce0ebd117d2de93cfc6db290600090a25050565b610688610549565b6001600160a01b0316336001600160a01b0316146106e3576040805162461bcd60e51b815260206004820152601360248201527226bab9ba103ab9b2902624a725903a37b5b2b760691b604482015290519081900360640190fd5b856106ec611927565b6001600160a01b0316816001600160a01b03161415610752576040805162461bcd60e51b815260206004820152601760248201527f43616e6e6f742063616c6c6261636b20746f204c494e4b000000000000000000604482015290519081900360640190fd5b600088815260086020526040902054808a10156107ad576040805162461bcd60e51b8152602060048201526014602482015273125b9cdd59999a58da595b9d081c185e5b595b9d60621b604482015290519081900360640190fd5b604080516bffffffffffffffffffffffff1960608e901b1660208083019190915260348083018a905283518084039091018152605490920183528151918101919091206000818152600a90925291902054600160201b90046001600160a01b031615610857576040805162461bcd60e51b81526020600482015260146024820152734e6f6e636520616c726561647920696e2d75736560601b604482015290519081900360640190fd5b87600a600083815260200190815260200160002060000160006101000a81548163ffffffff021916908360e01c021790555088600a600083815260200190815260200160002060010160006101000a8154816001600160a01b0302191690836001600160a01b031602179055508b600a600083815260200190815260200160002060000160046101000a8154816001600160a01b0302191690836001600160a01b031602179055506109408a8287878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061193692505050565b818b11156109fd57600061095a8c8463ffffffff611c0316565b90506000610966611927565b9050806001600160a01b031663a9059cbb8f846040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600087803b1580156109c857600080fd5b505af11580156109dc573d6000803e3d6000fd5b505050506040513d60208110156109f257600080fd5b50516109fa57fe5b50505b505050505050505050505050565b60008281526005602052604081205483906001600160a01b03163314610a625760405162461bcd60e51b81526004018080602001828103825260288152602001806129066028913960400191505060405180910390fd5b60008181526005602052604080822080546001600160a01b03191690555182917f7cc135e0cebb02c3480ae5d74d377283180a2601f8f644edf7987b009316c63a91a26000848152600960208181526040808420805480865260088452828620600101548a8752600b8552838720805490889055958552959091558151888152915190923392859285927f6bd4bffa5426494ba16814dba4b1994c92f88f7664ad231cf8aa811fff6e925e928290030190a46000828152600a6020908152604082206002018054600181018083559184529190922001879055831415610dab57600081815260086020526040902060020154610b6590600163ffffffff611c0316565b600082815260086020526040902060020155610b7f6126e6565b6000838152600a6020908152604091829020825160808101845281546001600160e01b031960e082901b1682526001600160a01b03600160201b909104811682850152600183015416818501526002820180548551818602810186019096528086529194929360608601939290830182828015610c1b57602002820191906000526020600020905b815481526020019060010190808311610c07575b505050919092525050506000848152600a6020526040812080546001600160c01b03191681556001810180546001600160a01b0319169055919250610c6360028301826126c8565b50506000610c748260600151611c65565b905083837fe991444bc589ce1a82e7cbe4e5ebaa8aaa2a5c44964bd32d2af07dd846a638ba836040518082815260200191505060405180910390a36040808301518351825160248101889052604480820186905284518083039091018152606490910184526020810180516001600160e01b03166001600160e01b0319909316929092178252925183516000946001600160a01b03909416939282918083835b60208310610d335780518252601f199092019160209182019101610d14565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114610d95576040519150601f19603f3d011682016040523d82523d6000602084013e610d9a565b606091505b50909850610db39650505050505050565b600194505050505b5092915050565b6000848152600b602090815260408083208054908490556009909252822091909155610de46126e6565b6000828152600a6020908152604091829020825160808101845281546001600160e01b031960e082901b1682526001600160a01b03600160201b909104811682850152600183015416818501526002820180548551818602810186019096528086529194929360608601939290830182828015610e8057602002820191906000526020600020905b815481526020019060010190808311610e6c575b5050505050815250509050336001600160a01b031681602001516001600160a01b031614610ef5576040805162461bcd60e51b815260206004820152601960248201527f4f6e6c79207265717565737465722063616e2063616e63656c00000000000000604482015290519081900360640190fd5b6000828152600a6020526040812080546001600160c01b03191681556001810180546001600160a01b031916905590610f3160028301826126c8565b5050610f3f86868686611d1a565b6000610f49611927565b9050806001600160a01b031663a9059cbb8360200151886040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050602060405180830381600087803b158015610faf57600080fd5b505af1158015610fc3573d6000803e3d6000fd5b505050506040513d6020811015610fd957600080fd5b5051611021576040805162461bcd60e51b81526020600482015260126024820152712ab730b13632903a37903a3930b739b332b960711b604482015290519081900360640190fd5b50505050505050565b6000611034611556565b611073576040805162461bcd60e51b815260206004820181905260248201526000805160206128e6833981519152604482015290519081900360640190fd5b600088116110c8576040805162461bcd60e51b815260206004820152601960248201527f4d696e20726573706f6e736573206d757374206265203e203000000000000000604482015290519081900360640190fd5b85841480156110d657508582145b611116576040805162461bcd60e51b815260206004820152600c60248201526b0aadcdacae840d8cadccee8d60a31b604482015290519081900360640190fd5b602d86111561116c576040805162461bcd60e51b815260206004820181905260248201527f43616e6e6f742068617665206d6f7265207468616e203435206f7261636c6573604482015290519081900360640190fd5b878610156111b9576040805162461bcd60e51b8152602060048201526015602482015274496e76616c6964206d696e20726573706f6e73657360581b604482015290519081900360640190fd5b6000805b838110156111f4576111ea8585838181106111d457fe5b9050602002013583611df290919063ffffffff16565b91506001016111bd565b5060078054604080516020808201849052428284015282518083038401815260608301808552815191830191909120600190950190955561012082018352858552608082018e9052600060a083015282518c820281810183019094528c815293965060c090910192918c918c91829185019084908082843760009201919091525050509082525060408051602089810282810182019093528982529283019290918a918a9182918501908490808284376000920191909152505050908252506040805160208781028281018201909352878252928301929091889188918291850190849080828437600092018290525093909452505084815260086020908152604091829020845181558482015160018201559184015160028301556060840151805192935061132d926003850192919091019061270c565b5060808201518051611349916004840191602090910190612771565b5060a08201518051611365916005840191602090910190612771565b505060408051838152602081018c905281518593507f1df950b8dca286fff2ebb83642851b5a9db00ff4bc87815828e845b45d183eaf929181900390910190a250979650505050505050565b6006546001600160a01b031690565b6113c8611556565b611407576040805162461bcd60e51b815260206004820181905260248201526000805160206128e6833981519152604482015290519081900360640190fd5b6000611411611927565b604080516370a0823160e01b815230600482015290519192506001600160a01b0383169163a9059cbb91339184916370a082319160248083019260209291908290030181600087803b15801561146657600080fd5b505af115801561147a573d6000803e3d6000fd5b505050506040513d602081101561149057600080fd5b5051604080516001600160e01b031960e086901b1681526001600160a01b03909316600484015260248301919091525160448083019260209291908290030181600087803b1580156114e157600080fd5b505af11580156114f5573d6000803e3d6000fd5b505050506040513d602081101561150b57600080fd5b5051611553576040805162461bcd60e51b81526020600482015260126024820152712ab730b13632903a37903a3930b739b332b960711b604482015290519081900360640190fd5b50565b6006546001600160a01b0316331490565b61156f610549565b6001600160a01b0316336001600160a01b0316146115ca576040805162461bcd60e51b815260206004820152601360248201527226bab9ba103ab9b2902624a725903a37b5b2b760691b604482015290519081900360640190fd5b805181906044111561161c576040805162461bcd60e51b8152602060048201526016602482015275092dcecc2d8d2c840e4cae2eacae6e840d8cadccee8d60531b604482015290519081900360640190fd5b602082015182906001600160e01b031981166320214ca360e11b14611688576040805162461bcd60e51b815260206004820152601e60248201527f4d757374207573652077686974656c69737465642066756e6374696f6e730000604482015290519081900360640190fd5b8560248501528460448501526000306001600160a01b0316856040518082805190602001908083835b602083106116d05780518252601f1990920191602091820191016116b1565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855af49150503d8060008114611730576040519150601f19603f3d011682016040523d82523d6000602084013e611735565b606091505b5050905080611021576040805162461bcd60e51b815260206004820152601860248201527f556e61626c6520746f2063726561746520726571756573740000000000000000604482015290519081900360640190fd5b600081815260086020908152604080832080546001820154600283015460038401805486518189028101890190975280875288978897606097889788979096909590949093600483019360059093019291859183018282801561181757602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116117f9575b505050505092508180548060200260200160405190810160405280929190818152602001828054801561186957602002820191906000526020600020905b815481526020019060010190808311611855575b50505050509150808054806020026020016040519081016040528092919081815260200182805480156118bb57602002820191906000526020600020905b8154815260200190600101908083116118a7575b5050505050905095509550955095509550955091939550919395565b6118df611556565b61191e576040805162461bcd60e51b815260206004820181905260248201526000805160206128e6833981519152604482015290519081900360640190fd5b61155381611e53565b6002546001600160a01b031690565b61193e6127b8565b600084815260086020908152604091829020825160c0810184528154815260018201548184015260028201548185015260038201805485518186028101860190965280865291949293606086019392908301828280156119c757602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116119a9575b5050505050815260200160048201805480602002602001604051908101604052809291908181526020018280548015611a1f57602002820191906000526020600020905b815481526020019060010190808311611a0b575b5050505050815260200160058201805480602002602001604051908101604052809291908181526020018280548015611a7757602002820191906000526020600020905b815481526020019060010190808311611a63575b50505050508152505090506000816020015111611adb576040805162461bcd60e51b815260206004820152601960248201527f496e76616c696420736572766963652061677265656d656e7400000000000000604482015290519081900360640190fd5b611ae36127ee565b600085815260086020526040812060020154611b0690600163ffffffff611df216565b60008781526008602090815260409182902060020192909255845181519081529051879289927f0d3e7811af83862cbc3778c66d787596cdb580e0dbc448d99f21c865770a8432929081900390910190a360005b83606001515181101561102157611b9084608001518281518110611b7a57fe5b602002602001015130636a9705b460e01b611ef4565b9250611ba2838663ffffffff611f1f16565b611bdb84606001518281518110611bb557fe5b6020026020010151848660a001518481518110611bce57fe5b6020026020010151611f42565b6000818152600b602090815260408083208a9055600990915290208890559150600101611b5a565b600082821115611c5a576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b508082035b92915050565b805160009081611c7c82600263ffffffff61211916565b905060028206611cfb576000611c9a611c9486612183565b836121f3565b90506000611cb886611cb385600163ffffffff611df216565b6121f3565b90506000600280840781840701059050611cef81611ce360028505600287059063ffffffff6123c616565b9063ffffffff6123c616565b95505050505050611d15565b611d1084611cb383600163ffffffff611df216565b925050505b919050565b60008481526005602052604080822080546001600160a01b0319811690915590516001600160a01b039091169186917fe1fe3afa0f7f761ff0a8b89086790efd5140d2907ebd5b7ff6bfcb5e075fd4c59190a260408051636ee4d55360e01b815260048101879052602481018690526001600160e01b0319851660448201526064810184905290516001600160a01b03831691636ee4d55391608480830192600092919082900301818387803b158015611dd357600080fd5b505af1158015611de7573d6000803e3d6000fd5b505050505050505050565b600082820183811015611e4c576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b9392505050565b6001600160a01b038116611e985760405162461bcd60e51b815260040180806020018281038252602681526020018061287c6026913960400191505060405180910390fd5b6006546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3600680546001600160a01b0319166001600160a01b0392909216919091179055565b611efc6127ee565b611f046127ee565b611f168186868663ffffffff61242b16565b95945050505050565b611f2e82608001518251612468565b50611f3d8260800151826124a2565b505050565b6004546040805130606090811b60208084019190915260348084018690528451808503909101815260549093018452825192810192909220908601939093526000838152600590915281812080546001600160a01b0319166001600160a01b038816179055905182917fb5e6e01e79f91267dc17b4e6314d5d4d03593d2ceee0fbb452b750bd70ea5af991a26002546001600160a01b0316634000aea08584611fea876124bc565b6040518463ffffffff1660e01b815260040180846001600160a01b03166001600160a01b0316815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b8381101561205457818101518382015260200161203c565b50505050905090810190601f1680156120815780820380516001836020036101000a031916815260200191505b50945050505050602060405180830381600087803b1580156120a257600080fd5b505af11580156120b6573d6000803e3d6000fd5b505050506040513d60208110156120cc57600080fd5b50516121095760405162461bcd60e51b81526004018080602001828103825260238152602001806128a26023913960400191505060405180910390fd5b6004805460010190559392505050565b600080821161216f576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b600082848161217a57fe5b04949350505050565b60608082516040519080825280602002602001820160405280156121b1578160200160208202803883390190505b50905060005b8351811015610db3578381815181106121cc57fe5b60200260200101518282815181106121e057fe5b60209081029190910101526001016121b7565b81516040805182815260208084028201019091526000918491849190606090828015612229578160200160208202803883390190505b509050606082604051908082528060200260200182016040528015612258578160200160208202803883390190505b5090506000806000805b8861227488600263ffffffff61211916565b8151811061227e57fe5b602002602001015191506000935060009250600090505b8681101561234357818982815181106122aa57fe5b602002602001015112156122ee578881815181106122c457fe5b60200260200101518685815181106122d857fe5b602090810291909101015260019093019261233b565b818982815181106122fb57fe5b6020026020010151131561233b5788818151811061231557fe5b602002602001015185848151811061232957fe5b60209081029190910101526001909201915b600101612295565b8388116123615783965061235789876125e5565b90995095506123c1565b612371878463ffffffff611c0316565b8811156123b15761239861238b888563ffffffff611c0316565b899063ffffffff611c0316565b97508296506123a789866125e5565b90995094506123c1565b509750611c5f9650505050505050565b612262565b60008282018183128015906123db5750838112155b806123f057506000831280156123f057508381125b611e4c5760405162461bcd60e51b81526004018080602001828103825260218152602001806128c56021913960400191505060405180910390fd5b6124336127ee565b6124438560800151610100612468565b50509183526001600160a01b031660208301526001600160e01b031916604082015290565b612470612823565b60208206156124855760208206602003820191505b506020828101829052604080518085526000815290920101905290565b6124aa612823565b611e4c838460000151518485516125e8565b8051602080830151604080850151606086810151608088015151935160006024820181815260448301829052606483018a90526001600160a01b03881660848401526001600160e01b0319861660a484015260c48301849052600160e48401819052610100610104850190815288516101248601528851969b6320214ca360e11b9b949a8b9a91999098909796939591949361014401918501908083838e5b8381101561257357818101518382015260200161255b565b50505050905090810190601f1680156125a05780820380516001836020036101000a031916815260200191505b5060408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909d169c909c17909b5250989950505050505050505050919050565b91565b6125f0612823565b82518211156125fe57600080fd5b8460200151828501111561262857612628856126208760200151878601612694565b6002026126ab565b6000808651805187602083010193508088870111156126475787860182525b505050602084015b6020841061266e5780518252601f19909301926020918201910161264f565b51815160001960208690036101000a019081169019919091161790525083949350505050565b6000818311156126a5575081611c5f565b50919050565b81516126b78383612468565b506126c283826124a2565b50505050565b5080546000825590600052602060002090810190611553919061283d565b604080516080810182526000808252602082018190529181019190915260608082015290565b828054828255906000526020600020908101928215612761579160200282015b8281111561276157825182546001600160a01b0319166001600160a01b0390911617825560209092019160019091019061272c565b5061276d929150612857565b5090565b8280548282559060005260206000209081019282156127ac579160200282015b828111156127ac578251825591602001919060010190612791565b5061276d92915061283d565b6040518060c001604052806000815260200160008152602001600081526020016060815260200160608152602001606081525090565b6040805160a08101825260008082526020820181905291810182905260608101919091526080810161281e612823565b905290565b604051806040016040528060608152602001600081525090565b61055691905b8082111561276d5760008155600101612843565b61055691905b8082111561276d5780546001600160a01b031916815560010161285d56fe4f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373756e61626c6520746f207472616e73666572416e6443616c6c20746f206f7261636c655369676e6564536166654d6174683a206164646974696f6e206f766572666c6f774f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572536f75726365206d75737420626520746865206f7261636c65206f66207468652072657175657374a265627a7a7231582016334d96e8181daa2247033917c2af27a705dc5c6ab737b3f730482c9c23913e64736f6c634300050d0032

Verified Source Code Partial Match

Compiler: v0.5.13+commit.5b0b510c EVM: petersburg Optimization: Yes (200 runs)
PreCoordinator.sol 1548 lines
// File: contracts/vendor/Buffer.sol

pragma solidity ^0.5.0;

/**
* @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);
  }
}

// File: contracts/vendor/CBOR.sol

pragma solidity ^0.5.0;


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 memory value) internal pure {
    encodeType(buf, MAJOR_TYPE_BYTES, value.length);
    buf.append(value);
  }

  function encodeString(Buffer.buffer memory buf, string memory 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);
  }
}

// File: contracts/Chainlink.sol

pragma solidity ^0.5.0;


/**
 * @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 memory _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 memory _key, string memory _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 memory _key, bytes memory _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 memory _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 memory _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 memory _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();
  }
}

// File: contracts/interfaces/ENSInterface.sol

pragma solidity ^0.5.0;

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);

}

// File: contracts/interfaces/LinkTokenInterface.sol

pragma solidity ^0.5.0;

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 memory tokenName);
  function symbol() external returns (string memory tokenSymbol);
  function totalSupply() external returns (uint256 totalTokensIssued);
  function transfer(address to, uint256 value) external returns (bool success);
  function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool success);
  function transferFrom(address from, address to, uint256 value) external returns (bool success);
}

// File: contracts/interfaces/ChainlinkRequestInterface.sol

pragma solidity ^0.5.0;

interface ChainlinkRequestInterface {
  function oracleRequest(
    address sender,
    uint256 requestPrice,
    bytes32 serviceAgreementID,
    address callbackAddress,
    bytes4 callbackFunctionId,
    uint256 nonce,
    uint256 dataVersion, // Currently unused, always "1"
    bytes calldata data
  ) external;

  function cancelOracleRequest(
    bytes32 requestId,
    uint256 payment,
    bytes4 callbackFunctionId,
    uint256 expiration
  ) external;
}

// File: contracts/interfaces/PointerInterface.sol

pragma solidity ^0.5.0;

interface PointerInterface {
  function getAddress() external view returns (address);
}

// File: contracts/vendor/ENSResolver.sol

pragma solidity ^0.5.0;

contract ENSResolver {
  function addr(bytes32 node) public view returns (address);
}

// File: contracts/vendor/SafeMath.sol

pragma solidity ^0.5.0;

/**
 * @dev Wrappers over Solidity's arithmetic operations with added overflow
 * checks.
 *
 * Arithmetic operations in Solidity wrap on overflow. This can easily result
 * in bugs, because programmers usually assume that an overflow raises an
 * error, which is the standard behavior in high level programming languages.
 * `SafeMath` restores this intuition by reverting the transaction when an
 * operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 */
library SafeMath {
  /**
    * @dev Returns the addition of two unsigned integers, reverting on
    * overflow.
    *
    * Counterpart to Solidity's `+` operator.
    *
    * Requirements:
    * - Addition cannot overflow.
    */
  function add(uint256 a, uint256 b) internal pure returns (uint256) {
    uint256 c = a + b;
    require(c >= a, "SafeMath: addition overflow");

    return c;
  }

  /**
    * @dev Returns the subtraction of two unsigned integers, reverting on
    * overflow (when the result is negative).
    *
    * Counterpart to Solidity's `-` operator.
    *
    * Requirements:
    * - Subtraction cannot overflow.
    */
  function sub(uint256 a, uint256 b) internal pure returns (uint256) {
    require(b <= a, "SafeMath: subtraction overflow");
    uint256 c = a - b;

    return c;
  }

  /**
    * @dev Returns the multiplication of two unsigned integers, reverting on
    * overflow.
    *
    * Counterpart to Solidity's `*` operator.
    *
    * Requirements:
    * - Multiplication cannot overflow.
    */
  function mul(uint256 a, uint256 b) internal pure returns (uint256) {
    // Gas optimization: this is cheaper than requiring '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;
    }

    uint256 c = a * b;
    require(c / a == b, "SafeMath: multiplication overflow");

    return c;
  }

  /**
    * @dev Returns the integer division of two unsigned integers. Reverts on
    * division by zero. The result is rounded towards zero.
    *
    * Counterpart to Solidity's `/` operator. Note: this function uses a
    * `revert` opcode (which leaves remaining gas untouched) while Solidity
    * uses an invalid opcode to revert (consuming all remaining gas).
    *
    * Requirements:
    * - The divisor cannot be zero.
    */
  function div(uint256 a, uint256 b) internal pure returns (uint256) {
    // Solidity only automatically asserts when dividing by 0
    require(b > 0, "SafeMath: division by zero");
    uint256 c = a / b;
    // assert(a == b * c + a % b); // There is no case in which this doesn't hold

    return c;
  }

  /**
    * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
    * Reverts when dividing by zero.
    *
    * Counterpart to Solidity's `%` operator. This function uses a `revert`
    * opcode (which leaves remaining gas untouched) while Solidity uses an
    * invalid opcode to revert (consuming all remaining gas).
    *
    * Requirements:
    * - The divisor cannot be zero.
    */
  function mod(uint256 a, uint256 b) internal pure returns (uint256) {
    require(b != 0, "SafeMath: modulo by zero");
    return a % b;
  }
}

// File: contracts/ChainlinkClient.sol

pragma solidity ^0.5.0;








/**
 * @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 = address(0);
  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 requestCount = 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(address(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, requestCount));
    _req.nonce = requestCount;
    pendingRequests[requestId] = _oracle;
    emit ChainlinkRequested(requestId);
    require(link.transferAndCall(_oracle, _payment, encodeRequest(_req)), "unable to transferAndCall to oracle");
    requestCount += 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");
    _;
  }
}

// File: contracts/LinkTokenReceiver.sol

pragma solidity ^0.5.0;

contract LinkTokenReceiver {

  bytes4 constant private ORACLE_REQUEST_SELECTOR = 0x40429946;
  uint256 constant private SELECTOR_LENGTH = 4;
  uint256 constant private EXPECTED_REQUEST_WORDS = 2;
  uint256 constant private MINIMUM_REQUEST_LENGTH = SELECTOR_LENGTH + (32 * EXPECTED_REQUEST_WORDS);
  /**
   * @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 memory _data
  )
    public
    onlyLINK
    validRequestLength(_data)
    permittedFunctionsForLINK(_data)
  {
    assembly {
      // solhint-disable-next-line avoid-low-level-calls
      mstore(add(_data, 36), _sender) // ensure correct sender is passed
      // solhint-disable-next-line avoid-low-level-calls
      mstore(add(_data, 68), _amount)    // ensure correct amount is passed
    }
    // solhint-disable-next-line avoid-low-level-calls
    (bool success, ) = address(this).delegatecall(_data); // calls oracleRequest
    require(success, "Unable to create request");
  }

  function getChainlinkToken() public view returns (address);

  /**
   * @dev Reverts if not sent from the LINK token
   */
  modifier onlyLINK() {
    require(msg.sender == getChainlinkToken(), "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 memory _data) {
    bytes4 funcSelector;
    assembly {
      // solhint-disable-next-line avoid-low-level-calls
      funcSelector := mload(add(_data, 32))
    }
    require(funcSelector == ORACLE_REQUEST_SELECTOR, "Must use whitelisted functions");
    _;
  }

  /**
   * @dev Reverts if the given payload is less than needed to create a request
   * @param _data The request payload
   */
  modifier validRequestLength(bytes memory _data) {
    require(_data.length >= MINIMUM_REQUEST_LENGTH, "Invalid request length");
    _;
  }
}

// File: contracts/vendor/SignedSafeMath.sol

pragma solidity ^0.5.0;

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)
  {
    // solium-disable-next-line zeppelin/no-arithmetic-operations
    int256 c = _a + _b;
    require((_b >= 0 && c >= _a) || (_b < 0 && c < _a), "SignedSafeMath: addition overflow");

    return c;
  }
}

// File: contracts/Median.sol

pragma solidity ^0.5.0;



library Median {
  using SafeMath for uint256;
  using SignedSafeMath for int256;

  /**
   * @dev Returns the sorted middle, or the average of the two middle indexed 
   * items if the array has an even number of elements
   * @param _list The list of elements to compare
   */
  function calculate(int256[] memory _list)
    internal
    returns (int256)
  {
    uint256 answerLength = _list.length;
    uint256 middleIndex = answerLength.div(2);
    if (answerLength % 2 == 0) {
      int256 median1 = quickselect(copy(_list), middleIndex);
      int256 median2 = quickselect(_list, middleIndex.add(1)); // quickselect is 1 indexed
      int256 remainder = (median1 % 2 + median2 % 2) / 2;
      return (median1 / 2).add(median2 / 2).add(remainder); // signed integers are not supported by SafeMath
    } else {
      return quickselect(_list, middleIndex.add(1)); // quickselect is 1 indexed
    }
  }

  /**
   * @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 Makes an in memory copy of the array passed in
   * @param _list The pointer to the array to be copied
   */
  function copy(int256[] memory _list)
    private
    pure
    returns(int256[] memory)
  {
    int256[] memory list2 = new int256[](_list.length);
    for (uint256 i = 0; i < _list.length; i++) {
      list2[i] = _list[i];
    }
    return list2;
  }

}

// File: contracts/vendor/Ownable.sol

pragma solidity ^0.5.0;

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be aplied to your functions to restrict their use to
 * the owner.
 *
 * This contract has been modified to remove the revokeOwnership function
 */
contract Ownable {
  address private _owner;

  event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

  /**
   * @dev Initializes the contract setting the deployer as the initial owner.
   */
  constructor () internal {
    _owner = msg.sender;
    emit OwnershipTransferred(address(0), _owner);
  }

  /**
   * @dev Returns the address of the current owner.
   */
  function owner() public view returns (address) {
    return _owner;
  }

  /**
   * @dev Throws if called by any account other than the owner.
   */
  modifier onlyOwner() {
    require(isOwner(), "Ownable: caller is not the owner");
    _;
  }

  /**
   * @dev Returns true if the caller is the current owner.
   */
  function isOwner() public view returns (bool) {
    return msg.sender == _owner;
  }

  /**
   * @dev Transfers ownership of the contract to a new account (`newOwner`).
   * Can only be called by the current owner.
   */
  function transferOwnership(address newOwner) public onlyOwner {
    _transferOwnership(newOwner);
  }

  /**
   * @dev Transfers ownership of the contract to a new account (`newOwner`).
   */
  function _transferOwnership(address newOwner) internal {
    require(newOwner != address(0), "Ownable: new owner is the zero address");
    emit OwnershipTransferred(_owner, newOwner);
    _owner = newOwner;
  }
}

// File: contracts/PreCoordinator.sol

pragma solidity ^0.5.0;






/**
 * @title PreCoordinator is a contract that builds on-chain service agreements
 * using the current architecture of 1 request to 1 oracle contract.
 * @dev This contract accepts requests as service agreement IDs and loops over
 * the corresponding list of oracles to create distinct requests to each one.
 */
contract PreCoordinator is ChainlinkClient, Ownable, ChainlinkRequestInterface, LinkTokenReceiver {
  using SafeMath for uint256;

  uint256 constant private MAX_ORACLE_COUNT = 45;

  uint256 private globalNonce;

  struct ServiceAgreement {
    uint256 totalPayment;
    uint256 minResponses;
    uint256 activeRequests;
    address[] oracles;
    bytes32[] jobIds;
    uint256[] payments;
  }

  struct Requester {
    bytes4 callbackFunctionId;
    address sender;
    address callbackAddress;
    int256[] responses;
  }

  // Service Agreement ID => ServiceAgreement
  mapping(bytes32 => ServiceAgreement) internal serviceAgreements;
  // Local Request ID => Service Agreement ID
  mapping(bytes32 => bytes32) internal serviceAgreementRequests;
  // Requester's Request ID => Requester
  mapping(bytes32 => Requester) internal requesters;
  // Local Request ID => Requester's Request ID
  mapping(bytes32 => bytes32) internal requests;

  event NewServiceAgreement(bytes32 indexed saId, uint256 payment, uint256 minresponses);
  event ServiceAgreementRequested(bytes32 indexed saId, bytes32 indexed requestId, uint256 payment);
  event ServiceAgreementResponseReceived(bytes32 indexed saId, bytes32 indexed requestId, address indexed oracle, int256 answer);
  event ServiceAgreementAnswerUpdated(bytes32 indexed saId, bytes32 indexed requestId, int256 answer);
  event ServiceAgreementDeleted(bytes32 indexed saId);

  /**
   * @notice Deploy the contract with a specified address for the LINK
   * and Oracle contract addresses
   * @dev Sets the storage for the specified addresses
   * @param _link The address of the LINK token contract
   */
  constructor(address _link) public {
    if(_link == address(0)) {
      setPublicChainlinkToken();
    } else {
      setChainlinkToken(_link);
    }
  }

  /**
   * @notice Allows the owner of the contract to create new service agreements
   * with multiple oracles. Each oracle will have their own Job ID and can have
   * their own payment amount.
   * @dev The globalNonce keeps service agreement IDs unique. Assume one cannot
   * create the max uint256 number of service agreements in the same block.
   * @param _minResponses The minimum number of responses before the requesting
   * contract is called with the response data.
   * @param _oracles The list of oracle contract addresses.
   * @param _jobIds The corresponding list of Job IDs.
   * @param _payments The corresponding list of payment amounts.
   */
  function createServiceAgreement(
    uint256 _minResponses,
    address[] calldata _oracles,
    bytes32[] calldata _jobIds,
    uint256[] calldata _payments
  )
    external onlyOwner returns (bytes32 saId)
  {
    require(_minResponses > 0, "Min responses must be > 0");
    require(_oracles.length == _jobIds.length && _oracles.length == _payments.length, "Unmet length");
    require(_oracles.length <= MAX_ORACLE_COUNT, "Cannot have more than 45 oracles");
    require(_oracles.length >= _minResponses, "Invalid min responses");
    uint256 totalPayment;
    for (uint i = 0; i < _payments.length; i++) {
      totalPayment = totalPayment.add(_payments[i]);
    }
    saId = keccak256(abi.encodePacked(globalNonce, now));
    globalNonce++; // yes, let it overflow
    serviceAgreements[saId] = ServiceAgreement(totalPayment, _minResponses, 0, _oracles, _jobIds, _payments);

    emit NewServiceAgreement(saId, totalPayment, _minResponses);
  }

  /**
   * @notice This is a helper function to retrieve the details of a service agreement
   * by its given service agreement ID.
   * @dev This function is used instead of the public mapping to return the values
   * of the arrays: oracles, jobIds, and payments.
   */
  function getServiceAgreement(bytes32 _saId)
    external view returns
  (
    uint256 totalPayment,
    uint256 minResponses,
    uint256 activeRequests,
    address[] memory oracles,
    bytes32[] memory jobIds,
    uint256[] memory payments
  )
  {
    return
    (
      serviceAgreements[_saId].totalPayment,
      serviceAgreements[_saId].minResponses,
      serviceAgreements[_saId].activeRequests,
      serviceAgreements[_saId].oracles,
      serviceAgreements[_saId].jobIds,
      serviceAgreements[_saId].payments
    );
  }

  /**
   * @notice Deletes a service agreement from storage
   * @dev Use this with caution since there may be responses waiting to come
   * back for a service agreement. This can be monitored off-chain by looking
   * for the ServiceAgreementRequested event.
   * @param _saId The service agreement ID
   */
  function deleteServiceAgreement(bytes32 _saId)
    external
    onlyOwner
    whenNotActive(_saId)
  {
    delete serviceAgreements[_saId];
    emit ServiceAgreementDeleted(_saId);
  }

  /**
   * @notice Returns the address of the LINK token
   * @dev This is the public implementation for chainlinkTokenAddress, which is
   * an internal method of the ChainlinkClient contract
   */
  function getChainlinkToken() public view returns (address) {
    return chainlinkTokenAddress();
  }

  /**
   * @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 _saId 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 _data The CBOR payload of the request
   */
  function oracleRequest(
    address _sender,
    uint256 _payment,
    bytes32 _saId,
    address _callbackAddress,
    bytes4 _callbackFunctionId,
    uint256 _nonce,
    uint256,
    bytes calldata _data
  )
    external
    onlyLINK
    checkCallbackAddress(_callbackAddress)
  {
    uint256 totalPayment = serviceAgreements[_saId].totalPayment;
    // this revert message does not bubble up
    require(_payment >= totalPayment, "Insufficient payment");
    bytes32 callbackRequestId = keccak256(abi.encodePacked(_sender, _nonce));
    require(requesters[callbackRequestId].sender == address(0), "Nonce already in-use");
    requesters[callbackRequestId].callbackFunctionId = _callbackFunctionId;
    requesters[callbackRequestId].callbackAddress = _callbackAddress;
    requesters[callbackRequestId].sender = _sender;
    createRequests(_saId, callbackRequestId, _data);
    if (_payment > totalPayment) {
      uint256 overage = _payment.sub(totalPayment);
      LinkTokenInterface _link = LinkTokenInterface(chainlinkTokenAddress());
      assert(_link.transfer(_sender, overage));
    }
  }

  /**
   * @dev Creates Chainlink requests to each oracle in the service agreement with the
   * same data payload supplied by the requester
   * @param _saId The service agreement ID
   * @param _incomingRequestId The requester-supplied request ID
   * @param _data The data payload (request parameters) to send to each oracle
   */
  function createRequests(bytes32 _saId, bytes32 _incomingRequestId, bytes memory _data) private {
    ServiceAgreement memory sa = serviceAgreements[_saId];
    require(sa.minResponses > 0, "Invalid service agreement");
    Chainlink.Request memory request;
    bytes32 outgoingRequestId;
    serviceAgreements[_saId].activeRequests = serviceAgreements[_saId].activeRequests.add(1);
    emit ServiceAgreementRequested(_saId, _incomingRequestId, sa.totalPayment);
    for (uint i = 0; i < sa.oracles.length; i++) {
      request = buildChainlinkRequest(sa.jobIds[i], address(this), this.chainlinkCallback.selector);
      request.setBuffer(_data);
      outgoingRequestId = sendChainlinkRequestTo(sa.oracles[i], request, sa.payments[i]);
      requests[outgoingRequestId] = _incomingRequestId;
      serviceAgreementRequests[outgoingRequestId] = _saId;
    }
  }

  /**
   * @notice The fulfill method from requests created by this contract
   * @dev The recordChainlinkFulfillment protects this function from being called
   * by anyone other than the oracle address that the request was sent to
   * @param _requestId The ID that was generated for the request
   * @param _data The answer provided by the oracle
   */
  function chainlinkCallback(bytes32 _requestId, int256 _data)
    external
    recordChainlinkFulfillment(_requestId)
    returns (bool)
  {
    uint256 minResponses = serviceAgreements[serviceAgreementRequests[_requestId]].minResponses;
    bytes32 cbRequestId = requests[_requestId];
    bytes32 saId = serviceAgreementRequests[_requestId];
    delete requests[_requestId];
    delete serviceAgreementRequests[_requestId];
    emit ServiceAgreementResponseReceived(saId, cbRequestId, msg.sender, _data);
    if (requesters[cbRequestId].responses.push(_data) == minResponses) {
      serviceAgreements[saId].activeRequests = serviceAgreements[saId].activeRequests.sub(1);
      Requester memory req = requesters[cbRequestId];
      delete requesters[cbRequestId];
      int256 result = Median.calculate(req.responses);
      emit ServiceAgreementAnswerUpdated(saId, cbRequestId, result);
      // solhint-disable-next-line avoid-low-level-calls
      (bool success, ) = req.callbackAddress.call(abi.encodeWithSelector(req.callbackFunctionId, cbRequestId, result));
      return success;
    }
    return true;
  }

  /**
   * @notice Allows the owner ...

// [truncated — 52074 bytes total]

Read Contract

getChainlinkToken 0x165d35e1 → address
getServiceAgreement 0xaf52c981 → uint256, uint256, uint256, address[], bytes32[], uint256[]
isOwner 0x8f32d59b → bool
owner 0x8da5cb5b → address

Write Contract 8 functions

These functions modify contract state and require a wallet transaction to execute.

cancelOracleRequest 0x6ee4d553
bytes32 _requestId
uint256 _payment
bytes4 _callbackFunctionId
uint256 _expiration
chainlinkCallback 0x6a9705b4
bytes32 _requestId
int256 _data
returns: bool
createServiceAgreement 0x834b55e0
uint256 _minResponses
address[] _oracles
bytes32[] _jobIds
uint256[] _payments
returns: bytes32
deleteServiceAgreement 0x3a4a660b
bytes32 _saId
onTokenTransfer 0xa4c0ed36
address _sender
uint256 _amount
bytes _data
oracleRequest 0x40429946
address _sender
uint256 _payment
bytes32 _saId
address _callbackAddress
bytes4 _callbackFunctionId
uint256 _nonce
uint256
bytes _data
transferOwnership 0xf2fde38b
address newOwner
withdrawLink 0x8dc654a2
No parameters

Recent Transactions

This address has 1 on-chain transactions, but only 0.8% of the chain is indexed. Transactions will appear as indexing progresses. View on Etherscan →