Address Contract Partially Verified
Address
0x0563fC575D5219C48E2Dfc20368FA4179cDF320D
Balance
0 ETH
Nonce
1
Code Size
10594 bytes
Creator
0x6f61507F...9B61 at tx 0xdef345a9...c2eab1
Indexed Transactions
0 (1 on-chain, 0.8% indexed)
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
Token Balances (1)
View Transfers →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 →