ETH Price: $2,539.14 (+0.32%)

Transaction Decoder

Block:
10698501 at Aug-20-2020 05:48:39 PM +UTC
Transaction Fee:
0.759869262 ETH $1,929.41
Gas Used:
5,506,299 Gas / 138 Gwei

Emitted Events:

106 AccessControlledAggregator.RoundDetailsUpdated( paymentAmount=410000000000000000, minSubmissionCount=0, maxSubmissionCount=0, restartDelay=0, timeout=600 )

Account State Difference:

  Address   Before After State Difference Code
(MiningPoolHub)
4,298.295171619340890154 Eth4,299.055040881340890154 Eth0.759869262
0x4A03707a...2270041A9
(Chainlink: YFI - ETH ACA 1)
0 Eth
Nonce: 0
0 Eth
Nonce: 1
From: 0 To: 57884681375957546299555451602363358023335948015705558154607989056651640743279972757594858058817569324219209157418465238713016868777241230996405466957473142613548827430348073215161565191425163571107496498425169205261626149589341989652630145652972410448576840189185462497272382801317167512161593414819780752183709440305578754930937020642254917855328646527378672158185532342870776049292054631412937322125202016470188988815149670283783810431956865751008200542114966821902225170692738571838494931694515354167798307539476392421155324733127780320678730009356076477285751476088167490210351500346959906349503416360874629954672044750680587139087140168769158786057161256446201251592636761227037415141594948589820225809572104004714227566471137042670765779178025588616232140421220366394631025435344125478683352061333904835871658344397119566563314720143447985489463040993666021585262835276524180278139098440980986071450186744598737234833996584693173157666423170018842675627528753192384075122371118645258377761623929518760477933463603932691924632055205607141875024234572995299060703691581754237274684746532020558962836998093680602687025180448823275624496111789285005835090754429812510091170836617180252734219372371494942190843749377514700669131426538831302899317748523870077058068172739869283874349944234194080358936333588380865905365165682027007899607638011661449228899418191501624598169134484590863197805628000921159537409655396778555186358938582762875796407109904629492616835517111188325422982749196555299461046804809819281064300830179467862598909272729091010235092121235397480242359240233806552096148699179775959061202891052102218036674779178098266030203365492820430751744388860447064313738558692138955889637000223514873780405333649227027534727462890613880125396407653177447535096259004744850619902117182765635004062012184859550556195461109325796804577051518811937936080956341135934501089573128229479262044243971695589154792841340721739106917726738091400459242353191219332519002808081590841045107466366230563361300624373314620541544664421037527892094700519122258131652474304459596308240102441080415394779017484473204616299329205080006308044856290235364134227101726009518081703669972299023713075947339820427151216332880977046963526280380061525904774042862100513076739172276831713913279746417890797892989561330478392233020425639813040565247406570490096780144397364226275082926651182601170324026240404076856050460915786238096036137449566929168619904591023818449542722369250125423828016220697050886100858579436233286743840060035569309101279882562739896460339928082246065208423390384344358337082818592546304186198600332709242727277315133872314013047998117522871595713534859628018132583572506238930952393953402088198047392359640146581940352498590154834600485557316854516115521804735028184283213636493947796293199614670580595454999704878486088229349856650999459770265219375568477697190447944802362259458350830000535149216114896915578243349621200532841577430390910198812268255838509728673719392355615569661798311187395781082337956936899390921443889927137528431245664857883856508049251111599168983594728118707332485335202966201863160326229991495440217366307612791298394397748411493098636112989236946473919183600155781578928044995365544881364485823367256068309527940949502451406854026895984061207806491363875163115697285610619254890467975047452502911499612274177553737900376438409440709619393909745151555234078316492096356914604510582164522103282615732449930350277450741329531424799346642999248258158917825460630748609903626077710877119213738689075964025843121966997084073395224917920312580802965277778808503830578190909450808783400876814728343360502660672720329355159710357574805481634356805461595818861356895872267684261939454703729109137980090221611170380440293934975136162316010763438928936686374943487611691974193633823703350846275291503720295114165575239773548054203878619773885905785695623396291470540002165564368255311963105307708941317267751946812358949057942452586863209576725681059788132032693298899988138790996650445019169179711283789191459940956937077393771288893952805100260603179796355065031155780344475342518950702701794628411049304407785425171196900387335394452968947510228043700176146821878791285187885309487725641381169510156805631302042184863707229695507324399437155795947198626875755377586527677647328463129183518269601714030791068573549641965918876856349640732866391247618387586505310820285282005974254574193958728458980345196672400422762584972678366119919893140004756313496171785305566652261736488488769556040685736632054124447349409952551335438539922226574084489854071309983165960396825269240982627375017265518710784469754916990855990940122160399480347496254369263221602926247376062282418942118475288693698762731977525348457215467396032589006137225550268430478293264655302504006985132880205826060747423960386592503010137628028019935421822548971012036733285973090824231873428495706715848780603519775472865035681366599383993426520429647797405666980912107993985735382034051574741714694282971728917480792496052364077818808486506815359650380688636807482088457386831251850652819734392361671799457142040113923356970333230879914686333084398438872586875232352379036985805432668781468601160689906912101336203270311819942454448029736501539874969863216103713932612383154066306033156946722632079207455005301439600030006069967425267535331849127209981220423219105365130172083568581795975145653716196907824613478739755723800183524444574850095138285553685483477681626999635506493507894460311002753742009978596589067249604203522428108762777032255577408406771588502480845414168022548497301687612801211357462804123833636362075979522220282616497393128487178311417716744226584510716254999110752111863364642009552101060311337698393586779189300410216070633571498672723303614527891937644106095232730798390904051376110542899618802937274432814415365933878500195920290779666048008962259694882928918266070637625193318779996571107819642935853991680258707795799455147580506760408984221747762660585040701975387113102048419922652786168327754378510394311886768790538485502274875667412228766018798912991022834212734887529195474628502943220334144131684997536012047873588543536825825411608535158791365518013969132613356608241947691090620714338446689883194051140209994773632186248413827921724741030319394911999033700071174349930971641471774144532330639797644435410505568128559658593362420565894192822227313893782063663236216239109247528478141560257955080030073244496256326342278616814446798217809429704055682199324638832299037654589753722742112597095222070739292310311777181715258313798421521279719303442858503555433716043000013145214004481145074105535251848479593780932637472568788959837558340743605571186142913545059872881636394709555779986802148761534189227569523381826038505511801270350769211488085957535075385566020014331531712206081461639112915495854550995967431712808345847744510555876725751669533036773048983342166984708116894773706487256719681773821425301844516306149917073016776677741275983456241580278508765079759216528124735153251725204357542055850669976835800623171399717939088648776108574618938214881617557099051795296108292017141925247462719123707491493074022636693300824954334381077684122063905400455130520972397102499864478727181238204123612090365549673947371675837362669836385736639767844956576511557544772890508173576643069903901507767280934133418612922402500472026051186779478823660847999367629002695580461573469208425416582839312753154690149054115609740699202952464943293095429605427859011088898636571133360156882372651426450741162774842154523379637589823119929381447635188711172606521604463643612941825772713851587183666864293031421712427435278099874649271816437213514117186492752777825250479190034758739098495571892947529817296267725014873371479732810181929517517084399005729969472481787089187398570432656594389145933681007811637762677959093502389246247895651190052678430279086740995152650932850915406785930048807242995609567071747790388492570906183779622194970528535485942775669609178334961122408177279015004439499114303822764101474532518604037868524561035406373360079957194209763744931729396075499308271320363908409007783890892250532696338643346170947130166832211056922124826838468066617744877193929752820725045089575301693089524627024735901589085787762551983027731075792312942992379696409516392772137226754271287604695388816561489816004589612439858294877071517809374018231095825482699136012068222969454703546641698980081997892039095509003400977911524176425735942648192157970593880199218551570704288410097844890394756753188559812736956664769313214955650989576573009706013580415636898679484635958490497947596413124941297564978731486236812287554845785942231167251322235651264805840033476459075088344083432699796978879878657548012598178771379791660170256767272307199281852782360246738038567411020143348911025094504764213028983723332958231121396331462837661533789781644201216677239579774470666395442805499688118322607002019774216948128766592647636342541468450879214001538497302170459429283175337862913841057647069276709469117972702994741063866603657575645918300047241816314271149864633326427164150712243313511415625663620759720486371444357985537404944213033661803325725874338969389122384203993565584948005968808995684325126145595300416036289163845626799220815228771920200183599859699078980676985454608605998682446351885901180816532501657132467098511923910511573885128472936929420740952226812723814213764510946734148155544005081858735483856109370809116274469615421935314424674009237587691467571690401878462241179492909558633409754158257169940678184032989922338291961492516673179654100993217049703761858083739514198952813680200275026653558791091804465450712196158320128622288570090815561351485843330011870535032488720172276103150472203133499876907220951806235170630963179783548965841100124253602370326833422328398133572438093152629534626794033788946417122852871568168829336044592895403439534426385600583541047774665893449225922952041214130611212984071355630010494450589767917974532594419461546189744452379535570448330846892783746534360686863955890058486010851983377648518336614841630154247967327613409350415722060216707054714809575872974414930983689277076521651985214930902234551877844416184669625038507447721676484030246312526269214292547170958045278365349265196612033747922387591644446108335270720685600239722074628475892912617649598942610616594602133969086267149452906177006244241988249080748455124219434278912850284765420606406382501368163846951829718785225634025550957411616922612807911577775212728397496185580636301467920466388613978138138970146496267264956927311359585228510813290053572216087685257535584519985961920131245502398192206419142749234646054656846361481150347315830664169090929471607571063445540769774927858728869255989283210775143388901916344809848940462973439741124783443107979742598864101796381739141103519059848048614039232098274566911173106910151912297357990255067507516128732174995835882690176964646084063642836250402748047217709470229805779019610333899065717469381874270727768193928698036205111510651360012416895853413899148182652562840246869881312618200224184486952703982286610812014862386091604305328199994626541864698468345022590136179440841303183670451321510837419339317755689347885212503588986426754249998599037228165252294658823112926986666700661940866575539125518140779131530141457176640210704688640685664017689171854860181844696345899416223588534324849718527287800292558935880399559447753235928384062682640361906220178469875931669944880283784511735401171296635029111651684328037231595074409724658575217122130335707897227072431651820672861295493976709837396918720560314738126954096585574192584719791997311111042459403479387297490560992892619701604272263912188776019179136633073308434607656563260998039459919799093962409498249337512477850408867844539634730309468795751287478065934180660974789587677751904988337820444648934955324790368331495269131533955974095374970150797441161123071586029237374537215198487468930707067149745240349708274415029571929340392781016262269399213885638711844837581346411980031032760061630486851292899328782628704633461619904676929332165639566330093115840179301939377484138271406080851429092340238737039628194696470148994855215856763028975723949572698718014021149373750824680346694193576285214428851036895204110367929925690011572621008789273215085951061093558043706714370803037317497131371914382307653439831266137781333608830295164346333062269698270782078151901671179031922210614514036019900961194654077056013459724336973442665926648871046253857477039497703771489110588713968292445948847331663771857661622925523033234772055124386170957336721571998826533972508930268525851654162936995719874796491097208113922139895073288721135783743274514306013006325172968870142037703152335785236207602288666225567881909910667689605533014284072476387284567698413477239422695653456459049518628298283819519256570522730971326322930756640577806562842475362139871623856194954330708929034565280875886860235284664405691662635054512843257808340253492550384151216123191226460086152821401696628588623621199834012702885646891811582848140844632186201506857252418373635208601154539112099807427173299845687922980956670174286219574328403805797163586043388895594507518514759446598400944788204671020604114224071556122595697395486165768387805427416930672291953756185548748224615273427403688234178089439179379056986250178672024250915419356510223839906667205233963827057742974613167373549135505574707174871956922417513210806618219055690485934849355438690727297789073983264981541273616988352573358917150787525373659962084513174325063633807059214644660784776759105292423890053895046894738709002075561981001808423983049000258898051318811770998414425533642125163637166622745867087067408095992530187145939711667734071175660480533587426743873209983530370075036590681130441906835092776292349188908866771055554077452675105790068825936278520261047974975174924230825985668470446234212199320894126441665352780834546605404080723652274978075020213182330882285732298230075062574004389940728644070627803788455752696545375568713601841595277021597015807410122730090750386231464698637341030594781925787906558409022766854198272657255186736286056665651262600494897230689904946703282222193775306249556694537482136849786425876608606043812394615862433438367369328488192910966391760390099698178046892846444215294266830322041212033265747683449158904600570189732085763486922472695994953695565373940735802613435798379699697645983066592170653911394268024051975198259398403718666691870118319170260399665543084086807759478791465060464830400387449088311341611298492392086076374524631095803489140452889434528959433990820979642818961724475764965477204718470582414092373484797602851852126362588505438263617013028188517700902845836641383732989126245546438903504374411120203245886311727224362457679960818439725934768196152656054593971780028170894663508204314048135565278476723133106739945013772352601202204700047456116587623594965749016469919696781479159193600254550790724745760471293356469012330154956587086105054711176506297977176708269762052924010350947273220187099663117169463930357359987891889478316675198645893397162751119765077249764523181488643897045409328863356795880384524890832225101345738862532918488008217673621986821063263341429139570013429170510210879841896045082137841523315844834896979453494969324174736770195908628608467923360043564558516068567744358911462378993688293589893517069436831205679487418956147748880297099618015850628201509744749065442976988831997684773303858684325595506689251941895703309826271379577435258287542964554689073185372836690437573766168576021598153847934841013680202439975092502672948868704498412201201951037050836265386677581246731977531463769358301533947830550270965284367950156731720097276001302918326729477087060858034276259863485930379230111756595977924760179961037217315636969744921243098780115760825527942721229159264165802371438915148279284334863162670945615147473241579429638697335871550961366435088942869503938600934375708603919464183331962808029346775833059036424877377179697854057122494785029313052542783757835791582990714657697211140893346816120762404790156653723641047482612408979558189165781511581198195081609653335683763219273390371255200410958117372349029261422229428967071424693069387942403865590569228232540295471389809444795179170427734275657284338679933705150521747351239216977776128492200679912907283443307383052523469472889107134845243555322557592114158986727351070986163050714518610939166523584120765932220740497686663816052087029473890504105705774425583995769772087273788057475591963956458673821687685171724861687849124239483048487405390035644093959714587142164140566883289171185333597282163657560738404159626931429300351347893572376876848909930692616377849655589007387110907935314858579576747613269834211458077416386055624801285626833824273050009769150600596545154970057859965631162560050971427709084760647511210989106591403282709654287193971854502498600510916135888234896274335584873781334010954384552243443490586277550464600655912872248563474092571142613038790362123666619352996134663700356618618294280042951066283533289427213472557390525444249510185939630681622827004837489656143383173419493604959942513553991308864141876135970636442080187412736612886550995039456356316392878215195586188793637228757771221868339010783162482920525144077671696661242025637340872821423582619688800607780935122202107864285170329776584003379887713292737776203062869263721952533808323430380408583785614758871915735736273379581795411987561120867086840948838505011434569178487468185398045891424446585541438308712684480222773182679800574720002529572263415541433109807644074507368796293753962782475544316340737944513007506490686264719056504455018530882641724187916230110303761542807960119341410988147182273964573063390878665885350501237770685670101689917496009638859580623219891326650748472733029930053216967446834750733573246888451236103914690631349924458183840733175325934632534740401413562744486622165149872318765401631611963224394162068298201133179878188326463717657919445915395528134562026492851765027193608862259772546305452066542056312571839279304742674854232365908129266678003338123413755038201941386386756113691755102509160643100114058483779228210772290932486902183754097005341960156594314084963077892320502874496502726058628400518683428089454871237549659772280795618650771495232019975809461151514555282389325392117140890164530379687940021987046430585218030130912312613381813493572022817004656082605062300582369897706631252931735235227236451344900227432777799421283506901793631068404516842821725965190801213204364414264481905322141417114244828976994808400279893681429306271931388351918806787310154305706262371281846265987983115444991590176417522879761221244530670582353538146572921284291265833500786204145808721731433916445023844119475242700091512725153039309952442629780521173625213092024535770931399927332228941567588177604583173276186322056833257560454057053189241347866884721825108406713203219163041051597235828498758306023833027223011721392675873797987751826461270400712775836475109101439787403434969213328366319347006396256527441681367426140892027337832761671154234967987269957276944538810967705742299575258841690765922651915661791579640369161353247139716282935651378062148038344174773538704580594046537076544754185402346206945401409172077380673404601975909546104978667789469003798843534150209646201680008070630462055028984397916794843343417384250187805285868266086005723874888709669426710743953975191981607794512297544149134739250894946144522533708041827065903187859888946332862902891987690031808327907614374426390569476121670703902535985429377727978838173231537780279374935996501031592839766107372650119347918918778994253641939717580121393807279688134981115096385165192037418978140592312818791057459221671111168825739190153056766363205847841465614783202038253603272621046451590536108209963225222586627412413302573956463402916542166535250038054707206853499058136932389480239447532996620515215091489897674899167899922659143714635013800264512029405554894643261535643189801653405326549399606675411722213201462192361964046805935744734027669943219970981641475654819036550644604040583399889603541448979426975979666722323981670820337509110043697342845055724047412314217420174265622437979414566599092137803619288212847535610613338066870744025814676385223061181444921648336278440839068038512977807292641866201148395494554825237882173310883548150664534068043709610009563044904579778771974395295767883647128730545505497189101844624136323442991343278876750077006114711251260092325514861504082316439082685646915764187112213652144512514564032663891477768053606897934113738123372281147432166632610731696227331940096022970527261048551893239009049183992342284886254649664073520173690263794951067637386841583096053484890275606284845631619406599131231614006307912165547230533074103409356805426115670744528252987825994969728803842141114063283768325144496743323985338370991257087807418459736499219166843730714589477403773635616604362809751955973971963626991177314471213591038098558315038921540634914060820243274645252252096480530374853164074556719372101813082538341187866742359359152026767169508260241042175694244393586877540313198874811394987018546059173414330242012979827265527482404605795965437767535299977597546651232841519214894810953487455588541559802250607189414736539162377286691059617153190713113328449776834615797583637165387063593089216611260671557244781182783283416349568361594668746093957126650027746947616394713117489769320479450071760767943131146944149731577492547642784601525798594012617267060743023739607081796897117681989067623334024296785524236526950823600903909449121650621627552796607825834365533080685033686838545026211185605632177559075547644856528557268656028772711437252749394807927964993283342408139394591073756494505247483215017671367846178809413124018430126631624607375553502582692438261074748406340623513877677219095249358659167798434666096735557326972596966015987460769293916021105080100753499317291142862992776462494967221782519588831232023558888471240284934853560047552139306066784413825164833466388062094268424065196213734942656996073317075893778906423411324872526642509845808724887489033296094699524537957229164196634859784658468748068865737583794692582787703898148643453623681582417267063296212442332564704941883725134489375482330737337985556082322736196475829008600926439846010222279429860345436778609133623584740457969710640303656379376645209621662096612786048746630212099173566350384298307505137489644466185287832699796467771462598234527844949046527079107135207122505018730761587557820302027233767201820285645842175701630852694102805444775205801407088790013759449429055300071419295865003351755273831848703726590144339828421714218900999739288495651860651169681922168661959186241649385568031322983474523955798342376030471519337564902544494704772937676892652425343401029882709858778844764224851481464747902534591622264727075530232142861505426274044592511134220066084113557622666585859697214662777382808451724213729206986779767884585961709482142244979630995493046215040458347339868122189667374200216504784847719743167855088222854591463862980455164910520612961373740471664787844986912001314561078886939772920405520739419793556191805136516317276699922838505582661770790702949413082567631864039617586468551846479946096415522228485787151651683845038984812596339241431083014575602531446843303768814306865614470965289370534679058328726094449980062782668107007767882507434978873310234003115851099588388748225480686655450617779057660521808829374549260547608132052903800449706471601562452352880983539310335915814735512893175118749301034355028500205273925526714367589901428985120945107315596010010854134305151854967426989306388458898225398813531178372611812905262520343041181721078578675296897343400319942814919765161889952528773395886751641454962485582240460264607511924810514079208650268454788263387942732414426518920269877102350785377002942267710638419854149900011658113923723291853109264434100260118831079341166408499798762999051014918446432067036814120993098089423819177449661165895076064621016298397418393516375441751576279640167681328920676826072613308781874160465394836076867874769479827966044484282920999332343066282257307369911887694931348914752124673785777013647030293986240795558259613761807131082043160644448812132224117016698972211720320923872271539392695490743905462848083820994757928869401070074899827377034189391171490641767827022571324061595534591751167942943366156922938587077288471343523614762361100355009170738062010435848218446735632340761966390770108486664565770815207495836484892794619354524229738231947616723155113184287077799850644065872655959831913851454668424912327401872143079966348664696464440687521003255916880867291156199754828193162762945755457961686613709260029584578197019932752379845576237832228897793643873432370633102482132822568453697980065239053527307828237226622357225425972830584722046017232935587972933620326730550067862884586515106930078618604668403694717780065002675414345629305747928410298343310777524973690128677837710254493099907259055536575510740541159309777258834726239479509514808452049740992171482912799089649453551330194430818201190048916732499673715269647360160667393354085378383891600262919331174285263305833833820719657413836598683479075491613647882876798491888274306366752859875494877879145406345449502029946657100941875028304982733384249623945225125844526008041789396820813360349807099177408346141633863428098308464729920132912703022659939594497236319382226462992908701516790307711804288534205354229467591392404587999750757888235639032545846362065862799323577035519822080606132870054650275506353890596146543760751546315327444796311880088428778707559938901182726375860050393821368044327767869869941870132730956238626753256480297217807749621684317931762050672494460845410406457787218591894666926167319378688292365582244906711447454595852850870334900261800369710284513166428008091162029958437722838318728586362575773937384806538444619933079319415621592443065767777426270358257362866712001150813297101330053519404077639617411496356099076267341530102567573504214709509354404448087328888556772023422044149871305093006469579516065387889720750835078080660259623213774212094780079412560679895047449747659053450565355408674540052030482532057069721286283471724909767357164545805300080145144841645345022090761525987117591836807104982583084946373006397477125455059101417827394538485273310566491261480251891410847053452421390822860296297132234596114111574225963537045311576686993762649285513735177230920686769743315069385960586549295435921724034295722955097455183571452505552742164274234725000903011958907960238061658377202410381939744681740115996283209775004563510557990065609495672839701301196343395904257766108350375013491511112836939455765466712891425054641789917706341534539486888423728906811325314313442861224585174326868301330002123850084388366872182077553872609795044092352774649414243920162330517178808586672985211755194837590369260795119507327008512201001901340200595808917944850752905193826678084968328603299487312671403058518768270930429017954282021235860205367279563409294809882184852883466793894638869847750404613431834593111616036312280434136188614267539303801918706980682046192964915048325895362779269751769583945971665304130521284687650058059243793094383875997053761913535327952179800347862156248438653960278127778736062570116880269289751446566627075591445704583867246226944702624750520798614801080981708843484584322926846480210711275261759089155257922627594139245349877947887967667933065823209169763540380999361642929678614104096471573971963691524383787788642027110441254442063559835522258780853293189683633218615716885891714242434814307434898738819421253472489659145182079573660931351305342988086931919472662765388686090222542913782193509948537089721627051475654949998744320554435582118795153700057502628560422649330940181839686528585810252174756692952957656495418920985387666701854789894323765639197702973101642043575217156732441913843778377399405969883818016585052316756351266874596620620895896200369368221665479474479788352586232633056557530165780432284778360198529954602649822662827293615290699304792479431673693736879494565323731633745539653845330131606882109594111119765632698688408050184783223682157205183017668067638386355741403521720777794370902769356238437429609781072871617440550150883264335437697378929114273890938691318914264012056048828628159280830089950098470934542298926796751421153743210551002627005821764914090423276421634831971713525090500506706450651045780724505205150719018854327225520502087953951840946829472066944820381268827060740669079223889678180266895449054860404405125864426978906814302690534331859669948172210611987949510025040511049031475713287419619503175025299249304073507433487191030715314686820440863663544770188957041413181224294125083886917560365742225759282469972742050845871706524254493838046158165338859870702894414940657358645550683534205940834087622041741624223262268937199315562889345327779104327562695233043978994389474955469403940762835929891829664030479985558285593805787520753612958143401698297656749997023760013731623369730527965225500041535211624480581271114236482969811447389861087629099249702469813063385951311378891137384837582609502207740142653810337436376306061788354726676746143158433550218159936573496701755877469686991013866162282260885371096556901750605616282650693666374142300852761599109714830261039557605750137951479023278075468928161734101637198282200221164371510625708412041365457204362029413642274367472789611235739801357252877601524440157866388101805810857783837301592141954503854043709287165586992365338881282145959730830352888626310503369690732032080508725592496589440543923035223305596700425850514588328445200168477581685441911752860918074367112991036601696583509970334263641795751475931194086598424698789467368639802635904323317490040299827090339449077290358810114902543119137172783493051416834997009351558378209461461699973584658625049723552882987911438846655112441188523485380112513233842682659226144292775536234682346604824717151011635080488447272429943933043499245323721239604944530711403049012985491108375327763495165793882855264275227528831060983348878242239483724246663655943241905453765916292552899430228312079622825434390543816052190995947226435671926180461777107559203279166576492173692192224442933052850356942032587142448618462434795136076763942549978432415610978098181638037958087000785209580383403674833322319171894755454648411318565796224500549241916565673525012024949855967789734649207865933730734026575411483958803230025118651717970395539363296834674114497379049516384662502519303059460991099716556240799639496315279484242683956378296367203202823597015352052336446339129160398004801176730293986926850185733450798457369534244572309768870906186164872206396014086083414807177334642731387734592084260809123757899537154367449297462149509325739419277239507765225276689581729366063151128051097798120482376789215164713007820865485873633780220635420478996163975907449378319882828341139483303468558063396921283326104346323414086310332466666016937513238639936350942560178305003720125106643930018847952610971551861451803688847945515374569401624858547634720128382800183347909963329141112403886217692888575368264264763185565333155363687607021462188071319069446263680031035658841058199114749050412393745950559622243150662357080991421244387938959820284374899514807461178013471011526170295654033852670247493080357758009891807650567336097023040201582625000755267548604155508425365804985088642190722596172027803413234978971615655345849241565995599718749317042940779122688531456541127144737870543748117431824151228701377575667890845349537884696704184423253090289234699435093300225888922745200256033640157921681758798380634298335513220174297316105861511983621765273200800485258947478290980164799762418421493788963221402907786426323123244319622406704856188628209081396613872578328974028447730431649816368700371039801257755848555720285706597480021493014862870428041475469930377990490059708930216229497288092159735405921566776336512057552500500227412598823948124993329627171380170378064468579406680419311107393938977292725291933251417094441646486093560372642987817368192898985113815111880192432236289789603123413342293020918013636409443359866886798086245816740705825722714599303480776815872550995561302095954082773712952307793414572505988268700980345268904328246442388689445105881705332527508119523622704546250714711334536484155972132410299133392864162007033868135842162812122409429260207276963147480147864766023286056212029194723988711639807430805935667112220001759577345160506350425638644036653047707254033868477503713634471564625065441585560477495201074804770282170696560167916102063173995875864296283792299644985209563118154129740193576735372849454420500803724841641314733551375722774905684691126195644293408175337852187759311084481048649376064312664593872400953678793121974319706401215675458752286409087574811406868894742514499116037982887583494186427150553924012689199446270183973920544576514550998930106388490009589719210870524327034074706399082307282710870682305527261482095550446883994629254287675957636890300781398359323496524437743224803021163472787776988843194343118553910265175137417123096130322787105034049446618321977280799014101848129077839802230015921983691643027683055153107757805008235435729574080118055236079110125759467951535521196415666300034101068290055019274008835220369410337436818836715697007862246829566720067443627323610798282547381409158170019211960602249971209650850449321563578234472823191870425983711812475314086289606287263948123610207442421520810402467831904015464854990939448275598902817223154370596921149943530511405535567261628516875372458357409792388477634364986019711501285468223867050721851867899368928296319004923598920548160818905585139970607819358298447262367485039020878515924941401475354578710081514575105913128021449317324305914896027981756539935511758028416409503339086351862767130588813748951251520039058063359903213232730019794608816311604070303375643770790181543621205216458848127298296996662995577711168928382935194391836845659251105786431571430027011159995591675188644287008655570297626476222589998169730469661827747471222619299915696437538976058209091065313528327383172748425090840944518696459856590464812631927167722834405771863579513747275959615636293913226369153525419534325248311245742403616221187822287653861827133051443583707769862818523545925145673860536621758712771213029457891359970387842798812327083985913303920453770410950011610849714290731523478536888547212544988595363248352482185662587540552515653860550789970762136621912373432180172544605663894863007767219724852175299162313226134448909811403682674239730912454682727739976827225695048072366328294338882148426925396712807661388393507542670897618541046253632530525789940936057270533926811119954604189718130967194138836140585268034289041589794699521195478334518156950793915011354174450018821223989655599829507920532783801288007224446478859432874763177479699422269152763740384534284393677751899947769294257150931338913685724912516522702905327993718788090103098602135163265565595237868212428899414657179282648906264605885024357855370164500408770071211781972775362336001968364697524884281511709946248661326496160009379083909572937499892725341821519300281200145778029144178361445778387590313240023639002885435172454680489836670325755639741624835882171159650039186374262138799278171408630556266572977146295840968184736191258354733761610747020290725792017222392690844935502888965561019970916545063966344732899859334482435526978097364922288720621220507625522359688291733218910587664012862347953195950088503219176191645683185991692581046138493589118603639845807230937871985831887089187972337460159962111258379157344637757939849994028782677377381010083344719182968442047586416578848008411934964565926615376427481066154206210581852737586640918920113117418449005794120144138540906778801620483400395949517008792007920849499017557487123396998323901991720297077552808912121169839400766561907387784610408438190550613287122046323867402826408291984383668067451428357397578455166838098979082629953271677515064709638489910928139474558806517050186679860181182441390498702529222307677964806116926953625731820013538520162860059445856500330729023508390041703747834384063282826282778431490633412905486216240131273562959543499934615457881194116906357670634121606824978672048547393799728952898666499410413739188615384678006057889277517585282059708202900819285554418776693760777363921025703049864202557577856746703860722287196188072636383053657178670544705056501563915480625460728880486605622420364465919373512771155133500211943159012236689917887003451943263829478146552910793665768815027967261216773787257629457307410612219738610088562146175600178649941594388208426387207790168196703026125255812634933739944799971587342006403285346966550365873796560543376196273637605504720974153515414501827313475117099451719895508182171516805169575502567489076173118362577472051352737538985301334264744997940891508972041030759205170934898665100183833079438919368927686228971913010361588679244285519314937026073137574552048692424911533072744501851700529366503663524513409053549595198246289788660876860113733795403132478204296403970801577723533073891636431577261656195809007606914239331932425759667269597476132903509892781795968580126529537762126404467812105422512976626349259868952437640510246281373748818646462440089329074081731096841289726685893400306263767537599777157287749595697741922315213276851134334716084673365019517413996481047343970768346933467850644189230365393766702953588675509812095883105246166539384049352442652011463370479935724085556566767663519788300930751315180561978036832234860329725772078130457112909525092735399396636632250002210380853897187289932755982341071462309146360161509302443400970479918895492090422522582974187625569505048007314240964710501312376676310944558179119829151693208861640194005581657376809867263379430479927376561752829606922623738887791272341009629634134289131462122980873382241367528171457193088093579349063354750036555551667313865312492049451736546231703495529688981141062233191520546507762971473654754503662007457742063378169586351330419811769416734801671150779172469236247009447219188223999378365939680039095664557992629342571877824272282187718600455661941242654535620661436007978269406904353825448638835474156264643659333847457277483448045558147856344027326025302238900239538738767887490689907382158128765844399161694507758588255104624894326457491601154483945383292698246461757438636542422344828764106314837669132607387879964060366982504046825265862784257720445058981147551230759659524791882181202865331968595671618647436509261686148211121159509122649569052961532773911750527157492494707671945748534468188620463407140299647932183436558069244568458930611875867448830616372811287168292019093965664462393732703236023770025972779925104312928914596786646502795618804981477327819904667501860496344192091471200553562158582112101934200624332448988313877800438540516243483273842941761930525021131718097908728518424683852588334419443725486308877126140554727494117838031296978432093318606415202951075900452516210131077078804292162891425210909644002734191165451565362642051753206812826729757982116572677980939790789302167250651111462651297853809499729945616007645885952238600978005871841357962426361942729493225514248520452647210602969597231934660063682876748776369694690840360837009828139069716073968338224425898686015511451117688808193922624260427703911072852834722262845437642434340368548446093116472409019730045028499780360625845558356074644906182370204543137554966009980248547147534716582020718529745036940355062893499689753728032964890516145270088984177299171751909289913652965324581063536508720918591654290030299436507045481535016946136925742781762107935656737659374621421111416752290365201428306979468948833395375811457072017210323771133398068367040880206521228889551484721909817273440539830577999553894584812802784710324976868508376478763694437860392437219969788082371568603896886885455091340723955093769328863357177826929230482984160002131369493203958690878017995179356408767593668447331430097951137697832390688672385505278879837426657034454636264754248280065340967419700707793854984550619500795300095254935564222189804797872985200038072955186430053504392607132677563474616982280646442421035293500307528752331214081362934240585706560357346511053969402225421328865421865479202757909217506078983939890117763816569505937389791707767478436615321972849226924616358778726244154351800915369911118218334445170674463870665809780741267354034173632759824485346223469709156517193248769427238119787246333237937526891152275743984087393875762008279970773948442337194883604055075930517023290097838711043034487023513867062071641070881112230145430764381585225459695201559465576547399744863681307258999599193553111273341076239954504173826075554500243715381084838518760223441646181189773582545854146320926947845170790005580806623811097432514763410288013118923639241407351794887810765306922794301229215801866718819359912251865409483264332027273659774646807820207901903124404584502926484628377760226306087955314101479586393347471152769250483475319367897690647735388523030467164062693802187444250265055842733901520560571060233359801414248937324187343244012368268733612132341473904583129187702420483041383189159280620789179812250207697538014158003129329110838199955844924753729147076291130154938195662030383615572007298458926293893312795501506266946238776165776938057430194783859150664086127678835096686488482962979317322642131879014680730992401406706834231497511498362834852248357453085303877201549259899480989078208937664753694394417654153789910106019935020074267542050297336558498489933482972271677534110508591891534410581606769411101839913559715810847930570974732532842053255467333018594498219898769098544500442414164138218213978243241281115900036803131569290178259912839235646809490082153416170436436189407361111617954100076145480789575086154483879621094574750334911586251803006121504579815984727917290603137445439753754918396155305839829764379831184307781317838207744393960122326030597789564722077215142396542669432257860869040727989859013809406022082357392575049245276052028889929462150511707570971453320464609448598618644490296197809710539705572046986369631423383754156074656290358483080715759474876279595859121803641665189925926225409744744238170416264433835570526545285483246118931351127294216350377425796616239890801946202246931299112705199903101071821532002733301873851088955771218368872253892637375873730991581039804278530699564893564054754225535077277453178508236335610189165036517173179361472351095920841651792319827373855638990301347806487995680595693142809329903418156519322393462288660967562999598214057542119627572336539066831929995624378298674367967197489987878479562318391026121755822118784501212771172531225354682402334403420862534977523631463537001353196882219063926476274311568048679508500000143268014033784356211569638466316751657495968639575169129531411496468740089496710577352462148874578896902674430404060509670780882118305527177776675722998902077415331164731884050869544011767745457496185565808596998034622795039277201631977464874768013834944772402342118296121484824037599345559103536573492719669653107425116690647864358637502975929785047862787786984740506275707624303024246143138883462205124028357606830122768107398172031043410977705398664099347954673186217808981996519425384778125957226031333263132447410817991693574850979973564564883012846878511968349159034676463966647086274365656406342498302623488848889198557817328390432672943421157708845299376420161231207335796252421124434506616290469939859486639464295341858100839211399546143521676547418053701895118191847433113655117917054929658474775964023973523156626083535560090480012532262890588250620558546538306057661084329411184987484495194454500094280151490982743276222496471218835786015317440049602563295754242614097480507424554191783843214343974345748773989368210239479659571117955886203235663802122607064418059091356901443337660238479806644128151275951446645009137707624270574342882470807713438651509510007084970563779929898375615981542218393035770293584225322011615367955778452995528467956901734154365488203904520868088178785638010580529609210734143965193600355262168757359605761044919180058242935026997202883457006806971234527007147878708155242509879212655516201094501578355142545361401199047700967590160307362821505883666031627867221263311489122893710578582997507534501168470233705824836214381159250006295010238327358734689428836494541914063573003231416546568126847011486596124371158558668553203507896950241088784015933574948906662642745210586887526490301809416633131722754064233636764051390731500815925919024562776303220020314659168303781563272578748267235443299697886318940532030633079243870258743876610146772639625551802790822688956576005125198882910755335156008952356673920398130062614090657253952852876359406191173351154743769105955716706959972185181861142772683403837040404656619841841308276999383035468657729110499381418911226581343240384890079994002079036164911493395209126445170720242161543778524744749116661670320080902616788325696026510723692028707024935506548086516635133047596130717436197401385368042329230955111378193884226155724335977539783975693196875002568673659611308224588160948641571798791407531687008251137197900724246679371723389724523124478138506680277246048543072642340696916112265934688956480098177960653561515663789433993696239700160735591799743565368342613997301078031808507095045247920112547782294418110332990590206130791241888671020374897992515930829595438914308250280711703147575340182845130415445717339580243972164899676857168232217946026946519831237616008412331750388249168887766189704704230347504094922384845040165224037949064989485675864781542338288371812003786970616765363015207398892429365403085140028636838947208088674554479728968467568193845087863384643126010822482182615887564766419537529231601300283708157228569627286382648092333598304231170038090479933611628581721945809571742144351108955358147387622221559429749729600975061375929222053288676846114279756449968853187230518129053433689461745718747259103438443609003487675272200725271262287676269337186118920962247399126553094827677929926546395430708362915104280111374210563520297880046332360350948646972704479546882442218007306550791946245344565559733508446261205841576322000598307514608048728224030762104576343298917574342730679722460951311597269315508071504391846805678043029993920896003848714977576392961710816581103043141185175931342219691982069334568388489688157642695485239549982541655993815682812667716991249853875333989641541915107389617879982305288007722803728532862384224012215012999540204351542924127534539479663315059168209470760792213991613412454737707259536200014530820678245371735750684616840976663893015095415134832023038873255157201290513795366263462627815067106803621266602767381795626157390399665752608632822537255244590603631478117146489601914986068516325502807451457699123060667209000917411329701940436714750581419217235922025377629477385732393319429604432283591829610561861016240624472737461281445508317150481863879915344922126846683686794580620977452909061992437244436037628852178013795403689914456599826715148996065418695814390167001692080308443557385126544367464053217693519539316533960899379254276856837569932056438248324390353004336107822795768885508999180776199035619582506292122763863210065508122828871854481669595012428953157080699886159146979984238023801210220042698658052941998429849289943728969659668514181339854514134007742746551130248080514632577153690916530546185466500702602760337463438647899649543257728134012054987033793237920287388029930800781621406031095760631471264135091767670027506919292431948465892667414363333411851897761646583770382901173443658581709744582544887860007274452810972227449479789373315733289648454934986516331545018721931597659822385454938133130550879961523950069327658241826039897287043575007413366588671562529276377907719236582825655816382558380209100921542651284881103040346789763855349125940115911822598877253473540379682604510551495168487627646198471316124043054825689319143722968728569766910318841367979363484908594347958434222070583578899749365710335009894528292671747731668923972585858738499160753708161820854247361824260848262957203531053162412769363358054835288168056198946738693499491125260864537456990643001459277987674869498298213477617979959008676942021265236860224736061794851709266868815793060377989333575807158724281703610588029646603990687179054386491152155690469136729048667743746604867064695394536704276500940140805758030708652876774623658382940817470624608733706916423745910516712547257078506743969218459596453206083399736252966950336094119120671143384348836552106917880727209577716503724470957321753504813299333957311515620458345739587336148841879848457881308520848349645621577127392797338127724677783170804804359500385166394028346930968043759261626938950539737308112374755459540857213369465884796881079252234539061570659824508775561797107791940079133361954506634866142507672152242864847313848939262832051707918752071261532462165034124137860566222549084124066540791964051959238938743952656524287567420591764112883324393304732825960419522014466485756974981920491166009714475641454989390758415405131584495930573169521178245805347179018592342594796502917079142756933906125515772207124702931191416971899840862092905694249942150198071244675059218941708497132922874471633786719104163912972578032838175471985731216768483188764060741685827011079022063072952490945466613839138548806338227427136491202495910023403913157351513417981826295717106067397971155985468955443174077507771100456278482638626496682848144745744173783191067133225942316046743911662782919062529075408823890090402130370701857956352804834812975272518464709282589796167812134200712347019225212715926999297027279076728057921919766589250346482600324442870583251813088327313269793891964109966208543942098779896041828434193549982638105301368085459932327374902497724765229143140705528749325837456346782695806663569203430820893885139729260378099546499311633254866672339496246055051980052279501070885464672311606278235265162271678706203625638095650416408259992042952203034560887216753855521849438054868644925360125935823119135561133772625643018711424157280322180273367093213534278466813820778965974804645778821548835328235035713012694378092119362495998353462019754735041261596384485632901617019210230346414165709321304752286884459162201887444445769871339984174542221400326356246816415190846502669295933034320373518611576139049747146392418027566249609727809180233863206961374394830225504036056626098296049924428363778547110441757353157410073226570189479283457546375324894300464336573803309765322872608370321867352784846355927085229820904814821801776954520082992771169950284399088202780878080534716979162155501809095524933984308678637884850881829925873234948860874016052852638624059509781380722442030496345936137989487269506393095795955568655826242990391550146092294147033708547814335294401897382412833649020605921163657876826514424888768600464203921448291149777546361663975425786391518000594834584157759446976713145281759766448253373247794411374559196670288674398023163514023142359760827998360774820228910108754000957287990513870699474249999777628029245969783957986211454203825418714076423545989434377812669589968348027757049449271653498994721440143332241253055289773864433390286180810115980147245136679869560317003271488760202473970859910311405520674951614652316451516335214729497785628463108893735645270018283311848716056885918153855988638807728216319333627410148956800268247753044610638822351438458238708812007022807627200848206928390453304322377383062764282915969940844361787481497145379823297938765822989262451012140016150161356597520186941873917553270148079554930473267611862247751111554294059590053271863543767867987335595664681727796598378304182361388148925220703392205957663364267116703137698527341016249412901925097300361372495083733373625779551904195120681269313559307388952814714088697707846661142942638957300577826351518330197533102790626394905228378853387566527863881750369276032264906290977804197305633366570432956150357571085634212801825412315529596703920262248214656239374615387554188620499747481262463338336436548525341853247733540108701314474268275234112321059148284711374597603741568345477156746348818616191455510010677295020519723915130944619340504474945988549430668018574028523842725589482715850250853957791025395060690969676523875338497520565969932077192190002427381855426987835980213773899860776621739051072293594176436659155567089605158335919014221700337188736885675924182860003194479164171185300421319956854009810252179603093522554245597726871397417583720751013308907322958629072909666814101328099618102848721587284979273123673926808352275930505661063990539698958724644762047726375038465891056402492484850934616731462346718883179684082264874786128048425449846631339341364405103467941508209919390502405916224207970067846528788893950435485333611235217186645299697862945543361853452387778511603651289313350083877937314361712613647643853881700198404946797518359833201713967428839154974945751136969812689232949891910606274958134266019188518261312217632674398486886906711913344115421003091025586926397910059080017253658638851671041314147565478945362897849516822797889788370342209294024020700292010808865331831971903261063346492903467671577471668273864253126427349629960094141892013058823130458257470892438959208516207200464221865004846177949808447228450004153173965943371304142417627750811933741925277610031841153992416035108940104635974506428496114792656270610584480259407295186964107831756878059867939429638458371903107482424823489215744771442838995306045206285594557899057404305754134652252271196721324993012424873147804804511170960243205154326817396112507711767758346846759841430809798078802433762960785512859444861692534271844157927701898113313930231378027921941043274660666569402283737397001904249247351066302040096169257905946337195454415199535655814164519650271841817656047375525815320823728524528777342470680237708931953394629246994521894102551050410487635355533676285808741491477493682796158736445682538607431078787811839728386507206865523038357527561614980293575632379611533899403826903327161736777647710616601997597037443054577692034512336522265658559493920052465206670714118575389907478385080467226544796488941794814329252386847721808773993142815843633742463447828272657674786957037612813013319302760761348891860894001461059895932507636827303453749111417648250619623070801648626907002429109678722778874787369607324736061079857019207761318143039855048072833690608148142057859103187736084290868710323944862391949368313402039338278993233122904503514101801357705917991284221446456929592940747369773899452834350520254765538719374158734311561458739493962906908125281245851889797153555214887401547410366077445903215636970658952557869903401618189111809204979965046008830849756709603570713630575860048103235715165418329546385839303534945959024380628125592776497087684610039432873798794667340710112274201825404489807423483415454770335841107216959059990867824377248024404952295389078106332270598646762239676069269980589763116131669801901781530021754117268963054215195203398831597955414112854730815285303411544962370790173901278276275698896691531290669348430539629850568324463211012042027375505680994508293610209257002805590403416101245602568448970370609453482075335478699151415498428073887328987834770457749033854182985189574501120424851848482563609744575245623505112098812052794962379983644403236819670293400042804087075228125594301607824167659343466222651653553807550106425401195021435191780372929131885080148269599252861101945538231109872314132301112019683495646166507332757794543630783219950700404951698441936284129491419601908570930995374886801500725880655404398109572692670305505420110333828445475861856005006251523961661202470209881688966822868426330369495864411891191119300923943107763528974453186047846621254759255030663410479731925421243767809616955240715454229809100778350805322659293870560593507984977400875693035829326350312510725702425054392855135323912477598213985419300776511932045426681378169237754709389684150839884206721617045561738327338950608551541080831814479895913696338715523713979473591979475148104657525917913702975861731532287247515403220811530274606681064750848328337830876055511820178681143557088702275305041575482136306386288612931225706970762056849188360926811482068295138350060456422939682784556950524626659378053892393987818205711746096198290000652127374538887848350619901348487222686758704670713296535575123677492950283393416863984260396425633395788913282667077108206365197207767234049527381759568688090755626854305459669388391091365180876950303172458344096222251913088467058729077294633540101246138197160838055231640671974042585140803106959676331804254982370887449059423845240774274396310091593761636919845756974009855422424591214905314964315158611519878335305531008517233060615813626310043470071598986271145182675843906415682798672984666681831624100130223941473079040297045808412189200401573372184973255467753270452527382792461434112860665661147135367217325359898228110524413616248265324168458532588536533136396885667758339361126459405287041049888900714990627503774174655458996026663578434472547763226008867883635990642485532752547473505623727378211337115200248085308719971668057796116315845018546788083360221923358088492399153653189581334182059327374301489639107887109553212356535117310350332149959749428388757937232635773978353649032046893073535207503537039996731778582592066553924842922368769788904652969167843878441154056462922210715506264123967480452863091550352099754807993634111603686777540645765436572517129349351938300802047963787270681770150430954285044918868761128974360405928624140929288941658666380199289325112215571337572152434993707569120066352297242077089437491544506858969583474156667522500306703737420539687756878490560542412125863517115044294066914933899113987911065128598906033620678968485896170454295257044961250432469727550641458350213333916465792067765009313511030427607377447078032477692065327635110199240369937696584780328543798444370936507560726062601405219699894654190116587834517282789892802789532969884244357296526706734243124130301796259314033166064759973903508730130678104516821727878665406582656620124624081186276273360865637556742937452453890042737069061617387484473621434513625250730827851192952186925722901056491512566452476242215382776582723144737899950109823923839312109598318920031981573664322178785667548931052742344349091638718097501138115703978422079603351189886747238201672646600905184194159288854641085429393689119041113464935359728185408708905987772766610039500543675731317281219321413477421755646310881731499955684419844603564744786719576000170803774108363573270754391278936548437984634542622228278645655421653208110734198109680351269255988016587959613479232923316848444048229892082622557579130510816443032984273110881933436780841222998389739345575860089793060609106301911660263114038366449957878820221676976967233387672229617866370663155805112157988399935769866909354688563
0x71C05a4e...265d4Bdc8
3.72918195060419102 Eth
Nonce: 771
2.96931268860419102 Eth
Nonce: 772
0.759869262

