ETH Price: $2,401.75 (-4.94%)

Transaction Decoder

Block:
11870289 at Feb-16-2021 09:30:55 PM +UTC
Transaction Fee:
0.367729973 ETH $883.20
Gas Used:
2,175,917 Gas / 169 Gwei

Account State Difference:

  Address   Before After State Difference Code
0x3E7d1eAB...65364e32D
(Chainlink: USDT/USD Price Feed)
0 Eth
Nonce: 0
0 Eth
Nonce: 1
From: 0 To: 693428931381062719079904143609047567298998383595737092671452355341022129882279364899126799278727149016175910111543336329768414027402382300992123576717836531740346733015020101727434875028795909770564984994211298681347778134497122053953269608777920190123027576699431121722505092670861235328995852297178860228852638972258031556338677892925923474977599928589355835354436200784860729873724553192783844403560880852560289176326571048642143361155521029909665524505015327069846286945224136524465499762351753351614995909903786055061077743827316278778854881801528182639799806744812044847922514140918792685942404083157759170815748242304783636240356218493038001699577749406882469808577376101751015502334152507860695547590719313228702038407610889213977643191904654586594482783662179315139878627173302954183985518642357022200669568340362042847710658584214484960831831653935449410079632904433901977169278203539206867424024470480129131488444271176421922728151272782125100195040646524872102795831384363290447972191107710077210979992267779099270605183226543752986968227678782866343106157962518698875950096636990040821694349105835386900354918749674432145580012027681797163825675453440048573577933039068305721455884837625207225294951045630393926866854801778689477920281002975701479671132990277823417589052522693488268727623193719346942623909117933168969845754307450708865223770764027361129771336943702362266967930165943864953299958365311223367223768553830954441379961425036844090082682439644340879444908341854675307618314856800323977511937780078474510197680064151432340245647303759672659734827960256117147613387910745226502507374139931512711703379398071444163496886564863168942164247243972311686666129567946946093346109611909505970225513726786432115898011717333473998191881300364220277290407436722764790007003828407671801096026351169943203496999879747200942171589977322301469545327275688669975001000147553017234529180979716530656726573633702578723220019574043796055014261864159568481356779656489963021984210601002251733249012071884615216467980816429112442682152668671707151346153245546247741209257079804135795947435034540374448545023713727816142575715194391599744381721438946519535027822689418113261469405450443245310406459408345588438332378968251677047408586438893579902402338149646765558468298819107442025213557146019855482169003806324460278524491075124883305410837677324649308189053879511899011450481521563446949719632501701272049447381214481668684884858183668702543845766162628630008996352581909091069888925206400907221942176833394800094353871989708480405892906785121321513208927017383496420219352762474609537235028609771721380154120334787677944781601788308873796631227609973173072746820972152437409831099463962147134280814498698255615608016805646870360358129551190025449339040123139462002160205051349729319099578237529104270656879531136848020555164428616056534287579871335498397162252309812524496226458580420103279719182178992488004235813530673748866510544188507893714566100377110459033968957023370933436511594773471482294401434477928581866016093733505049399177190700654893025753968839363277873647995530497122720882533037372694738315919595334171272823716559000144828029460471696138652878198146222094466919659406446361933684825867483550150022357945340398026683576940364378158115663711761440101273201155398053172508648460670581162096607452907134777465849004896092404325480619850169471236144426641640703792114054540688547449850481844203552889738040421234570555293114999568624969692528489226442157161750661734668759238543824356874647614975650355546541561029319295960120483301567145575695199160290391672843842708119424737038835543784089170240968422745362979688430382133177205681586239803270306926065916844165162381006679501428309891935160091985192761704962141615818679842980315381451628896926791492081998489198379708155674325454152601071313938034005726543790352788399169486323168896149862791083799817976344282844095650437977101820700087714673452320105794582295394059916721635454739538174318528999949333623126499845366234183770720249023495438444283981985323994518999040347965272114647417010826872988547184069298863305034772388820653191179846352202696191398167488428977430240611194452997444669632994706497319759860183869646267503375785872130867386706775356218566110312654802205858996371496192097995859998277288348819821123453175464312548891392190711956052080842874480280942528547007898436013175607943635381582124329595451266278155980848609319996976100866305130292993176162169833363492826715024234269981502981363692943557932641616670540523437018544829168414232596931908191334599351918509627866262600564967942744160719129754407374633327650096575757293324459560684550968581473055600516714975673276726469451093551805176680014830286615791492738741478110123424502613623590069437210559035259746705812751594097879330432903686426764189240373994574924845162189788811834850299590262409277521976667031941897275620796279368652421352407949399547608280288696264516252502837012900230441563217060022039045495244075456964758588005437447660858781696308350744975098022075732145539411981317743448425138574959553298773162820582992760011666564016052843575320193073740906014319512196217840090097735800149391162073327148450794292075987812611758090259288156746568498616805054705727022215384642642056091511265423339489235103093050340320914458853536085462791126725684368183733173083934203793811785394379381782254872281292984222458863730215797400172080874465349785622936394562663179677383914030188605449034343000004245834838298146768266453401975983575970251894534531306368811947105362895433601913833690308307638735500116638877697994138306364801065796676475183064353356945654626902894910221335444746389290143064680408733053630468891708893849089002252788805694289161593151999221995798620476617960125723122008968708934572224811044600200987605965361350251092261899225652555276065636090738208269073051554591775847941999796115765430875407861194930228271806748724746926086182594244223856894856263674282716320254072492695831588156423922181273100745717551418911643790271744013093620671523433851570067219008481845902866652463943274736755352391909367496082251998017995710801777641223881713971158517075397140789505580228793191904617575612791743222272890782441385654151516210802827789629465281251879479389043336220902925379190009460845881846111058064018419342186156339913686951597721941030210137300096973231459066808522745977116295370792352539776545244887638828568790680687122358729831981414952527303526969627781275517377841161269120666185480689817329688715314303516692676922376325822083742794419174490471062196700456667583577398266029856338816660845925491864623845521687653610149141921115721127309336005311101858913974833695957899230445081926429743948783810840747509535213799898971353982972057746599969926022920344738519329074855594562053910499308236255954720939726987110864889074598095289950905887492807684147206044673377682943880588723280964863319666818533890605170558857359440869966458603774243022759397029180211142582300942816841775230274706999224986279056721498751146714599132882898376222291031906097932754504224629377986925872715667280463383285435475846634473636660085341691793307991989084925243152201715898822742668939385469524086606309760170365602172646577651273758852615430195198050493954811332517044270648861753489506421827161363637830669831813542152857264351709428718705150687558061726238512415441317697373287835505872236063815747674734362785030625924877720664018613242725560056983281451799025143123509054495990534103787299806857895342369612239863981308267079229204037387361761190130124968676009860843388072728255496401860140969708450649848601584977779766591670928047500464781214577073702066263593008294135602049635081227746243019541281498172630964694843009352986994005662648270599163116332270488285439509090529157824905336943857307211913807237338391158529111819687190163381497123799132039069185773774387943442357463877185017484376254744210762456410503282063159796962295868823535904132822106513900608485713432076761679619538163897830806249317622220906205684080129589097842703366671930495310403062692887017738716199004552788359371555537602275142346237391086906161959662248016005481613718108192263932332460638449803287237444980062898100796881276779939759446479652615595492302813825481898834579979588048341067491505554429399852691366253604522464734108315388025619443484229279944845221678413676534187370375364275653451268601116961308815975925489039468392684195940113581338651429592667044379090398814991138222094211873047109065492972438248360342764213044432092609308298032600298794260946210624048443941984265793443434436198875334252161545345275591302786897082884042977251998047267460109206191849543645590811737228855080665735720946197716047156596724996937880082499293648164507436747232889492693835607406806167085950121910685123730138765296212251927878545515706231087931929872775591748561082388654505852393942786590002998130644687064150311743917608906512164111711861947530268049452849745540634949638761777618564335607272094483416487047475623296794887390192248691839635636116029966921633046852157388353148670577425765658415928997048799369553332321767964246827847584264115432124261556201632750384559946562434767092894486791995437452540119179360840337094770952511282477208416864367092457097683399156226806138456119735580816396427420495890253036650510258688043061203577933975435383463935451227382707014264799234750352206690275910498249366594552853754070698879504235013958293555769559785331349988728306512282334998713447935572729788418975506496905430535442617358156623553847760362647191925071938551171101213219778384864344593467006860715740393103345829515061639488519579757336277596217851809713863946948909080189832788140058684179114011453716163639263847368330295693812014839841421734170436562137614199562483141998223691937370752350541456440243506563346989649245828018556613724562826259600704815192100689077297991509448164107143965396998159772304459464199484458590108937922121713815891822851087836295725630439112885295515682696319176012129276000326818814201586695287528709823665550721203890470100587281598908125963735191039540775526742024177123954903388342906611079954464139987535285368127943807828930240309660708944017377566489238698133365168962780567468959120094900680198408259572353662603813116844136415949946233316801868926630677422933409681478721380891744977008091357001515656574182401661349666415045793753294783193367926629605441963730552901786325521238044660064343513590967055311345801971878940255139018432826792778608669526090416502709025727727330664693974832686527308679313573326491238207426166346437182806587350110741373587082605736988146852603079676762137846361109201226493361646171554907668651278001596454597695021394175110134332178385628238081389105382492195924215239863544941430143162742218970389264996019125929477380738832995934412908989590956523086300226332533315145001026691417749389597323664335821801989266968684772631083578086605768858947770167780589501307069112526406394626591821566657278910206564466595701476530421518600884933237121367944139631980368814195971263074861493811472880580013954863078330329783836586632434896668757722271972903100950230992009788036025385804785203157547575103873480994530362937203377213778436495021726106195474708467674934980555446234859034348118726463756331363841792131097185180215291505025596555015846105285134026455667801492462639189007257932452997934047826568019597180858687065600854572838042833381706396252348202639408867941609425008818122357186179326289226613366009008202462159560593159663707174759306028454102486034979386577274488226442632947807950748489723234135674238512450329018871641153870803055072326535667480556830419753991129727564017448735749256734670922904889911228982615329202595359304618908344604648589830921272801247089919081532924990196537821067919284774791657666211115720342289237620189137398249599068122655048610622800932348713826935524184699506679009958684808678602811259477120412615390604423944634414426672619370272884686568346826297959541701419584972253697262409947641825254364180003704586582367441606546588021710699412039016176554560103548800908295112489474594856377121100438415954127224975665701859180254353410434942171432675938233310935555543060944507450187369221514302572735770416463526241391114292732424914838641803135126584639937699637477082938940183425262157629197291631805393346562302723720913775698062107951359914682063330388395412016831984129256495163926982118232770594458868602268664829089110561131938227062555229656473124893348031417854225642056470586353397133278095936772384185153555728926588048445698554517507657509970645067784608775803251329875721633695772954139742395165804785166011679202408559038486864409991496123801313261099276782917893045320474188459653726207778942273971641479301976431571281749773679608231321195459040153628811410399939040257020259294234780862385999927865107417438766999219811350485007118138793766765697990071098077510415955991798661838674194973835742695844378357426037731003500784313539921372274482365153756449129715871221266555986554139799796717783854538746143239613871745576092495664313720525853551410293818608572891930419700451129914301189383720654742468637278150835552970600549689314538565656073915395701432698996956345613994881151952659301610450056589912287437631819988970581179864611262823751060539416373361903238934400985968802229810631554435783327100041099307511017623150914496630477017099996984374434416338089481527661705508402203361323255642171306540790850801764751617204002381552273985907912737015266800684587886997619134537695054886228985290769585196365078460262694730852071308782938321208046945370393485865132199609350418728530378449055888154901051273498850524644143533488602208874466563958425006214690797223842988497696121719477280140184526376303321531283136035222172433104477105321949194330525662781280924093828088007123173821849556733381403843878238735121107620447512230760815234354519795219638631480071831018142572073254275714159467938885725389340989400704869890772613008308147283709947324904698236287235684185571129938070489250826830667773404237668189334851045305999398521542349822448362340669589927265487985748672023076130949159205364577258293124275957810186340338880821869380379490742664199604970050032793993511467174260888843423816353180620436215564760931491519901091660717480848171771024090423393269210860946469894397921573488992746934773259008624680337901221717196918445045192903078366819097651136614905910065511819800975303634319625899515237379435775460507866217817502271417681436874325808126121345497451604970727238944179853973938966420385379135117880111496726324849075490096908219024789837439762041715988114556812751100147450749159153141668670234170066183178858314475816049466975614604428591669943945452118691237630522932181616195317992428597607992797046514186211936437196123654092726683562659371201435009951644608477454796334620817526787384610643678588115193169931849300876339851918477897773110139410077068501368448833881452646222367525910500875236600061789809405339654981925614911591850463666123932681437312001890163434639834204479897767590114518189546260502537548843359216178205495801057815541777062761290225510562689250378133668589325748553240147381694206564248749093066442811843219148861858567525608324551385153256105712017212632690270746298022606505977510550670910972134034288176880226963677945719875236924467496455861554191471075614355687454321032622489064240325400368376638769028261589865321721031937806561360452651289120891796468570632572331480381243655271098653389162307266703571791413816700041631776971818970736386774288611656006403855377556528304563402369749326488834627687762955479458686699765282139467432246562415947651127508510095415069310149883782811094034074220428476427994937970315581048093449788264914055457821280631721236342675913502291556748488577932350749303353211319384878756490553765828128207065683087575511102060878959982139600875831903680776171329757113172175488969569641524556737917930978516597936479531115071004686014219178555081802773754539655565204052277257718425356445966710407770876824592468795045679844610487763291812994903477077099485064434096421207032780498224221878935552709803075512913354915867631803466209152686411668206614260848378975638705505661027493955237192922322636185489488366249569049825446975375841100938567543621420374442695304789076922072788620847079758786814380662960017189482478048434405395810749544982853773870380645826007441568689796280265263995172966856547883171535191500327967632916139195342858974435443729548169297811674869088457691448347377480834728764857782824932500370939308321801076580922068916970755253245484078530433440258378977766345985154922598436825321265937934322150995706439774122702322986318875518739336882621791056388993696937513435576979641039311545563173365350783332040044757023810230312031622816257719839458514464588242426859164672816741313390044558965108609026035436290420286066648205318642362976427484729227922010131647078365424447003285444060258620902494739565239020090816276726046876783118158514582788491500782760384875427101460397794589328640055755091910162201740963497336704983457470965755990739297088173291728599703254513343948266242585934948797107698764135102034997798092288289033830017309461977901223168608648066913790296405584820655155337964119851218273882076138949347704814797156269487145240040360372894538587116336064630070581695550956717117008549837520101870608965415153314577035264929891411044558556380021315646702824779357634651718818410879576577226230820606884883458348317287932414299654177523387058609076708380498559575183871542811544282270119224661078065624864564423552930539469643944559323993457987049650783190815574154198127952568753465831365702058448959255026282029927327808286493923295145748272799444612713760507730038834656873185097736264831699477789530787757117253004164416554352196223549945288027840326993696716781041341887448106354335752076806038294524889592911080526301500378853687754392946617101893214795031132362955105804047827231360498753654212739980438368736715627433279934077271397877291350370372641649352061719192391284449205732485968026832239236490642461183320439459068842520450057291669597459261080742986666798389174899979497779866926634692061286143736642666406588539105800680662636472970354795154310069872679215732196485346888830241138085875556422602867731654060613936881072108692033884479432298597546667372571429184883610473091822211147358863235397105006632434211094909546675495727035508491492559705103448884413076720201030087200043566569337745594598958009758142493967005544376728297832101584162845315200150694376827175048172690928301126592335739535279619764380592217320889190819220277258260023101328534850536932665111887751272229113349994286070370754179468783990699388513110544879953141118644880630915674551859061568833140988386896747415987425081317801668339256630370070518148828833029779493246108136539060183045496284815703709695132883488206476817652433567259216884409989313000420324189407178689016472952762661450968445415181259118166905132738967046257392359171897234368079125604115513656128089488684044879874174318329579522507366746790579156087234123932075348631311919148075953420712855180809729935919191262378176221964408188657404131427143078515636540814619694147328173221325089802707623613024613565326886062867604238062446146649660663296752496698343294425078241903130651989269366945602340853252197214480677987745845624209747705557399662298920337442068600752933419895225025672936558121201131120782067954562316271854177369283775145030575741471037304453276006664381183892085130632410339573435135233995171262157654045037525839093763664775356959080286414104060489969384236036849003305047389365870746689633794714479771642550566224051684496750354844240205408940274082035804852116615921259683176865910066180379753746201930249164569507955403781365316402326807567239319046240242684999219364692490304915100727992805259281174583371336399682151269745950094785568603032173753233599651351928542980413850965692945348661521772701868769400227278865430342986732642968610643664818464381312665396170206629145730052154014067190594742752193014915541931902096566506178204335615973169486944934212830862965527717194691831499358266688381596107157880348734904375671281188419684743598310660378420677202887139828350387043193510827778353410929975346639763389994875680583075221928834010281924458228938326168190174063767183423117465255807595029261805343516731120615290447949030433038536243571787023589435554050271149035118282981641469018354459966234887352994452476306732349862180739894835829898938085235117389007119691376088336061249502273961917758033197817341426188911502736280912438976105029922112685868797499147319462386304068092331362038757674292644917181427657560436759314657762414913674158170222542122756083871405678333323676118481131493683212051853030847141221145904731982205246946738914015792719650278032033068559773458609462773941448915203250422057595256165126609429090609204691850089599130244461434152488546051044663997301098247693688699667683374807944705701006877550751151452276238520108130254251235923256701906784779349860995904849767820171495823948652038962962164636810033318853232161038034520697337707311044807752351835467842482361834728844238848996282048967386005132335563063547870224073268459918375253923915304916183120786607301157367855415389563170095316749233740067612820495841654028274019048520030206470786465965987903739973002006111317454154267267596520981876047187365405905378135839241995686984900028681742836056073456741808042756546989791617848440683270259724241943878943076525250826869419732213212091200458043249377432566328080694112883047347159334941264065735678307695903921648641196080664409187572604679409712180143910729139004668337659182858705665676315674207706516244593708024189207255683536590760270886187979705098775963729076782612081114944071358661059368997420508593036584461446497023081521572021025275416446234044862017744494885657102264235484953794626784988967891827121200955597577331629005001132266872973960614595412235584479607666660525582978129631286106797872926722682377762155114369913422263258177013906869527332471509770284348817583611788483895454264727887210992665823928450373302304769280310573735221392367534031185826080860376040741240625238135552385188743793513517161166341703817325206693105101408981675393682733624802927718890795113497089726075528810416445949116871765578877601419478465799247279243097003768183400172569083484963574940556591952774727134959507415491671545069929175057703458042970422745689701435041414067943857659436665502249778181724135861490210703670273079921850981126062190674475189576349844253294239595850275785577051527569597116077640034350459889584031788957961219218899039970202360664533592103554279569657110497918658197983130028512152214638961019140680980274920872445394115365259435283468754505377756615815758095666444931687525734136475878023564262907002925195871566444501464772348232807218157621248266621258674405854509900809154283523282039219796077076067020767187600418815180019604577312279233023959308226576703525517886384528957767107141903670756146209768448208477507339420070306349972220212912088576805769624546479592335655436339
0x536Ee634...66E9B8eC7
9.779934971970548526 Eth
Nonce: 710
9.412204998970548526 Eth
Nonce: 711
0.367729973
(Ethermine)
1,436.70317119779573647 Eth1,437.07090117079573647 Eth0.367729973