Execution Trace

AccessControlledAggregator.60c06040( )
pragma solidity 0.6.6;


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

library SignedSafeMath {
  int256 constant private _INT256_MIN = -2**255;

  /**
   * @dev Multiplies two signed integers, reverts on overflow.
   */
  function mul(int256 a, int256 b) internal pure returns (int256) {
    // 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-contracts/pull/522
    if (a == 0) {
      return 0;
    }

    require(!(a == -1 && b == _INT256_MIN), "SignedSafeMath: multiplication overflow");

    int256 c = a * b;
    require(c / a == b, "SignedSafeMath: multiplication overflow");

    return c;
  }

  /**
   * @dev Integer division of two signed integers truncating the quotient, reverts on division by zero.
   */
  function div(int256 a, int256 b) internal pure returns (int256) {
    require(b != 0, "SignedSafeMath: division by zero");
    require(!(b == -1 && a == _INT256_MIN), "SignedSafeMath: division overflow");

    int256 c = a / b;

    return c;
  }

  /**
   * @dev Subtracts two signed integers, reverts on overflow.
   */
  function sub(int256 a, int256 b) internal pure returns (int256) {
    int256 c = a - b;
    require((b >= 0 && c <= a) || (b < 0 && c > a), "SignedSafeMath: subtraction overflow");

    return c;
  }

  /**
   * @dev Adds two signed integers, reverts on overflow.
   */
  function add(int256 a, int256 b) internal pure returns (int256) {
    int256 c = a + b;
    require((b >= 0 && c >= a) || (b < 0 && c < a), "SignedSafeMath: addition overflow");

    return c;
  }

  /**
   * @notice Computes average of two signed integers, ensuring that the computation
   * doesn't overflow.
   * @dev If the result is not an integer, it is rounded towards zero. For example,
   * avg(-3, -4) = -3
   */
  function avg(int256 _a, int256 _b)
    internal
    pure
    returns (int256)
  {
    if ((_a < 0 && _b > 0) || (_a > 0 && _b < 0)) {
      return add(_a, _b) / 2;
    }
    int256 remainder = (_a % 2 + _b % 2) / 2;
    return add(add(_a / 2, _b / 2), remainder);
  }
}