Execution Trace

EACAggregatorProxy.60806040( )
pragma solidity 0.6.6;


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

  address 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");
    _;
  }

}

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
{
}

/**
 * @title A trusted proxy for updating where current answers are read from
 * @notice This contract provides a consistent address for the
 * CurrentAnwerInterface but delegates where it reads from to the owner, who is
 * trusted to update it.
 */
contract AggregatorProxy is AggregatorV2V3Interface, Owned {

  struct Phase {
    uint16 id;
    AggregatorV2V3Interface aggregator;
  }
  Phase private currentPhase;
  AggregatorV2V3Interface public proposedAggregator;
  mapping(uint16 => AggregatorV2V3Interface) public phaseAggregators;

  uint256 constant private PHASE_OFFSET = 64;
  uint256 constant private PHASE_SIZE = 16;
  uint256 constant private MAX_ID = 2**(PHASE_OFFSET+PHASE_SIZE) - 1;

  constructor(address _aggregator) public Owned() {
    setAggregator(_aggregator);
  }

  /**
   * @notice Reads the current answer from aggregator delegated to.
   *
   * @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 answer)
  {
    return currentPhase.aggregator.latestAnswer();
  }

  /**
   * @notice Reads the last updated height from aggregator delegated to.
   *
   * @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 updatedAt)
  {
    return currentPhase.aggregator.latestTimestamp();
  }

  /**
   * @notice get past rounds answers
   * @param _roundId the answer 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 answer)
  {
    if (_roundId > MAX_ID) return 0;

    (uint16 phaseId, uint64 aggregatorRoundId) = parseIds(_roundId);
    AggregatorV2V3Interface aggregator = phaseAggregators[phaseId];
    if (address(aggregator) == address(0)) return 0;

    return aggregator.getAnswer(aggregatorRoundId);
  }

  /**
   * @notice get block timestamp when an answer was last updated
   * @param _roundId the answer 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 updatedAt)
  {
    if (_roundId > MAX_ID) return 0;

    (uint16 phaseId, uint64 aggregatorRoundId) = parseIds(_roundId);
    AggregatorV2V3Interface aggregator = phaseAggregators[phaseId];
    if (address(aggregator) == address(0)) return 0;

    return aggregator.getTimestamp(aggregatorRoundId);
  }

  /**
   * @notice get the latest completed round where the answer was updated. This
   * ID includes the proxy's phase, to make sure round IDs increase even when
   * switching to a newly deployed aggregator.
   *
   * @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 roundId)
  {
    Phase memory phase = currentPhase; // cache storage reads
    return addPhase(phase.id, uint64(phase.aggregator.latestRound()));
  }

  /**
   * @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.
   * Note that different underlying implementations of AggregatorV3Interface
   * have slightly different semantics for some of the return values. Consumers
   * should determine what implementations they expect to receive
   * data from and validate that they can properly handle return data from all
   * of them.
   * @param _roundId the requested round ID as presented through the proxy, this
   * is made up of the aggregator's round ID with the phase ID encoded in the
   * two highest order bytes
   * @return roundId is the round ID from the aggregator for which the data was
   * retrieved combined with an phase to ensure that round IDs get larger as
   * time moves forward.
   * @return answer is the answer for the given round
   * @return startedAt is the timestamp when the round was started.
   * (Only some AggregatorV3Interface implementations return meaningful values)
   * @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.
   * (Only some AggregatorV3Interface implementations return meaningful values)
   * @dev Note that 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
    )
  {
    (uint16 phaseId, uint64 aggregatorRoundId) = parseIds(_roundId);

    (
      uint80 roundId,
      int256 answer,
      uint256 startedAt,
      uint256 updatedAt,
      uint80 ansIn
    ) = phaseAggregators[phaseId].getRoundData(aggregatorRoundId);

    return addPhaseIds(roundId, answer, startedAt, updatedAt, ansIn, phaseId);
  }

  /**
   * @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.
   * Note that different underlying implementations of AggregatorV3Interface
   * have slightly different semantics for some of the return values. Consumers
   * should determine what implementations they expect to receive
   * data from and validate that they can properly handle return data from all
   * of them.
   * @return roundId is the round ID from the aggregator for which the data was
   * retrieved combined with an phase to ensure that round IDs get larger as
   * time moves forward.
   * @return answer is the answer for the given round
   * @return startedAt is the timestamp when the round was started.
   * (Only some AggregatorV3Interface implementations return meaningful values)
   * @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.
   * (Only some AggregatorV3Interface implementations return meaningful values)
   * @dev Note that answer and updatedAt may change between queries.
   */
  function latestRoundData()
    public
    view
    virtual
    override
    returns (
      uint80 roundId,
      int256 answer,
      uint256 startedAt,
      uint256 updatedAt,
      uint80 answeredInRound
    )
  {
    Phase memory current = currentPhase; // cache storage reads

    (
      uint80 roundId,
      int256 answer,
      uint256 startedAt,
      uint256 updatedAt,
      uint80 ansIn
    ) = current.aggregator.latestRoundData();

    return addPhaseIds(roundId, answer, startedAt, updatedAt, ansIn, current.id);
  }

  /**
   * @notice Used if an aggregator contract has been proposed.
   * @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.
   * (Only some AggregatorV3Interface implementations return meaningful values)
   * @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.
  */
  function proposedGetRoundData(uint80 _roundId)
    public
    view
    virtual
    hasProposal()
    returns (
      uint80 roundId,
      int256 answer,
      uint256 startedAt,
      uint256 updatedAt,
      uint80 answeredInRound
    )
  {
    return proposedAggregator.getRoundData(_roundId);
  }

  /**
   * @notice Used if an aggregator contract has been proposed.
   * @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.
   * (Only some AggregatorV3Interface implementations return meaningful values)
   * @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.
  */
  function proposedLatestRoundData()
    public
    view
    virtual
    hasProposal()
    returns (
      uint80 roundId,
      int256 answer,
      uint256 startedAt,
      uint256 updatedAt,
      uint80 answeredInRound
    )
  {
    return proposedAggregator.latestRoundData();
  }

  /**
   * @notice returns the current phase's aggregator address.
   */
  function aggregator()
    external
    view
    returns (address)
  {
    return address(currentPhase.aggregator);
  }

  /**
   * @notice returns the current phase's ID.
   */
  function phaseId()
    external
    view
    returns (uint16)
  {
    return currentPhase.id;
  }

  /**
   * @notice represents the number of decimals the aggregator responses represent.
   */
  function decimals()
    external
    view
    override
    returns (uint8)
  {
    return currentPhase.aggregator.decimals();
  }

  /**
   * @notice the version number representing the type of aggregator the proxy
   * points to.
   */
  function version()
    external
    view
    override
    returns (uint256)
  {
    return currentPhase.aggregator.version();
  }

  /**
   * @notice returns the description of the aggregator the proxy points to.
   */
  function description()
    external
    view
    override
    returns (string memory)
  {
    return currentPhase.aggregator.description();
  }

  /**
   * @notice Allows the owner to propose a new address for the aggregator
   * @param _aggregator The new address for the aggregator contract
   */
  function proposeAggregator(address _aggregator)
    external
    onlyOwner()
  {
    proposedAggregator = AggregatorV2V3Interface(_aggregator);
  }

  /**
   * @notice Allows the owner to confirm and change the address
   * to the proposed aggregator
   * @dev Reverts if the given address doesn't match what was previously
   * proposed
   * @param _aggregator The new address for the aggregator contract
   */
  function confirmAggregator(address _aggregator)
    external
    onlyOwner()
  {
    require(_aggregator == address(proposedAggregator), "Invalid proposed aggregator");
    delete proposedAggregator;
    setAggregator(_aggregator);
  }


  /*
   * Internal
   */

  function setAggregator(address _aggregator)
    internal
  {
    uint16 id = currentPhase.id + 1;
    currentPhase = Phase(id, AggregatorV2V3Interface(_aggregator));
    phaseAggregators[id] = AggregatorV2V3Interface(_aggregator);
  }

  function addPhase(
    uint16 _phase,
    uint64 _originalId
  )
    internal
    view
    returns (uint80)
  {
    return uint80(uint256(_phase) << PHASE_OFFSET | _originalId);
  }

  function parseIds(
    uint256 _roundId
  )
    internal
    view
    returns (uint16, uint64)
  {
    uint16 phaseId = uint16(_roundId >> PHASE_OFFSET);
    uint64 aggregatorRoundId = uint64(_roundId);

    return (phaseId, aggregatorRoundId);
  }

  function addPhaseIds(
      uint80 roundId,
      int256 answer,
      uint256 startedAt,
      uint256 updatedAt,
      uint80 answeredInRound,
      uint16 phaseId
  )
    internal
    view
    returns (uint80, int256, uint256, uint256, uint80)
  {
    return (
      addPhase(phaseId, uint64(roundId)),
      answer,
      startedAt,
      updatedAt,
      addPhase(phaseId, uint64(answeredInRound))
    );
  }

  /*
   * Modifiers
   */

  modifier hasProposal() {
    require(address(proposedAggregator) != address(0), "No proposed aggregator present");
    _;
  }

}

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