library Median {
  using SignedSafeMath for int256;

  int256 constant INT_MAX = 2**255-1;

  /**
   * @notice Returns the sorted middle, or the average of the two middle indexed items if the
   * array has an even number of elements.
   * @dev The list passed as an argument isn't modified.
   * @dev This algorithm has expected runtime O(n), but for adversarially chosen inputs
   * the runtime is O(n^2).
   * @param list The list of elements to compare
   */
  function calculate(int256[] memory list)
    internal
    pure
    returns (int256)
  {
    return calculateInplace(copy(list));
  }

  /**
   * @notice See documentation for function calculate.
   * @dev The list passed as an argument may be permuted.
   */
  function calculateInplace(int256[] memory list)
    internal
    pure
    returns (int256)
  {
    require(0 < list.length, "list must not be empty");
    uint256 len = list.length;
    uint256 middleIndex = len / 2;
    if (len % 2 == 0) {
      int256 median1;
      int256 median2;
      (median1, median2) = quickselectTwo(list, 0, len - 1, middleIndex - 1, middleIndex);
      return SignedSafeMath.avg(median1, median2);
    } else {
      return quickselect(list, 0, len - 1, middleIndex);
    }
  }

  /**
   * @notice Maximum length of list that shortSelectTwo can handle
   */
  uint256 constant SHORTSELECTTWO_MAX_LENGTH = 7;

  /**
   * @notice Select the k1-th and k2-th element from list of length at most 7
   * @dev Uses an optimal sorting network
   */
  function shortSelectTwo(
    int256[] memory list,
    uint256 lo,
    uint256 hi,
    uint256 k1,
    uint256 k2
  )
    private
    pure
    returns (int256 k1th, int256 k2th)
  {
    // Uses an optimal sorting network (https://en.wikipedia.org/wiki/Sorting_network)
    // for lists of length 7. Network layout is taken from
    // http://jgamble.ripco.net/cgi-bin/nw.cgi?inputs=7&algorithm=hibbard&output=svg

    uint256 len = hi + 1 - lo;
    int256 x0 = list[lo + 0];
    int256 x1 = 1 < len ? list[lo + 1] : INT_MAX;
    int256 x2 = 2 < len ? list[lo + 2] : INT_MAX;
    int256 x3 = 3 < len ? list[lo + 3] : INT_MAX;
    int256 x4 = 4 < len ? list[lo + 4] : INT_MAX;
    int256 x5 = 5 < len ? list[lo + 5] : INT_MAX;
    int256 x6 = 6 < len ? list[lo + 6] : INT_MAX;

    if (x0 > x1) {(x0, x1) = (x1, x0);}
    if (x2 > x3) {(x2, x3) = (x3, x2);}
    if (x4 > x5) {(x4, x5) = (x5, x4);}
    if (x0 > x2) {(x0, x2) = (x2, x0);}
    if (x1 > x3) {(x1, x3) = (x3, x1);}
    if (x4 > x6) {(x4, x6) = (x6, x4);}
    if (x1 > x2) {(x1, x2) = (x2, x1);}
    if (x5 > x6) {(x5, x6) = (x6, x5);}
    if (x0 > x4) {(x0, x4) = (x4, x0);}
    if (x1 > x5) {(x1, x5) = (x5, x1);}
    if (x2 > x6) {(x2, x6) = (x6, x2);}
    if (x1 > x4) {(x1, x4) = (x4, x1);}
    if (x3 > x6) {(x3, x6) = (x6, x3);}
    if (x2 > x4) {(x2, x4) = (x4, x2);}
    if (x3 > x5) {(x3, x5) = (x5, x3);}
    if (x3 > x4) {(x3, x4) = (x4, x3);}

    uint256 index1 = k1 - lo;
    if (index1 == 0) {k1th = x0;}
    else if (index1 == 1) {k1th = x1;}
    else if (index1 == 2) {k1th = x2;}
    else if (index1 == 3) {k1th = x3;}
    else if (index1 == 4) {k1th = x4;}
    else if (index1 == 5) {k1th = x5;}
    else if (index1 == 6) {k1th = x6;}
    else {revert("k1 out of bounds");}

    uint256 index2 = k2 - lo;
    if (k1 == k2) {return (k1th, k1th);}
    else if (index2 == 0) {return (k1th, x0);}
    else if (index2 == 1) {return (k1th, x1);}
    else if (index2 == 2) {return (k1th, x2);}
    else if (index2 == 3) {return (k1th, x3);}
    else if (index2 == 4) {return (k1th, x4);}
    else if (index2 == 5) {return (k1th, x5);}
    else if (index2 == 6) {return (k1th, x6);}
    else {revert("k2 out of bounds");}
  }

  /**
   * @notice Selects the k-th ranked element from list, looking only at indices between lo and hi
   * (inclusive). Modifies list in-place.
   */
  function quickselect(int256[] memory list, uint256 lo, uint256 hi, uint256 k)
    private
    pure
    returns (int256 kth)
  {
    require(lo <= k);
    require(k <= hi);
    while (lo < hi) {
      if (hi - lo < SHORTSELECTTWO_MAX_LENGTH) {
        int256 ignore;
        (kth, ignore) = shortSelectTwo(list, lo, hi, k, k);
        return kth;
      }
      uint256 pivotIndex = partition(list, lo, hi);
      if (k <= pivotIndex) {
        // since pivotIndex < (original hi passed to partition),
        // termination is guaranteed in this case
        hi = pivotIndex;
      } else {
        // since (original lo passed to partition) <= pivotIndex,
        // termination is guaranteed in this case
        lo = pivotIndex + 1;
      }
    }
    return list[lo];
  }

  /**
   * @notice Selects the k1-th and k2-th ranked elements from list, looking only at indices between
   * lo and hi (inclusive). Modifies list in-place.
   */
  function quickselectTwo(
    int256[] memory list,
    uint256 lo,
    uint256 hi,
    uint256 k1,
    uint256 k2
  )
    internal // for testing
    pure
    returns (int256 k1th, int256 k2th)
  {
    require(k1 < k2);
    require(lo <= k1 && k1 <= hi);
    require(lo <= k2 && k2 <= hi);

    while (true) {
      if (hi - lo < SHORTSELECTTWO_MAX_LENGTH) {
        return shortSelectTwo(list, lo, hi, k1, k2);
      }
      uint256 pivotIdx = partition(list, lo, hi);
      if (k2 <= pivotIdx) {
        hi = pivotIdx;
      } else if (pivotIdx < k1) {
        lo = pivotIdx + 1;
      } else {
        assert(k1 <= pivotIdx && pivotIdx < k2);
        k1th = quickselect(list, lo, pivotIdx, k1);
        k2th = quickselect(list, pivotIdx + 1, hi, k2);
        return (k1th, k2th);
      }
    }
  }

  /**
   * @notice Partitions list in-place using Hoare's partitioning scheme.
   * Only elements of list between indices lo and hi (inclusive) will be modified.
   * Returns an index i, such that:
   * - lo <= i < hi
   * - forall j in [lo, i]. list[j] <= list[i]
   * - forall j in [i, hi]. list[i] <= list[j]
   */
  function partition(int256[] memory list, uint256 lo, uint256 hi)
    private
    pure
    returns (uint256)
  {
    // We don't care about overflow of the addition, because it would require a list
    // larger than any feasible computer's memory.
    int256 pivot = list[(lo + hi) / 2];
    lo -= 1; // this can underflow. that's intentional.
    hi += 1;
    while (true) {
      do {
        lo += 1;
      } while (list[lo] < pivot);
      do {
        hi -= 1;
      } while (list[hi] > pivot);
      if (lo < hi) {
        (list[lo], list[hi]) = (list[hi], list[lo]);
      } else {
        // Let orig_lo and orig_hi be the original values of lo and hi passed to partition.
        // Then, hi < orig_hi, because hi decreases *strictly* monotonically
        // in each loop iteration and
        // - either list[orig_hi] > pivot, in which case the first loop iteration
        //   will achieve hi < orig_hi;
        // - or list[orig_hi] <= pivot, in which case at least two loop iterations are
        //   needed:
        //   - lo will have to stop at least once in the interval
        //     [orig_lo, (orig_lo + orig_hi)/2]
        //   - (orig_lo + orig_hi)/2 < orig_hi
        return hi;
      }
    }
  }

  /**
   * @notice Makes an in-memory copy of the array passed in
   * @param list Reference 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;
  }
}

/**
 * @title The Owned contract
 * @notice A contract with helpers for basic contract ownership.
 */
contract Owned {

  address payable public owner;
  address private pendingOwner;

  event OwnershipTransferRequested(
    address indexed from,
    address indexed to
  );
  event OwnershipTransferred(
    address indexed from,
    address indexed to
  );

  constructor() public {
    owner = msg.sender;
  }

  /**
   * @dev Allows an owner to begin transferring ownership to a new address,
   * pending.
   */
  function transferOwnership(address _to)
    external
    onlyOwner()
  {
    pendingOwner = _to;

    emit OwnershipTransferRequested(owner, _to);
  }

  /**
   * @dev Allows an ownership transfer to be completed by the recipient.
   */
  function acceptOwnership()
    external
  {
    require(msg.sender == pendingOwner, "Must be proposed owner");

    address oldOwner = owner;
    owner = msg.sender;
    pendingOwner = address(0);

    emit OwnershipTransferred(oldOwner, msg.sender);
  }

  /**
   * @dev Reverts if called by anyone other than the contract owner.
   */
  modifier onlyOwner() {
    require(msg.sender == owner, "Only callable by owner");
    _;
  }

}

/**
 * @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.
 *
 * This library is a version of Open Zeppelin's SafeMath, modified to support
 * unsigned 128 bit integers.
 */
library SafeMath128 {
  /**
    * @dev Returns the addition of two unsigned integers, reverting on
    * overflow.
    *
    * Counterpart to Solidity's `+` operator.
    *
    * Requirements:
    * - Addition cannot overflow.
    */
  function add(uint128 a, uint128 b) internal pure returns (uint128) {
    uint128 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(uint128 a, uint128 b) internal pure returns (uint128) {
    require(b <= a, "SafeMath: subtraction overflow");
    uint128 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(uint128 a, uint128 b) internal pure returns (uint128) {
    // 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;
    }

    uint128 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(uint128 a, uint128 b) internal pure returns (uint128) {
    // Solidity only automatically asserts when dividing by 0
    require(b > 0, "SafeMath: division by zero");
    uint128 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(uint128 a, uint128 b) internal pure returns (uint128) {
    require(b != 0, "SafeMath: modulo by zero");
    return a % b;
  }
}

/**
 * @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.
 *
 * This library is a version of Open Zeppelin's SafeMath, modified to support
 * unsigned 32 bit integers.
 */
library SafeMath32 {
  /**
    * @dev Returns the addition of two unsigned integers, reverting on
    * overflow.
    *
    * Counterpart to Solidity's `+` operator.
    *
    * Requirements:
    * - Addition cannot overflow.
    */
  function add(uint32 a, uint32 b) internal pure returns (uint32) {
    uint32 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(uint32 a, uint32 b) internal pure returns (uint32) {
    require(b <= a, "SafeMath: subtraction overflow");
    uint32 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(uint32 a, uint32 b) internal pure returns (uint32) {
    // 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;
    }

    uint32 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(uint32 a, uint32 b) internal pure returns (uint32) {
    // Solidity only automatically asserts when dividing by 0
    require(b > 0, "SafeMath: division by zero");
    uint32 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(uint32 a, uint32 b) internal pure returns (uint32) {
    require(b != 0, "SafeMath: modulo by zero");
    return a % b;
  }
}

/**
 * @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.
 *
 * This library is a version of Open Zeppelin's SafeMath, modified to support
 * unsigned 64 bit integers.
 */
library SafeMath64 {
  /**
    * @dev Returns the addition of two unsigned integers, reverting on
    * overflow.
    *
    * Counterpart to Solidity's `+` operator.
    *
    * Requirements:
    * - Addition cannot overflow.
    */
  function add(uint64 a, uint64 b) internal pure returns (uint64) {
    uint64 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(uint64 a, uint64 b) internal pure returns (uint64) {
    require(b <= a, "SafeMath: subtraction overflow");
    uint64 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(uint64 a, uint64 b) internal pure returns (uint64) {
    // 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;
    }

    uint64 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(uint64 a, uint64 b) internal pure returns (uint64) {
    // Solidity only automatically asserts when dividing by 0
    require(b > 0, "SafeMath: division by zero");
    uint64 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(uint64 a, uint64 b) internal pure returns (uint64) {
    require(b != 0, "SafeMath: modulo by zero");
    return a % b;
  }
}

interface AggregatorInterface {
  function latestAnswer() external view returns (int256);
  function latestTimestamp() external view returns (uint256);
  function latestRound() external view returns (uint256);
  function getAnswer(uint256 roundId) external view returns (int256);
  function getTimestamp(uint256 roundId) external view returns (uint256);

  event AnswerUpdated(int256 indexed current, uint256 indexed roundId, uint256 updatedAt);
  event NewRound(uint256 indexed roundId, address indexed startedBy, uint256 startedAt);
}

interface AggregatorV3Interface {

  function decimals() external view returns (uint8);
  function description() external view returns (string memory);
  function version() external view returns (uint256);

  // getRoundData and latestRoundData should both raise "No data present"
  // if they do not have data to report, instead of returning unset values
  // which could be misinterpreted as actual reported values.
  function getRoundData(uint80 _roundId)
    external
    view
    returns (
      uint80 roundId,
      int256 answer,
      uint256 startedAt,
      uint256 updatedAt,
      uint80 answeredInRound
    );
  function latestRoundData()
    external
    view
    returns (
      uint80 roundId,
      int256 answer,
      uint256 startedAt,
      uint256 updatedAt,
      uint80 answeredInRound
    );

}

interface AggregatorV2V3Interface is AggregatorInterface, AggregatorV3Interface
{
}

interface AggregatorValidatorInterface {
  function validate(
    uint256 previousRoundId,
    int256 previousAnswer,
    uint256 currentRoundId,
    int256 currentAnswer
  ) external returns (bool);
}

interface LinkTokenInterface {
  function allowance(address owner, address spender) external view returns (uint256 remaining);
  function approve(address spender, uint256 value) external returns (bool success);
  function balanceOf(address owner) external view returns (uint256 balance);
  function decimals() external view returns (uint8 decimalPlaces);
  function decreaseApproval(address spender, uint256 addedValue) external returns (bool success);
  function increaseApproval(address spender, uint256 subtractedValue) external;
  function name() external view returns (string memory tokenName);
  function symbol() external view returns (string memory tokenSymbol);
  function totalSupply() external view 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);
}

/**
 * @title The Prepaid Aggregator contract
 * @notice Handles aggregating data pushed in from off-chain, and unlocks
 * payment for oracles as they report. Oracles' submissions are gathered in
 * rounds, with each round aggregating the submissions for each oracle into a
 * single answer. The latest aggregated answer is exposed as well as historical
 * answers and their updated at timestamp.
 */
contract FluxAggregator is AggregatorV2V3Interface, Owned {
  using SafeMath for uint256;
  using SafeMath128 for uint128;
  using SafeMath64 for uint64;
  using SafeMath32 for uint32;

  struct Round {
    int256 answer;
    uint64 startedAt;
    uint64 updatedAt;
    uint32 answeredInRound;
  }

  struct RoundDetails {
    int256[] submissions;
    uint32 maxSubmissions;
    uint32 minSubmissions;
    uint32 timeout;
    uint128 paymentAmount;
  }

  struct OracleStatus {
    uint128 withdrawable;
    uint32 startingRound;
    uint32 endingRound;
    uint32 lastReportedRound;
    uint32 lastStartedRound;
    int256 latestSubmission;
    uint16 index;
    address admin;
    address pendingAdmin;
  }

  struct Requester {
    bool authorized;
    uint32 delay;
    uint32 lastStartedRound;
  }

  struct Funds {
    uint128 available;
    uint128 allocated;
  }

  LinkTokenInterface public linkToken;
  AggregatorValidatorInterface public validator;

  // Round related params
  uint128 public paymentAmount;
  uint32 public maxSubmissionCount;
  uint32 public minSubmissionCount;
  uint32 public restartDelay;
  uint32 public timeout;
  uint8 public override decimals;
  string public override description;

  int256 immutable public minSubmissionValue;
  int256 immutable public maxSubmissionValue;

  uint256 constant public override version = 3;

  /**
   * @notice To ensure owner isn't withdrawing required funds as oracles are
   * submitting updates, we enforce that the contract maintains a minimum
   * reserve of RESERVE_ROUNDS * oracleCount() LINK earmarked for payment to
   * oracles. (Of course, this doesn't prevent the contract from running out of
   * funds without the owner's intervention.)
   */
  uint256 constant private RESERVE_ROUNDS = 2;
  uint256 constant private MAX_ORACLE_COUNT = 77;
  uint32 constant private ROUND_MAX = 2**32-1;
  uint256 private constant VALIDATOR_GAS_LIMIT = 100000;
  // An error specific to the Aggregator V3 Interface, to prevent possible
  // confusion around accidentally reading unset values as reported values.
  string constant private V3_NO_DATA_ERROR = "No data present";

  uint32 private reportingRoundId;
  uint32 internal latestRoundId;
  mapping(address => OracleStatus) private oracles;
  mapping(uint32 => Round) internal rounds;
  mapping(uint32 => RoundDetails) internal details;
  mapping(address => Requester) internal requesters;
  address[] private oracleAddresses;
  Funds private recordedFunds;

  event AvailableFundsUpdated(
    uint256 indexed amount
  );
  event RoundDetailsUpdated(
    uint128 indexed paymentAmount,
    uint32 indexed minSubmissionCount,
    uint32 indexed maxSubmissionCount,
    uint32 restartDelay,
    uint32 timeout // measured in seconds
  );
  event OraclePermissionsUpdated(
    address indexed oracle,
    bool indexed whitelisted
  );
  event OracleAdminUpdated(
    address indexed oracle,
    address indexed newAdmin
  );
  event OracleAdminUpdateRequested(
    address indexed oracle,
    address admin,
    address newAdmin
  );
  event SubmissionReceived(
    int256 indexed submission,
    uint32 indexed round,
    address indexed oracle
  );
  event RequesterPermissionsSet(
    address indexed requester,
    bool authorized,
    uint32 delay
  );
  event ValidatorUpdated(
    address indexed previous,
    address indexed current
  );

  /**
   * @notice set up the aggregator with initial configuration
   * @param _link The address of the LINK token
   * @param _paymentAmount The amount paid of LINK paid to each oracle per submission, in wei (units of 10⁻¹⁸ LINK)
   * @param _timeout is the number of seconds after the previous round that are
   * allowed to lapse before allowing an oracle to skip an unfinished round
   * @param _validator is an optional contract address for validating
   * external validation of answers
   * @param _minSubmissionValue is an immutable check for a lower bound of what
   * submission values are accepted from an oracle
   * @param _maxSubmissionValue is an immutable check for an upper bound of what
   * submission values are accepted from an oracle
   * @param _decimals represents the number of decimals to offset the answer by
   * @param _description a short description of what is being reported
   */
  constructor(
    address _link,
    uint128 _paymentAmount,
    uint32 _timeout,
    address _validator,
    int256 _minSubmissionValue,
    int256 _maxSubmissionValue,
    uint8 _decimals,
    string memory _description
  ) public {
    linkToken = LinkTokenInterface(_link);
    updateFutureRounds(_paymentAmount, 0, 0, 0, _timeout);
    setValidator(_validator);
    minSubmissionValue = _minSubmissionValue;
    maxSubmissionValue = _maxSubmissionValue;
    decimals = _decimals;
    description = _description;
    rounds[0].updatedAt = uint64(block.timestamp.sub(uint256(_timeout)));
  }

  /**
   * @notice called by oracles when they have witnessed a need to update
   * @param _roundId is the ID of the round this submission pertains to
   * @param _submission is the updated data that the oracle is submitting
   */
  function submit(uint256 _roundId, int256 _submission)
    external
  {
    bytes memory error = validateOracleRound(msg.sender, uint32(_roundId));
    require(_submission >= minSubmissionValue, "value below minSubmissionValue");
    require(_submission <= maxSubmissionValue, "value above maxSubmissionValue");
    require(error.length == 0, string(error));

    oracleInitializeNewRound(uint32(_roundId));
    recordSubmission(_submission, uint32(_roundId));
    (bool updated, int256 newAnswer) = updateRoundAnswer(uint32(_roundId));
    payOracle(uint32(_roundId));
    deleteRoundDetails(uint32(_roundId));
    if (updated) {
      validateAnswer(uint32(_roundId), newAnswer);
    }
  }

  /**
   * @notice called by the owner to remove and add new oracles as well as
   * update the round related parameters that pertain to total oracle count
   * @param _removed is the list of addresses for the new Oracles being removed
   * @param _added is the list of addresses for the new Oracles being added
   * @param _addedAdmins is the admin addresses for the new respective _added
   * list. Only this address is allowed to access the respective oracle's funds
   * @param _minSubmissions is the new minimum submission count for each round
   * @param _maxSubmissions is the new maximum submission count for each round
   * @param _restartDelay is the number of rounds an Oracle has to wait before
   * they can initiate a round
   */
  function changeOracles(
    address[] calldata _removed,
    address[] calldata _added,
    address[] calldata _addedAdmins,
    uint32 _minSubmissions,
    uint32 _maxSubmissions,
    uint32 _restartDelay
  )
    external
    onlyOwner()
  {
    for (uint256 i = 0; i < _removed.length; i++) {
      removeOracle(_removed[i]);
    }

    require(_added.length == _addedAdmins.length, "need same oracle and admin count");
    require(uint256(oracleCount()).add(_added.length) <= MAX_ORACLE_COUNT, "max oracles allowed");

    for (uint256 i = 0; i < _added.length; i++) {
      addOracle(_added[i], _addedAdmins[i]);
    }

    updateFutureRounds(paymentAmount, _minSubmissions, _maxSubmissions, _restartDelay, timeout);
  }

  /**
   * @notice update the round and payment related parameters for subsequent
   * rounds
   * @param _paymentAmount is the payment amount for subsequent rounds
   * @param _minSubmissions is the new minimum submission count for each round
   * @param _maxSubmissions is the new maximum submission count for each round
   * @param _restartDelay is the number of rounds an Oracle has to wait before
   * they can initiate a round
   */
  function updateFutureRounds(
    uint128 _paymentAmount,
    uint32 _minSubmissions,
    uint32 _maxSubmissions,
    uint32 _restartDelay,
    uint32 _timeout
  )
    public
    onlyOwner()
  {
    uint32 oracleNum = oracleCount(); // Save on storage reads
    require(_maxSubmissions >= _minSubmissions, "max must equal/exceed min");
    require(oracleNum >= _maxSubmissions, "max cannot exceed total");
    require(oracleNum == 0 || oracleNum > _restartDelay, "delay cannot exceed total");
    require(recordedFunds.available >= requiredReserve(_paymentAmount), "insufficient funds for payment");
    if (oracleCount() > 0) {
      require(_minSubmissions > 0, "min must be greater than 0");
    }

    paymentAmount = _paymentAmount;
    minSubmissionCount = _minSubmissions;
    maxSubmissionCount = _maxSubmissions;
    restartDelay = _restartDelay;
    timeout = _timeout;

    emit RoundDetailsUpdated(
      paymentAmount,
      _minSubmissions,
      _maxSubmissions,
      _restartDelay,
      _timeout
    );
  }

  /**
   * @notice the amount of payment yet to be withdrawn by oracles
   */
  function allocatedFunds()
    external
    view
    returns (uint128)
  {
    return recordedFunds.allocated;
  }

  /**
   * @notice the amount of future funding available to oracles
   */
  function availableFunds()
    external
    view
    returns (uint128)
  {
    return recordedFunds.available;
  }

  /**
   * @notice recalculate the amount of LINK available for payouts
   */
  function updateAvailableFunds()
    public
  {
    Funds memory funds = recordedFunds;

    uint256 nowAvailable = linkToken.balanceOf(address(this)).sub(funds.allocated);

    if (funds.available != nowAvailable) {
      recordedFunds.available = uint128(nowAvailable);
      emit AvailableFundsUpdated(nowAvailable);
    }
  }

  /**
   * @notice returns the number of oracles
   */
  function oracleCount() public view returns (uint8) {
    return uint8(oracleAddresses.length);
  }

  /**
   * @notice returns an array of addresses containing the oracles on contract
   */
  function getOracles() external view returns (address[] memory) {
    return oracleAddresses;
  }

  /**
   * @notice get the most recently reported answer
   *
   * @dev #[deprecated] Use latestRoundData instead. This does not error if no
   * answer has been reached, it will simply return 0. Either wait to point to
   * an already answered Aggregator or use the recommended latestRoundData
   * instead which includes better verification information.
   */
  function latestAnswer()
    public
    view
    virtual
    override
    returns (int256)
  {
    return rounds[latestRoundId].answer;
  }

  /**
   * @notice get the most recent updated at timestamp
   *
   * @dev #[deprecated] Use latestRoundData instead. This does not error if no
   * answer has been reached, it will simply return 0. Either wait to point to
   * an already answered Aggregator or use the recommended latestRoundData
   * instead which includes better verification information.
   */
  function latestTimestamp()
    public
    view
    virtual
    override
    returns (uint256)
  {
    return rounds[latestRoundId].updatedAt;
  }

  /**
   * @notice get the ID of the last updated round
   *
   * @dev #[deprecated] Use latestRoundData instead. This does not error if no
   * answer has been reached, it will simply return 0. Either wait to point to
   * an already answered Aggregator or use the recommended latestRoundData
   * instead which includes better verification information.
   */
  function latestRound()
    public
    view
    virtual
    override
    returns (uint256)
  {
    return latestRoundId;
  }

  /**
   * @notice get past rounds answers
   * @param _roundId the round number to retrieve the answer for
   *
   * @dev #[deprecated] Use getRoundData instead. This does not error if no
   * answer has been reached, it will simply return 0. Either wait to point to
   * an already answered Aggregator or use the recommended getRoundData
   * instead which includes better verification information.
   */
  function getAnswer(uint256 _roundId)
    public
    view
    virtual
    override
    returns (int256)
  {
    if (validRoundId(_roundId)) {
      return rounds[uint32(_roundId)].answer;
    }
    return 0;
  }

  /**
   * @notice get timestamp when an answer was last updated
   * @param _roundId the round number to retrieve the updated timestamp for
   *
   * @dev #[deprecated] Use getRoundData instead. This does not error if no
   * answer has been reached, it will simply return 0. Either wait to point to
   * an already answered Aggregator or use the recommended getRoundData
   * instead which includes better verification information.
   */
  function getTimestamp(uint256 _roundId)
    public
    view
    virtual
    override
    returns (uint256)
  {
    if (validRoundId(_roundId)) {
      return rounds[uint32(_roundId)].updatedAt;
    }
    return 0;
  }

  /**
   * @notice get data about a round. Consumers are encouraged to check
   * that they're receiving fresh data by inspecting the updatedAt and
   * answeredInRound return values.
   * @param _roundId the round ID to retrieve the round data for
   * @return roundId is the round ID for which data was retrieved
   * @return answer is the answer for the given round
   * @return startedAt is the timestamp when the round was started. This is 0
   * if the round hasn't been started yet.
   * @return updatedAt is the timestamp when the round last was updated (i.e.
   * answer was last computed)
   * @return answeredInRound is the round ID of the round in which the answer
   * was computed. answeredInRound may be smaller than roundId when the round
   * timed out. answeredInRound is equal to roundId when the round didn't time out
   * and was completed regularly.
   * @dev Note that for in-progress rounds (i.e. rounds that haven't yet received
   * maxSubmissions) answer and updatedAt may change between queries.
   */
  function getRoundData(uint80 _roundId)
    public
    view
    virtual
    override
    returns (
      uint80 roundId,
      int256 answer,
      uint256 startedAt,
      uint256 updatedAt,
      uint80 answeredInRound
    )
  {
    Round memory r = rounds[uint32(_roundId)];

    require(r.answeredInRound > 0 && validRoundId(_roundId), V3_NO_DATA_ERROR);

    return (
      _roundId,
      r.answer,
      r.startedAt,
      r.updatedAt,
      r.answeredInRound
    );
  }

  /**
   * @notice get data about the latest round. Consumers are encouraged to check
   * that they're receiving fresh data by inspecting the updatedAt and
   * answeredInRound return values. Consumers are encouraged to
   * use this more fully featured method over the "legacy" latestRound/
   * latestAnswer/latestTimestamp functions. Consumers are encouraged to check
   * that they're receiving fresh data by inspecting the updatedAt and
   * answeredInRound return values.
   * @return roundId is the round ID for which data was retrieved
   * @return answer is the answer for the given round
   * @return startedAt is the timestamp when the round was started. This is 0
   * if the round hasn't been started yet.
   * @return updatedAt is the timestamp when the round last was updated (i.e.
   * answer was last computed)
   * @return answeredInRound is the round ID of the round in which the answer
   * was computed. answeredInRound may be smaller than roundId when the round
   * timed out. answeredInRound is equal to roundId when the round didn't time
   * out and was completed regularly.
   * @dev Note that for in-progress rounds (i.e. rounds that haven't yet
   * received maxSubmissions) answer and updatedAt may change between queries.
   */
   function latestRoundData()
    public
    view
    virtual
    override
    returns (
      uint80 roundId,
      int256 answer,
      uint256 startedAt,
      uint256 updatedAt,
      uint80 answeredInRound
    )
  {
    return getRoundData(latestRoundId);
  }


  /**
   * @notice query the available amount of LINK for an oracle to withdraw
   */
  function withdrawablePayment(address _oracle)
    external
    view
    returns (uint256)
  {
    return oracles[_oracle].withdrawable;
  }

  /**
   * @notice transfers the oracle's LINK to another address. Can only be called
   * by the oracle's admin.
   * @param _oracle is the oracle whose LINK is transferred
   * @param _recipient is the address to send the LINK to
   * @param _amount is the amount of LINK to send
   */
  function withdrawPayment(address _oracle, address _recipient, uint256 _amount)
    external
  {
    require(oracles[_oracle].admin == msg.sender, "only callable by admin");

    // Safe to downcast _amount because the total amount of LINK is less than 2^128.
    uint128 amount = uint128(_amount);
    uint128 available = oracles[_oracle].withdrawable;
    require(available >= amount, "insufficient withdrawable funds");

    oracles[_oracle].withdrawable = available.sub(amount);
    recordedFunds.allocated = recordedFunds.allocated.sub(amount);

    assert(linkToken.transfer(_recipient, uint256(amount)));
  }

  /**
   * @notice transfers the owner's LINK to another address
   * @param _recipient is the address to send the LINK to
   * @param _amount is the amount of LINK to send
   */
  function withdrawFunds(address _recipient, uint256 _amount)
    external
    onlyOwner()
  {
    uint256 available = uint256(recordedFunds.available);
    require(available.sub(requiredReserve(paymentAmount)) >= _amount, "insufficient reserve funds");
    require(linkToken.transfer(_recipient, _amount), "token transfer failed");
    updateAvailableFunds();
  }

  /**
   * @notice get the admin address of an oracle
   * @param _oracle is the address of the oracle whose admin is being queried
   */
  function getAdmin(address _oracle)
    external
    view
    returns (address)
  {
    return oracles[_oracle].admin;
  }

  /**
   * @notice transfer the admin address for an oracle
   * @param _oracle is the address of the oracle whose admin is being transferred
   * @param _newAdmin is the new admin address
   */
  function transferAdmin(address _oracle, address _newAdmin)
    external
  {
    require(oracles[_oracle].admin == msg.sender, "only callable by admin");
    oracles[_oracle].pendingAdmin = _newAdmin;

    emit OracleAdminUpdateRequested(_oracle, msg.sender, _newAdmin);
  }

  /**
   * @notice accept the admin address transfer for an oracle
   * @param _oracle is the address of the oracle whose admin is being transferred
   */
  function acceptAdmin(address _oracle)
    external
  {
    require(oracles[_oracle].pendingAdmin == msg.sender, "only callable by pending admin");
    oracles[_oracle].pendingAdmin = address(0);
    oracles[_oracle].admin = msg.sender;

    emit OracleAdminUpdated(_oracle, msg.sender);
  }

  /**
   * @notice allows non-oracles to request a new round
   */
  function requestNewRound()
    external
    returns (uint80)
  {
    require(requesters[msg.sender].authorized, "not authorized requester");

    uint32 current = reportingRoundId;
    require(rounds[current].updatedAt > 0 || timedOut(current), "prev round must be supersedable");

    uint32 newRoundId = current.add(1);
    requesterInitializeNewRound(newRoundId);
    return newRoundId;
  }

  /**
   * @notice allows the owner to specify new non-oracles to start new rounds
   * @param _requester is the address to set permissions for
   * @param _authorized is a boolean specifying whether they can start new rounds or not
   * @param _delay is the number of rounds the requester must wait before starting another round
   */
  function setRequesterPermissions(address _requester, bool _authorized, uint32 _delay)
    external
    onlyOwner()
  {
    if (requesters[_requester].authorized == _authorized) return;

    if (_authorized) {
      requesters[_requester].authorized = _authorized;
      requesters[_requester].delay = _delay;
    } else {
      delete requesters[_requester];
    }

    emit RequesterPermissionsSet(_requester, _authorized, _delay);
  }

  /**
   * @notice called through LINK's transferAndCall to update available funds
   * in the same transaction as the funds were transferred to the aggregator
   * @param _data is mostly ignored. It is checked for length, to be sure
   * nothing strange is passed in.
   */
  function onTokenTransfer(address, uint256, bytes calldata _data)
    external
  {
    require(_data.length == 0, "transfer doesn't accept calldata");
    updateAvailableFunds();
  }

  /**
   * @notice a method to provide all current info oracles need. Intended only
   * only to be callable by oracles. Not for use by contracts to read state.
   * @param _oracle the address to look up information for.
   */
  function oracleRoundState(address _oracle, uint32 _queriedRoundId)
    external
    view
    returns (
      bool _eligibleToSubmit,
      uint32 _roundId,
      int256 _latestSubmission,
      uint64 _startedAt,
      uint64 _timeout,
      uint128 _availableFunds,
      uint8 _oracleCount,
      uint128 _paymentAmount
    )
  {
    require(msg.sender == tx.origin, "off-chain reading only");

    if (_queriedRoundId > 0) {
      Round storage round = rounds[_queriedRoundId];
      RoundDetails storage details = details[_queriedRoundId];
      return (
        eligibleForSpecificRound(_oracle, _queriedRoundId),
        _queriedRoundId,
        oracles[_oracle].latestSubmission,
        round.startedAt,
        details.timeout,
        recordedFunds.available,
        oracleCount(),
        (round.startedAt > 0 ? details.paymentAmount : paymentAmount)
      );
    } else {
      return oracleRoundStateSuggestRound(_oracle);
    }
  }

  /**
   * @notice method to update the address which does external data validation.
   * @param _newValidator designates the address of the new validation contract.
   */
  function setValidator(address _newValidator)
    public
    onlyOwner()
  {
    address previous = address(validator);

    if (previous != _newValidator) {
      validator = AggregatorValidatorInterface(_newValidator);

      emit ValidatorUpdated(previous, _newValidator);
    }
  }


  /**
   * Private
   */

  function initializeNewRound(uint32 _roundId)
    private
  {
    updateTimedOutRoundInfo(_roundId.sub(1));

    reportingRoundId = _roundId;
    RoundDetails memory nextDetails = RoundDetails(
      new int256[](0),
      maxSubmissionCount,
      minSubmissionCount,
      timeout,
      paymentAmount
    );
    details[_roundId] = nextDetails;
    rounds[_roundId].startedAt = uint64(block.timestamp);

    emit NewRound(_roundId, msg.sender, rounds[_roundId].startedAt);
  }

  function oracleInitializeNewRound(uint32 _roundId)
    private
  {
    if (!newRound(_roundId)) return;
    uint256 lastStarted = oracles[msg.sender].lastStartedRound; // cache storage reads
    if (_roundId <= lastStarted + restartDelay && lastStarted != 0) return;

    initializeNewRound(_roundId);

    oracles[msg.sender].lastStartedRound = _roundId;
  }

  function requesterInitializeNewRound(uint32 _roundId)
    private
  {
    if (!newRound(_roundId)) return;
    uint256 lastStarted = requesters[msg.sender].lastStartedRound; // cache storage reads
    require(_roundId > lastStarted + requesters[msg.sender].delay || lastStarted == 0, "must delay requests");

    initializeNewRound(_roundId);

    requesters[msg.sender].lastStartedRound = _roundId;
  }

  function updateTimedOutRoundInfo(uint32 _roundId)
    private
  {
    if (!timedOut(_roundId)) return;

    uint32 prevId = _roundId.sub(1);
    rounds[_roundId].answer = rounds[prevId].answer;
    rounds[_roundId].answeredInRound = rounds[prevId].answeredInRound;
    rounds[_roundId].updatedAt = uint64(block.timestamp);

    delete details[_roundId];
  }

  function eligibleForSpecificRound(address _oracle, uint32 _queriedRoundId)
    private
    view
    returns (bool _eligible)
  {
    if (rounds[_queriedRoundId].startedAt > 0) {
      return acceptingSubmissions(_queriedRoundId) && validateOracleRound(_oracle, _queriedRoundId).length == 0;
    } else {
      return delayed(_oracle, _queriedRoundId) && validateOracleRound(_oracle, _queriedRoundId).length == 0;
    }
  }

  function oracleRoundStateSuggestRound(address _oracle)
    private
    view
    returns (
      bool _eligibleToSubmit,
      uint32 _roundId,
      int256 _latestSubmission,
      uint64 _startedAt,
      uint64 _timeout,
      uint128 _availableFunds,
      uint8 _oracleCount,
      uint128 _paymentAmount
    )
  {
    Round storage round = rounds[0];
    OracleStatus storage oracle = oracles[_oracle];

    bool shouldSupersede = oracle.lastReportedRound == reportingRoundId || !acceptingSubmissions(reportingRoundId);
    // Instead of nudging oracles to submit to the next round, the inclusion of
    // the shouldSupersede bool in the if condition pushes them towards
    // submitting in a currently open round.
    if (supersedable(reportingRoundId) && shouldSupersede) {
      _roundId = reportingRoundId.add(1);
      round = rounds[_roundId];

      _paymentAmount = paymentAmount;
      _eligibleToSubmit = delayed(_oracle, _roundId);
    } else {
      _roundId = reportingRoundId;
      round = rounds[_roundId];

      _paymentAmount = details[_roundId].paymentAmount;
      _eligibleToSubmit = acceptingSubmissions(_roundId);
    }

    if (validateOracleRound(_oracle, _roundId).length != 0) {
      _eligibleToSubmit = false;
    }

    return (
      _eligibleToSubmit,
      _roundId,
      oracle.latestSubmission,
      round.startedAt,
      details[_roundId].timeout,
      recordedFunds.available,
      oracleCount(),
      _paymentAmount
    );
  }

  function updateRoundAnswer(uint32 _roundId)
    internal
    returns (bool, int256)
  {
    if (details[_roundId].submissions.length < details[_roundId].minSubmissions) {
      return (false, 0);
    }

    int256 newAnswer = Median.calculateInplace(details[_roundId].submissions);
    rounds[_roundId].answer = newAnswer;
    rounds[_roundId].updatedAt = uint64(block.timestamp);
    rounds[_roundId].answeredInRound = _roundId;
    latestRoundId = _roundId;

    emit AnswerUpdated(newAnswer, _roundId, now);

    return (true, newAnswer);
  }

  function validateAnswer(
    uint32 _roundId,
    int256 _newAnswer
  )
    private
  {
    AggregatorValidatorInterface av = validator; // cache storage reads
    if (address(av) == address(0)) return;

    uint32 prevRound = _roundId.sub(1);
    uint32 prevAnswerRoundId = rounds[prevRound].answeredInRound;
    int256 prevRoundAnswer = rounds[prevRound].answer;
    // We do not want the validator to ever prevent reporting, so we limit its
    // gas usage and catch any errors that may arise.
    try av.validate{gas: VALIDATOR_GAS_LIMIT}(
      prevAnswerRoundId,
      prevRoundAnswer,
      _roundId,
      _newAnswer
    ) {} catch {}
  }

  function payOracle(uint32 _roundId)
    private
  {
    uint128 payment = details[_roundId].paymentAmount;
    Funds memory funds = recordedFunds;
    funds.available = funds.available.sub(payment);
    funds.allocated = funds.allocated.add(payment);
    recordedFunds = funds;
    oracles[msg.sender].withdrawable = oracles[msg.sender].withdrawable.add(payment);

    emit AvailableFundsUpdated(funds.available);
  }

  function recordSubmission(int256 _submission, uint32 _roundId)
    private
  {
    require(acceptingSubmissions(_roundId), "round not accepting submissions");

    details[_roundId].submissions.push(_submission);
    oracles[msg.sender].lastReportedRound = _roundId;
    oracles[msg.sender].latestSubmission = _submission;

    emit SubmissionReceived(_submission, _roundId, msg.sender);
  }

  function deleteRoundDetails(uint32 _roundId)
    private
  {
    if (details[_roundId].submissions.length < details[_roundId].maxSubmissions) return;

    delete details[_roundId];
  }

  function timedOut(uint32 _roundId)
    private
    view
    returns (bool)
  {
    uint64 startedAt = rounds[_roundId].startedAt;
    uint32 roundTimeout = details[_roundId].timeout;
    return startedAt > 0 && roundTimeout > 0 && startedAt.add(roundTimeout) < block.timestamp;
  }

  function getStartingRound(address _oracle)
    private
    view
    returns (uint32)
  {
    uint32 currentRound = reportingRoundId;
    if (currentRound != 0 && currentRound == oracles[_oracle].endingRound) {
      return currentRound;
    }
    return currentRound.add(1);
  }

  function previousAndCurrentUnanswered(uint32 _roundId, uint32 _rrId)
    private
    view
    returns (bool)
  {
    return _roundId.add(1) == _rrId && rounds[_rrId].updatedAt == 0;
  }

  function requiredReserve(uint256 payment)
    private
    view
    returns (uint256)
  {
    return payment.mul(oracleCount()).mul(RESERVE_ROUNDS);
  }

  function addOracle(
    address _oracle,
    address _admin
  )
    private
  {
    require(!oracleEnabled(_oracle), "oracle already enabled");

    require(_admin != address(0), "cannot set admin to 0");
    require(oracles[_oracle].admin == address(0) || oracles[_oracle].admin == _admin, "owner cannot overwrite admin");

    oracles[_oracle].startingRound = getStartingRound(_oracle);
    oracles[_oracle].endingRound = ROUND_MAX;
    oracles[_oracle].index = uint16(oracleAddresses.length);
    oracleAddresses.push(_oracle);
    oracles[_oracle].admin = _admin;

    emit OraclePermissionsUpdated(_oracle, true);
    emit OracleAdminUpdated(_oracle, _admin);
  }

  function removeOracle(
    address _oracle
  )
    private
  {
    require(oracleEnabled(_oracle), "oracle not enabled");

    oracles[_oracle].endingRound = reportingRoundId.add(1);
    address tail = oracleAddresses[uint256(oracleCount()).sub(1)];
    uint16 index = oracles[_oracle].index;
    oracles[tail].index = index;
    delete oracles[_oracle].index;
    oracleAddresses[index] = tail;
    oracleAddresses.pop();

    emit OraclePermissionsUpdated(_oracle, false);
  }

  function validateOracleRound(address _oracle, uint32 _roundId)
    private
    view
    returns (bytes memory)
  {
    // cache storage reads
    uint32 startingRound = oracles[_oracle].startingRound;
    uint32 rrId = reportingRoundId;

    if (startingRound == 0) return "not enabled oracle";
    if (startingRound > _roundId) return "not yet enabled oracle";
    if (oracles[_oracle].endingRound < _roundId) return "no longer allowed oracle";
    if (oracles[_oracle].lastReportedRound >= _roundId) return "cannot report on previous rounds";
    if (_roundId != rrId && _roundId != rrId.add(1) && !previousAndCurrentUnanswered(_roundId, rrId)) return "invalid round to report";
    if (_roundId != 1 && !supersedable(_roundId.sub(1))) return "previous round not supersedable";
  }

  function supersedable(uint32 _roundId)
    private
    view
    returns (bool)
  {
    return rounds[_roundId].updatedAt > 0 || timedOut(_roundId);
  }

  function oracleEnabled(address _oracle)
    private
    view
    returns (bool)
  {
    return oracles[_oracle].endingRound == ROUND_MAX;
  }

  function acceptingSubmissions(uint32 _roundId)
    private
    view
    returns (bool)
  {
    return details[_roundId].maxSubmissions != 0;
  }

  function delayed(address _oracle, uint32 _roundId)
    private
    view
    returns (bool)
  {
    uint256 lastStarted = oracles[_oracle].lastStartedRound;
    return _roundId > lastStarted + restartDelay || lastStarted == 0;
  }

  function newRound(uint32 _roundId)
    private
    view
    returns (bool)
  {
    return _roundId == reportingRoundId.add(1);
  }

  function validRoundId(uint256 _roundId)
    private
    view
    returns (bool)
  {
    return _roundId <= ROUND_MAX;
  }

}

interface AccessControllerInterface {
  function hasAccess(address user, bytes calldata data) external view returns (bool);
}

/**
 * @title SimpleWriteAccessController
 * @notice Gives access to accounts explicitly added to an access list by the
 * controller's owner.
 * @dev does not make any special permissions for externally, see
 * SimpleReadAccessController for that.
 */
contract SimpleWriteAccessController is AccessControllerInterface, Owned {

  bool public checkEnabled;
  mapping(address => bool) internal accessList;

  event AddedAccess(address user);
  event RemovedAccess(address user);
  event CheckAccessEnabled();
  event CheckAccessDisabled();

  constructor()
    public
  {
    checkEnabled = true;
  }

  /**
   * @notice Returns the access of an address
   * @param _user The address to query
   */
  function hasAccess(
    address _user,
    bytes memory
  )
    public
    view
    virtual
    override
    returns (bool)
  {
    return accessList[_user] || !checkEnabled;
  }

  /**
   * @notice Adds an address to the access list
   * @param _user The address to add
   */
  function addAccess(address _user)
    external
    onlyOwner()
  {
    if (!accessList[_user]) {
      accessList[_user] = true;

      emit AddedAccess(_user);
    }
  }

  /**
   * @notice Removes an address from the access list
   * @param _user The address to remove
   */
  function removeAccess(address _user)
    external
    onlyOwner()
  {
    if (accessList[_user]) {
      accessList[_user] = false;

      emit RemovedAccess(_user);
    }
  }

  /**
   * @notice makes the access check enforced
   */
  function enableAccessCheck()
    external
    onlyOwner()
  {
    if (!checkEnabled) {
      checkEnabled = true;

      emit CheckAccessEnabled();
    }
  }

  /**
   * @notice makes the access check unenforced
   */
  function disableAccessCheck()
    external
    onlyOwner()
  {
    if (checkEnabled) {
      checkEnabled = false;

      emit CheckAccessDisabled();
    }
  }

  /**
   * @dev reverts if the caller does not have access
   */
  modifier checkAccess() {
    require(hasAccess(msg.sender, msg.data), "No access");
    _;
  }
}

/**
 * @title SimpleReadAccessController
 * @notice Gives access to:
 * - any externally owned account (note that offchain actors can always read
 * any contract storage regardless of onchain access control measures, so this
 * does not weaken the access control while improving usability)
 * - accounts explicitly added to an access list
 * @dev SimpleReadAccessController is not suitable for access controlling writes
 * since it grants any externally owned account access! See
 * SimpleWriteAccessController for that.
 */
contract SimpleReadAccessController is SimpleWriteAccessController {

  /**
   * @notice Returns the access of an address
   * @param _user The address to query
   */
  function hasAccess(
    address _user,
    bytes memory _calldata
  )
    public
    view
    virtual
    override
    returns (bool)
  {
    return super.hasAccess(_user, _calldata) || _user == tx.origin;
  }

}

/**
 * @title AccessControlled FluxAggregator contract
 * @notice This contract requires addresses to be added to a controller
 * in order to read the answers stored in the FluxAggregator contract
 */
contract AccessControlledAggregator is FluxAggregator, SimpleReadAccessController {

  /**
   * @notice set up the aggregator with initial configuration
   * @param _link The address of the LINK token
   * @param _paymentAmount The amount paid of LINK paid to each oracle per submission, in wei (units of 10⁻¹⁸ LINK)
   * @param _timeout is the number of seconds after the previous round that are
   * allowed to lapse before allowing an oracle to skip an unfinished round
   * @param _validator is an optional contract address for validating
   * external validation of answers
   * @param _minSubmissionValue is an immutable check for a lower bound of what
   * submission values are accepted from an oracle
   * @param _maxSubmissionValue is an immutable check for an upper bound of what
   * submission values are accepted from an oracle
   * @param _decimals represents the number of decimals to offset the answer by
   * @param _description a short description of what is being reported
   */
  constructor(
    address _link,
    uint128 _paymentAmount,
    uint32 _timeout,
    address _validator,
    int256 _minSubmissionValue,
    int256 _maxSubmissionValue,
    uint8 _decimals,
    string memory _description
  ) public FluxAggregator(
    _link,
    _paymentAmount,
    _timeout,
    _validator,
    _minSubmissionValue,
    _maxSubmissionValue,
    _decimals,
    _description
  ){}

  /**
   * @notice get data about a round. Consumers are encouraged to check
   * that they're receiving fresh data by inspecting the updatedAt and
   * answeredInRound return values.
   * @param _roundId the round ID to retrieve the round data for
   * @return roundId is the round ID for which data was retrieved
   * @return answer is the answer for the given round
   * @return startedAt is the timestamp when the round was started. This is 0
   * if the round hasn't been started yet.
   * @return updatedAt is the timestamp when the round last was updated (i.e.
   * answer was last computed)
   * @return answeredInRound is the round ID of the round in which the answer
   * was computed. answeredInRound may be smaller than roundId when the round
   * timed out. answerInRound is equal to roundId when the round didn't time out
   * and was completed regularly.
   * @dev overridden funcion to add the checkAccess() modifier
   * @dev Note that for in-progress rounds (i.e. rounds that haven't yet
   * received maxSubmissions) answer and updatedAt may change between queries.
   */
  function getRoundData(uint80 _roundId)
    public
    view
    override
    checkAccess()
    returns (
      uint80 roundId,
      int256 answer,
      uint256 startedAt,
      uint256 updatedAt,
      uint80 answeredInRound
    )
  {
    return super.getRoundData(_roundId);
  }

  /**
   * @notice get data about the latest round. Consumers are encouraged to check
   * that they're receiving fresh data by inspecting the updatedAt and
   * answeredInRound return values. Consumers are encouraged to
   * use this more fully featured method over the "legacy" latestAnswer
   * functions. Consumers are encouraged to check that they're receiving fresh
   * data by inspecting the updatedAt and answeredInRound return values.
   * @return roundId is the round ID for which data was retrieved
   * @return answer is the answer for the given round
   * @return startedAt is the timestamp when the round was started. This is 0
   * if the round hasn't been started yet.
   * @return updatedAt is the timestamp when the round last was updated (i.e.
   * answer was last computed)
   * @return answeredInRound is the round ID of the round in which the answer
   * was computed. answeredInRound may be smaller than roundId when the round
   * timed out. answerInRound is equal to roundId when the round didn't time out
   * and was completed regularly.
   * @dev overridden funcion to add the checkAccess() modifier
   * @dev Note that for in-progress rounds (i.e. rounds that haven't yet
   * received maxSubmissions) answer and updatedAt may change between queries.
   */
  function latestRoundData()
    public
    view
    override
    checkAccess()
    returns (
      uint80 roundId,
      int256 answer,
      uint256 startedAt,
      uint256 updatedAt,
      uint80 answeredInRound
    )
  {
    return super.latestRoundData();
  }

  /**
   * @notice get the most recently reported answer
   * @dev overridden funcion to add the checkAccess() modifier
   *
   * @dev #[deprecated] Use latestRoundData instead. This does not error if no
   * answer has been reached, it will simply return 0. Either wait to point to
   * an already answered Aggregator or use the recommended latestRoundData
   * instead which includes better verification information.
   */
  function latestAnswer()
    public
    view
    override
    checkAccess()
    returns (int256)
  {
    return super.latestAnswer();
  }

  /**
   * @notice get the most recently reported round ID
   * @dev overridden funcion to add the checkAccess() modifier
   *
   * @dev #[deprecated] Use latestRoundData instead. This does not error if no
   * answer has been reached, it will simply return 0. Either wait to point to
   * an already answered Aggregator or use the recommended latestRoundData
   * instead which includes better verification information.
   */
  function latestRound()
    public
    view
    override
    checkAccess()
    returns (uint256)
  {
    return super.latestRound();
  }

  /**
   * @notice get the most recent updated at timestamp
   * @dev overridden funcion to add the checkAccess() modifier
   *
   * @dev #[deprecated] Use latestRoundData instead. This does not error if no
   * answer has been reached, it will simply return 0. Either wait to point to
   * an already answered Aggregator or use the recommended latestRoundData
   * instead which includes better verification information.
   */
  function latestTimestamp()
    public
    view
    override
    checkAccess()
    returns (uint256)
  {
    return super.latestTimestamp();
  }

  /**
   * @notice get past rounds answers
   * @dev overridden funcion to add the checkAccess() modifier
   * @param _roundId the round number to retrieve the answer for
   *
   * @dev #[deprecated] Use getRoundData instead. This does not error if no
   * answer has been reached, it will simply return 0. Either wait to point to
   * an already answered Aggregator or use the recommended getRoundData
   * instead which includes better verification information.
   */
  function getAnswer(uint256 _roundId)
    public
    view
    override
    checkAccess()
    returns (int256)
  {
    return super.getAnswer(_roundId);
  }

  /**
   * @notice get timestamp when an answer was last updated
   * @dev overridden funcion to add the checkAccess() modifier
   * @param _roundId the round number to retrieve the updated timestamp for
   *
   * @dev #[deprecated] Use getRoundData instead. This does not error if no
   * answer has been reached, it will simply return 0. Either wait to point to
   * an already answered Aggregator or use the recommended getRoundData
   * instead which includes better verification information.
   */
  function getTimestamp(uint256 _roundId)
    public
    view
    override
    checkAccess()
    returns (uint256)
  {
    return super.getTimestamp(_roundId);
  }

}