/**
 * @title External Access Controlled Aggregator Proxy
 * @notice A trusted proxy for updating where current answers are read from
 * @notice This contract provides a consistent address for the
 * Aggregator and AggregatorV3Interface but delegates where it reads from to the owner, who is
 * trusted to update it.
 * @notice Only access enabled addresses are allowed to access getters for
 * aggregated answers and round information.
 */
contract EACAggregatorProxy is AggregatorProxy {

  AccessControllerInterface public accessController;

  constructor(
    address _aggregator,
    address _accessController
  )
    public
    AggregatorProxy(_aggregator)
  {
    setController(_accessController);
  }

  /**
   * @notice Allows the owner to update the accessController contract address.
   * @param _accessController The new address for the accessController contract
   */
  function setController(address _accessController)
    public
    onlyOwner()
  {
    accessController = AccessControllerInterface(_accessController);
  }

  /**
   * @notice Reads the current answer from aggregator delegated to.
   * @dev overridden function 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 latest completed round where the answer was updated. This
   * ID includes the proxy's phase, to make sure round IDs increase even when
   * switching to a newly deployed aggregator.
   *
   * @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
   * @param _roundId the answer number to retrieve the answer for
   * @dev overridden function to add the checkAccess() modifier
   *
   * @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 block timestamp when an answer was last updated
   * @param _roundId the answer number to retrieve the updated timestamp for
   * @dev overridden function to add the checkAccess() modifier
   *
   * @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);
  }

  /**
   * @notice get the latest completed round where the answer was updated
   * @dev overridden function 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 data about a round. Consumers are encouraged to check
   * that they're receiving fresh data by inspecting the updatedAt and
   * answeredInRound return values.
   * Note that different underlying implementations of AggregatorV3Interface
   * have slightly different semantics for some of the return values. Consumers
   * should determine what implementations they expect to receive
   * data from and validate that they can properly handle return data from all
   * of them.
   * @param _roundId the round ID to retrieve the round data for
   * @return roundId is the round ID from the aggregator for which the data was
   * retrieved combined with a phase to ensure that round IDs get larger as
   * time moves forward.
   * @return answer is the answer for the given round
   * @return startedAt is the timestamp when the round was started.
   * (Only some AggregatorV3Interface implementations return meaningful values)
   * @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.
   * (Only some AggregatorV3Interface implementations return meaningful values)
   * @dev Note that answer and updatedAt may change between queries.
   */
  function getRoundData(uint80 _roundId)
    public
    view
    checkAccess()
    override
    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.
   * Note that different underlying implementations of AggregatorV3Interface
   * have slightly different semantics for some of the return values. Consumers
   * should determine what implementations they expect to receive
   * data from and validate that they can properly handle return data from all
   * of them.
   * @return roundId is the round ID from the aggregator for which the data was
   * retrieved combined with a phase to ensure that round IDs get larger as
   * time moves forward.
   * @return answer is the answer for the given round
   * @return startedAt is the timestamp when the round was started.
   * (Only some AggregatorV3Interface implementations return meaningful values)
   * @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.
   * (Only some AggregatorV3Interface implementations return meaningful values)
   * @dev Note that answer and updatedAt may change between queries.
   */
  function latestRoundData()
    public
    view
    checkAccess()
    override
    returns (
      uint80 roundId,
      int256 answer,
      uint256 startedAt,
      uint256 updatedAt,
      uint80 answeredInRound
    )
  {
    return super.latestRoundData();
  }

  /**
   * @notice Used if an aggregator contract has been proposed.
   * @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.
   * (Only some AggregatorV3Interface implementations return meaningful values)
   * @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.
  */
  function proposedGetRoundData(uint80 _roundId)
    public
    view
    checkAccess()
    hasProposal()
    override
    returns (
      uint80 roundId,
      int256 answer,
      uint256 startedAt,
      uint256 updatedAt,
      uint80 answeredInRound
    )
  {
    return super.proposedGetRoundData(_roundId);
  }

  /**
   * @notice Used if an aggregator contract has been proposed.
   * @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.
   * (Only some AggregatorV3Interface implementations return meaningful values)
   * @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.
  */
  function proposedLatestRoundData()
    public
    view
    checkAccess()
    hasProposal()
    override
    returns (
      uint80 roundId,
      int256 answer,
      uint256 startedAt,
      uint256 updatedAt,
      uint80 answeredInRound
    )
  {
    return super.proposedLatestRoundData();
  }

  /**
   * @dev reverts if the caller does not have access by the accessController
   * contract or is the contract itself.
   */
  modifier checkAccess() {
    AccessControllerInterface ac = accessController;
    require(address(ac) == address(0) || ac.hasAccess(msg.sender, msg.data), "No access");
    _;
  }
}