ETH Price: $2,420.64 (-2.42%)

Transaction Decoder

Block:
21124426 at Nov-05-2024 10:27:35 PM +UTC
Transaction Fee:
0.009814218897264192 ETH $23.76
Gas Used:
1,235,079 Gas / 7.946227648 Gwei

Emitted Events:

191 VotingV2.VoterSlashed( voter=0x4c0deE7F...b5a00fF1d, requestIndex=425, slashedTokens=-7418736980156570322 )
192 VotingV2.VoterSlashed( voter=0x4c0deE7F...b5a00fF1d, requestIndex=426, slashedTokens=-7418736980156570322 )
193 VotingV2.VoterSlashed( voter=0x4c0deE7F...b5a00fF1d, requestIndex=427, slashedTokens=-7418736980156570322 )
194 VotingV2.VoterSlashed( voter=0x4c0deE7F...b5a00fF1d, requestIndex=428, slashedTokens=-7418736980156570322 )
195 VotingV2.VoterSlashApplied( voter=0x4c0deE7F...b5a00fF1d, slashedTokens=-29674947920626281288, postStake=7389062032235944039853 )
196 VotingV2.UpdatedReward( voter=0x4c0deE7F...b5a00fF1d, newReward=483357149044503275, lastUpdateTime=1730845655 )
197 VotingV2.VoteCommitted( voter=0x4c0deE7F...b5a00fF1d, caller=[Sender] 0x4cd6ac17782d95dc7a8ee2106ff8de4a52984b01, roundId=10016, identifier=5945535F4F525F4E4F5F51554552590000000000000000000000000000000000, time=1730747077, ancillaryData=0x713A207469746C653A2057696C6C20486172726973206C65616420696E2052435020627920302D302E34206F6E204E6F7620343F2C206465736372697074696F6E3A20546869732069732061206D61726B6574206F6E207468652052435020506F6C6C696E672041766572616765206D617267696E206265747765656E20446F6E616C64205472756D7020616E64204B616D616C6120486172726973206173206F66204E6F76656D62657220342C20323032342C2031323A303020504D2045542E2054686520737072656164207265666572656E63656420696E20746865206669727374207461626C65206F6E207468652022323032342047656E6572616C20456C656374696F6E3A205472756D702076732E204861727269732220706167652061742068747470733A2F2F7777772E7265616C636C656172706F6C6C696E672E636F6D2F706F6C6C732F707265736964656E742F67656E6572616C2F323032342F7472756D702D76732D6861727269732077696C6C206265207573656420746F207265736F6C76652074686973206D61726B65742E0A0A54686973206D61726B65742077696C6C207265736F6C766520746F202759657327206966206265747765656E2048617272697320302E302028696E636C75736976652920616E6420486172726973202B302E342028696E636C7573697665292070657263656E7461676520706F696E74732E204F74686572776973652C2074686973206D61726B65742077696C6C207265736F6C766520746F20274E6F272E0A0A5468652052435020506F6C6C696E6720417665726167652077696C6C20626520636865636B6564206F6E204E6F76656D62657220342C2031323A303020504D2045542E0A0A506C65617365206E6F74652C2074686973206D61726B657420726566657273207370656369666963616C6C7920746F20746865206D617267696E20666F722052435020706F6C6C696E6720617665726167652061732070726573656E74656420696E207468652061666F72656D656E74696F6E656420636861727420696E2074686520636F6C756D6E207469746C65642027537072656164272E205468697320696E636C7564657320616E792061646A7573746D656E7473206F72206D6574686F646F6C6F6779206368616E676573206D6164652062792052435020696E2074686569722063616C63756C6174696F6E206F662074686520706F6C6C696E672061766572616765206F722074686520646174652072616E676520757365642E0A0A4966207468652052435020506F6C6C696E672041766572616765206D617267696E2064617461206265747765656E204B616D616C612048617272697320616E6420446F6E616C64205472756D70206973206E6F7420617661696C61626C65206279204E6F76656D62657220382C20323032342C2031313A353920504D2045542C20616E6F74686572206372656469626C6520736F75726365206F6620706F6C6C696E672064617461206173206F66204E6F76656D62657220342C2031323A303020504D2045542077696C6C206265207573656420666F72206D61726B6574207265736F6C7574696F6E2E2C207265735F646174613A2070313A20302C2070323A20312C2070333A20302E352E20576865726520703120636F72726573706F6E647320746F204E6F2C20703220746F205965732C20703320746F20756E6B6E6F776E2E20546869732072657175657374204D555354206F6E6C79207265736F6C766520746F207031206F722070322E202055706461746573206D61646520627920746865207175657374696F6E2063726561746F7220766961207468652062756C6C6574696E20626F617264206174203078324635653336383463623146333138656335316230304564626133386437394163326330614139642073686F756C6420626520636F6E736964657265642E2C696E697469616C697A65723A393134333063616432643339373537363634393937313766613064363661373864383134653563352C6F6F5265717565737465723A326635653336383463623166333138656335316230306564626133386437396163326330616139642C6368696C645265717565737465723A656533616665333437643563373433313730343165323631386334393533346461663838376332342C6368696C64436861696E49643A313337 )
198 VotingV2.EncryptedVote( caller=[Sender] 0x4cd6ac17782d95dc7a8ee2106ff8de4a52984b01, roundId=10016, identifier=5945535F4F525F4E4F5F51554552590000000000000000000000000000000000, time=1730747077, ancillaryData=0x713A207469746C653A2057696C6C20486172726973206C65616420696E2052435020627920302D302E34206F6E204E6F7620343F2C206465736372697074696F6E3A20546869732069732061206D61726B6574206F6E207468652052435020506F6C6C696E672041766572616765206D617267696E206265747765656E20446F6E616C64205472756D7020616E64204B616D616C6120486172726973206173206F66204E6F76656D62657220342C20323032342C2031323A303020504D2045542E2054686520737072656164207265666572656E63656420696E20746865206669727374207461626C65206F6E207468652022323032342047656E6572616C20456C656374696F6E3A205472756D702076732E204861727269732220706167652061742068747470733A2F2F7777772E7265616C636C656172706F6C6C696E672E636F6D2F706F6C6C732F707265736964656E742F67656E6572616C2F323032342F7472756D702D76732D6861727269732077696C6C206265207573656420746F207265736F6C76652074686973206D61726B65742E0A0A54686973206D61726B65742077696C6C207265736F6C766520746F202759657327206966206265747765656E2048617272697320302E302028696E636C75736976652920616E6420486172726973202B302E342028696E636C7573697665292070657263656E7461676520706F696E74732E204F74686572776973652C2074686973206D61726B65742077696C6C207265736F6C766520746F20274E6F272E0A0A5468652052435020506F6C6C696E6720417665726167652077696C6C20626520636865636B6564206F6E204E6F76656D62657220342C2031323A303020504D2045542E0A0A506C65617365206E6F74652C2074686973206D61726B657420726566657273207370656369666963616C6C7920746F20746865206D617267696E20666F722052435020706F6C6C696E6720617665726167652061732070726573656E74656420696E207468652061666F72656D656E74696F6E656420636861727420696E2074686520636F6C756D6E207469746C65642027537072656164272E205468697320696E636C7564657320616E792061646A7573746D656E7473206F72206D6574686F646F6C6F6779206368616E676573206D6164652062792052435020696E2074686569722063616C63756C6174696F6E206F662074686520706F6C6C696E672061766572616765206F722074686520646174652072616E676520757365642E0A0A4966207468652052435020506F6C6C696E672041766572616765206D617267696E2064617461206265747765656E204B616D616C612048617272697320616E6420446F6E616C64205472756D70206973206E6F7420617661696C61626C65206279204E6F76656D62657220382C20323032342C2031313A353920504D2045542C20616E6F74686572206372656469626C6520736F75726365206F6620706F6C6C696E672064617461206173206F66204E6F76656D62657220342C2031323A303020504D2045542077696C6C206265207573656420666F72206D61726B6574207265736F6C7574696F6E2E2C207265735F646174613A2070313A20302C2070323A20312C2070333A20302E352E20576865726520703120636F72726573706F6E647320746F204E6F2C20703220746F205965732C20703320746F20756E6B6E6F776E2E20546869732072657175657374204D555354206F6E6C79207265736F6C766520746F207031206F722070322E202055706461746573206D61646520627920746865207175657374696F6E2063726561746F7220766961207468652062756C6C6574696E20626F617264206174203078324635653336383463623146333138656335316230304564626133386437394163326330614139642073686F756C6420626520636F6E736964657265642E2C696E697469616C697A65723A393134333063616432643339373537363634393937313766613064363661373864383134653563352C6F6F5265717565737465723A326635653336383463623166333138656335316230306564626133386437396163326330616139642C6368696C645265717565737465723A656533616665333437643563373433313730343165323631386334393533346461663838376332342C6368696C64436861696E49643A313337, encryptedVote=0x72EA5A468C8ECC97893AA74B7B21FC9B02C3C8FFA3B9995F691801A6617E3AFFE3739E553B8DC016B055F5517329A33E4478D450E95D8B236C08A97F14C62705DA0A060ECF2852A29D8F9E6DE0921F1FC864AD6D698C46E56B6A52E43D3BDFAE007F2064070A888AC694E8536F00F1425902288BA5CDBD9E62DBF8E8DBB82B45C75F171C5B75134FD3B1D166BB9C4B00CE2FA1A0C6F62910ABD036DEE731FF9F1C4593AF2D5AA0B4DCDD4D7C1542D564BF047D944540C6D75058FD9E129FAF78B5 )
199 VotingV2.UpdatedReward( voter=0x4c0deE7F...b5a00fF1d, newReward=483357149044503275, lastUpdateTime=1730845655 )
200 VotingV2.VoteCommitted( voter=0x4c0deE7F...b5a00fF1d, caller=[Sender] 0x4cd6ac17782d95dc7a8ee2106ff8de4a52984b01, roundId=10016, identifier=5945535F4F525F4E4F5F51554552590000000000000000000000000000000000, time=1730698959, ancillaryData=0x713A207469746C653A2057696C6C205472756D70207361792022736B696269646922206265666F72652074686520656C656374696F6E3F2C206465736372697074696F6E3A2054686973206D61726B65742077696C6C207265736F6C766520746F20E2809C596573E2809D20696620446F6E616C64205472756D70207075626C69636C79206D656E74696F6E732074686520776F72642022736B696269646922206265747765656E2053657074656D62657220313720616E64204E6F76656D62657220342C20323032342C2031313A353920504D2045542E204F74686572776973652C2074686973206D61726B65742077696C6C207265736F6C766520746F20E2809C4E6FE2809D2E0A0A4120E280986D656E74696F6EE2809920696E636C756465732074686520666F6C6C6F77696E673A0A0A2D412076657262616C207573616765206F662074686520776F72642873292022736B6962696469222E0A2D416E79207772697474656E207573616765206F662074686520776F72642873292022736B696269646922207075626C6973686564207468726F756768205472756D70277320736F6369616C206D65646961206F72206F74686572206F6666696369616C20636F6D6D756E69636174696F6E206368616E6E656C73207265676172646C657373206F66206361706974616C697A6174696F6E2E0A0A416E79207573616765206F662074686520776F7264207265676172646C657373206F6620636F6E746578742077696C6C20636F756E7420746F7761726420746865207265736F6C7574696F6E206F662074686973206D61726B65742E0A0A506C7572616C697A6174696F6E2F706F7373657373697665206F662074686520776F72642077696C6C20636F756E7420746F7761726420746865207265736F6C7574696F6E206F662074686973206D61726B65742C20686F7765766572206F7468657220666F726D732077696C6C204E4F5420636F756E742E0A0A546865207265736F6C7574696F6E20736F7572636520666F722074686973206D61726B65742077696C6C20626520666F6F74616765206F6620446F6E616C64205472756D702074616B656E2077697468696E20746865206D656E74696F6E65642074696D656672616D652C2061732077656C6C206173206F6666696369616C20636F6D6D756E69636174696F6E732066726F6D20446F6E616C64205472756D702E207265735F646174613A2070313A20302C2070323A20312C2070333A20302E352E20576865726520703120636F72726573706F6E647320746F204E6F2C20703220746F205965732C20703320746F20756E6B6E6F776E2F35302D35302E2055706461746573206D61646520627920746865207175657374696F6E2063726561746F7220766961207468652062756C6C6574696E20626F61726420617420307836413944323232363136433930466341353735346364313333336346443962376662366134463734206173206465736372696265642062792068747470733A2F2F706F6C79676F6E7363616E2E636F6D2F74782F3078613134663031623131356334393133363234666333663530386639363066346465613235323735386537336332386635663037663865313964376263613036362073686F756C6420626520636F6E736964657265642E2C696E697469616C697A65723A393134333063616432643339373537363634393937313766613064363661373864383134653563352C6F6F5265717565737465723A366139643232323631366339306663613537353463643133333363666439623766623661346637342C6368696C645265717565737465723A656533616665333437643563373433313730343165323631386334393533346461663838376332342C6368696C64436861696E49643A313337 )
201 VotingV2.EncryptedVote( caller=[Sender] 0x4cd6ac17782d95dc7a8ee2106ff8de4a52984b01, roundId=10016, identifier=5945535F4F525F4E4F5F51554552590000000000000000000000000000000000, time=1730698959, ancillaryData=0x713A207469746C653A2057696C6C205472756D70207361792022736B696269646922206265666F72652074686520656C656374696F6E3F2C206465736372697074696F6E3A2054686973206D61726B65742077696C6C207265736F6C766520746F20E2809C596573E2809D20696620446F6E616C64205472756D70207075626C69636C79206D656E74696F6E732074686520776F72642022736B696269646922206265747765656E2053657074656D62657220313720616E64204E6F76656D62657220342C20323032342C2031313A353920504D2045542E204F74686572776973652C2074686973206D61726B65742077696C6C207265736F6C766520746F20E2809C4E6FE2809D2E0A0A4120E280986D656E74696F6EE2809920696E636C756465732074686520666F6C6C6F77696E673A0A0A2D412076657262616C207573616765206F662074686520776F72642873292022736B6962696469222E0A2D416E79207772697474656E207573616765206F662074686520776F72642873292022736B696269646922207075626C6973686564207468726F756768205472756D70277320736F6369616C206D65646961206F72206F74686572206F6666696369616C20636F6D6D756E69636174696F6E206368616E6E656C73207265676172646C657373206F66206361706974616C697A6174696F6E2E0A0A416E79207573616765206F662074686520776F7264207265676172646C657373206F6620636F6E746578742077696C6C20636F756E7420746F7761726420746865207265736F6C7574696F6E206F662074686973206D61726B65742E0A0A506C7572616C697A6174696F6E2F706F7373657373697665206F662074686520776F72642077696C6C20636F756E7420746F7761726420746865207265736F6C7574696F6E206F662074686973206D61726B65742C20686F7765766572206F7468657220666F726D732077696C6C204E4F5420636F756E742E0A0A546865207265736F6C7574696F6E20736F7572636520666F722074686973206D61726B65742077696C6C20626520666F6F74616765206F6620446F6E616C64205472756D702074616B656E2077697468696E20746865206D656E74696F6E65642074696D656672616D652C2061732077656C6C206173206F6666696369616C20636F6D6D756E69636174696F6E732066726F6D20446F6E616C64205472756D702E207265735F646174613A2070313A20302C2070323A20312C2070333A20302E352E20576865726520703120636F72726573706F6E647320746F204E6F2C20703220746F205965732C20703320746F20756E6B6E6F776E2F35302D35302E2055706461746573206D61646520627920746865207175657374696F6E2063726561746F7220766961207468652062756C6C6574696E20626F61726420617420307836413944323232363136433930466341353735346364313333336346443962376662366134463734206173206465736372696265642062792068747470733A2F2F706F6C79676F6E7363616E2E636F6D2F74782F3078613134663031623131356334393133363234666333663530386639363066346465613235323735386537336332386635663037663865313964376263613036362073686F756C6420626520636F6E736964657265642E2C696E697469616C697A65723A393134333063616432643339373537363634393937313766613064363661373864383134653563352C6F6F5265717565737465723A366139643232323631366339306663613537353463643133333363666439623766623661346637342C6368696C645265717565737465723A656533616665333437643563373433313730343165323631386334393533346461663838376332342C6368696C64436861696E49643A313337, encryptedVote=0x4C1454AE1CA561491ECD394C43D7C131030DCC5012C19852A9B07DBBA49C08258A34439D217DB20838414F430F0DF9834687F5E012C57CD35486841BFA2C913C9F254E06AFE7692471D5F2B2D0D82FE99888112C99B013A741641968823483E732CF6FAAC36C12E4FD82352B1C8A559C84C414D3DD90B6B38E9240A0689EF3885D86F5DFAA4BD0244575608BD6A71AB069D5449835B75233C4B3C95B58B228B41CF923FF074D0009DAF7445A914CCCE362333E1A362389BB4EC37E32D9480FE99D52DD334FACE652896EE2BF5E3B297C256C11E161BE534ED3C12141666EABB1EB987531E4B6FD719247D212BF19A069FA43C5E7A8B010F00E83D103CD23C3FC1519ED64948DA069EA600A168657B08351 )
202 VotingV2.UpdatedReward( voter=0x4c0deE7F...b5a00fF1d, newReward=483357149044503275, lastUpdateTime=1730845655 )
203 VotingV2.VoteCommitted( voter=0x4c0deE7F...b5a00fF1d, caller=[Sender] 0x4cd6ac17782d95dc7a8ee2106ff8de4a52984b01, roundId=10016, identifier=5945535F4F525F4E4F5F51554552590000000000000000000000000000000000, time=1730658150, ancillaryData=0x713A207469746C653A2057696C6C2053657267696F20506572657A2077696E20746865204272617A696C69616E204772616E6420507269783F2C206465736372697074696F6E3A2054686973206D61726B65742077696C6C207265736F6C766520746F20E2809C596573E2809D2069662053657267696F20506572657A2077696E73207468652032303234204272617A696C69616E204772616E642050726978207363686564756C656420666F72204E6F76656D62657220332C20323032342E204F74686572776973652C2074686973206D61726B65742077696C6C207265736F6C766520746F20E2809C4E6F2EE2809D0A0A4966207468652032303234204272617A696C69616E204772616E6420507269782069732063616E63656C6564206F722072657363686564756C656420746F20612064617465206166746572204E6F76656D6265722031372C20323032342C2074686973206D61726B65742077696C6C207265736F6C766520746F20E2809C4E6F2EE2809D0A0A546865207265736F6C7574696F6E20736F757263652077696C6C20626520746865206F6666696369616C20466F726D756C612031207765627369746520616E64206372656469626C652073706F727473206E657773207265706F7274696E672E2C207265735F646174613A2070313A20302C2070323A20312C2070333A20302E352E20576865726520703120636F72726573706F6E647320746F204E6F2C20703220746F205965732C20703320746F20756E6B6E6F776E2E20546869732072657175657374204D555354206F6E6C79207265736F6C766520746F207031206F722070322E202055706461746573206D61646520627920746865207175657374696F6E2063726561746F7220766961207468652062756C6C6574696E20626F617264206174203078324635653336383463623146333138656335316230304564626133386437394163326330614139642073686F756C6420626520636F6E736964657265642E2C696E697469616C697A65723A393134333063616432643339373537363634393937313766613064363661373864383134653563352C6F6F5265717565737465723A326635653336383463623166333138656335316230306564626133386437396163326330616139642C6368696C645265717565737465723A656533616665333437643563373433313730343165323631386334393533346461663838376332342C6368696C64436861696E49643A313337 )
204 VotingV2.EncryptedVote( caller=[Sender] 0x4cd6ac17782d95dc7a8ee2106ff8de4a52984b01, roundId=10016, identifier=5945535F4F525F4E4F5F51554552590000000000000000000000000000000000, time=1730658150, ancillaryData=0x713A207469746C653A2057696C6C2053657267696F20506572657A2077696E20746865204272617A696C69616E204772616E6420507269783F2C206465736372697074696F6E3A2054686973206D61726B65742077696C6C207265736F6C766520746F20E2809C596573E2809D2069662053657267696F20506572657A2077696E73207468652032303234204272617A696C69616E204772616E642050726978207363686564756C656420666F72204E6F76656D62657220332C20323032342E204F74686572776973652C2074686973206D61726B65742077696C6C207265736F6C766520746F20E2809C4E6F2EE2809D0A0A4966207468652032303234204272617A696C69616E204772616E6420507269782069732063616E63656C6564206F722072657363686564756C656420746F20612064617465206166746572204E6F76656D6265722031372C20323032342C2074686973206D61726B65742077696C6C207265736F6C766520746F20E2809C4E6F2EE2809D0A0A546865207265736F6C7574696F6E20736F757263652077696C6C20626520746865206F6666696369616C20466F726D756C612031207765627369746520616E64206372656469626C652073706F727473206E657773207265706F7274696E672E2C207265735F646174613A2070313A20302C2070323A20312C2070333A20302E352E20576865726520703120636F72726573706F6E647320746F204E6F2C20703220746F205965732C20703320746F20756E6B6E6F776E2E20546869732072657175657374204D555354206F6E6C79207265736F6C766520746F207031206F722070322E202055706461746573206D61646520627920746865207175657374696F6E2063726561746F7220766961207468652062756C6C6574696E20626F617264206174203078324635653336383463623146333138656335316230304564626133386437394163326330614139642073686F756C6420626520636F6E736964657265642E2C696E697469616C697A65723A393134333063616432643339373537363634393937313766613064363661373864383134653563352C6F6F5265717565737465723A326635653336383463623166333138656335316230306564626133386437396163326330616139642C6368696C645265717565737465723A656533616665333437643563373433313730343165323631386334393533346461663838376332342C6368696C64436861696E49643A313337, encryptedVote=0xC7E341D4F6183333A454D96C170BCC6A035CC0D700D3EEB0779147E733641F2BED92C442EA557A78EB399F15FA8C98EC593B242A2D2BF01A5D983713B8F0B0E2451DCE4FCDFCD523E9B9AA55B1B3E62F3761737EAAC15C2207BCEE7D09D581209906B916B24ECA1C23CBE28E07138251D2ED825E2F8F594BC4F517F69CB7E6D5729853C1E19F9375F12A8B377949F6CDF9C126A3BAFDB9DE20D3A2E40C1A8838C4C05B4DFBD083F2B0114541B8FECDCFC2DEBDA3AE35FAA8F6A6C10383749CB84325BFF43F372D842320CF83D159B5E6F83799DA809EF125EEAF12AB7B91F4769C92CF1A7AC53E87B3B720CDB4257400802421F3F38B5C2E0E06472040931BB7E14AF754B016C23DA1663F1DA85767051F )
205 VotingV2.UpdatedReward( voter=0x4c0deE7F...b5a00fF1d, newReward=483357149044503275, lastUpdateTime=1730845655 )
206 VotingV2.VoteCommitted( voter=0x4c0deE7F...b5a00fF1d, caller=[Sender] 0x4cd6ac17782d95dc7a8ee2106ff8de4a52984b01, roundId=10016, identifier=5945535F4F525F4E4F5F51554552590000000000000000000000000000000000, time=1730592385, ancillaryData=0x713A207469746C653A2057696C6C205472756D70207361792022766F746522203330206F72206D6F72652074696D657320647572696E672056697267696E69612072616C6C79206F6E204E6F7620323F2C206465736372697074696F6E3A20446F6E616C64205472756D7020686173207363686564756C656420612072616C6C79206F6E204E6F76656D626572203220696E2053616C656D2C2056697267696E696120287365653A2068747470733A2F2F6576656E742E646F6E616C646A7472756D702E636F6D2F6576656E74732F707265736964656E742D646F6E616C642D6A2D7472756D702D746F2D686F6C642D612D72616C6C792D696E2D73616C656D2D76697267696E6961292E0A0A54686973206D61726B65742077696C6C207265736F6C766520746F202259657322206966205472756D7020736179732022766F746522203330206F72206D6F72652074696D657320647572696E6720746865697220617070656172616E63652061742074686973206576656E742E204F74686572776973652C20746865206D61726B65742077696C6C207265736F6C766520746F20224E6F222E0A0A416E79207573616765206F6620746865207465726D207265676172646C657373206F6620636F6E746578742077696C6C20636F756E7420746F7761726420746865207265736F6C7574696F6E206F662074686973206D61726B65742E0A0A506C7572616C697A6174696F6E2F706F7373657373697665206F6620746865207465726D2077696C6C20636F756E7420746F7761726420746865207265736F6C7574696F6E206F662074686973206D61726B65742C20686F7765766572206F7468657220666F726D732077696C6C204E4F5420636F756E742E0A0A436F6D706F756E6420776F7264732077696C6C20636F756E74206173206C6F6E672061732022766F7465222069732070617274206F662074686520636F6D706F756E6420776F726420616E64207265666572656E63657320746865206D65616E696E672077686963682072656665727320746F206120666F726D616C20696E6469636174696F6E206F6620612063686F696365206265747765656E2074776F206F72206D6F72652063616E64696461746573206F7220636F7572736573206F6620616374696F6E2C20657870726573736564207479706963616C6C79207468726F75676820612062616C6C6F74206F7220612073686F77206F662068616E6473206F7220627920766F6963652E0A0A496620746869732063616E64696461746520646F6573206E6F74206170706561722061742074686973206576656E742C206F7220696620746865206576656E74206973206F74686572776973652063616E63656C6C6564206F722064656C61796564206265796F6E64204E6F76656D62657220322C2074686973206D61726B65742077696C6C207265736F6C766520746F20224E6F222E0A0A546865207265736F6C7574696F6E20736F757263652077696C6C2062652074686520766964656F206F6620746865207370656563682E207265735F646174613A2070313A20302C2070323A20312C2070333A20302E352E20576865726520703120636F72726573706F6E647320746F204E6F2C20703220746F205965732C20703320746F20756E6B6E6F776E2F35302D35302E2055706461746573206D61646520627920746865207175657374696F6E2063726561746F7220766961207468652062756C6C6574696E20626F61726420617420307836413944323232363136433930466341353735346364313333336346443962376662366134463734206173206465736372696265642062792068747470733A2F2F706F6C79676F6E7363616E2E636F6D2F74782F3078613134663031623131356334393133363234666333663530386639363066346465613235323735386537336332386635663037663865313964376263613036362073686F756C6420626520636F6E736964657265642E2C696E697469616C697A65723A393134333063616432643339373537363634393937313766613064363661373864383134653563352C6F6F5265717565737465723A366139643232323631366339306663613537353463643133333363666439623766623661346637342C6368696C645265717565737465723A656533616665333437643563373433313730343165323631386334393533346461663838376332342C6368696C64436861696E49643A313337 )
207 VotingV2.EncryptedVote( caller=[Sender] 0x4cd6ac17782d95dc7a8ee2106ff8de4a52984b01, roundId=10016, identifier=5945535F4F525F4E4F5F51554552590000000000000000000000000000000000, time=1730592385, ancillaryData=0x713A207469746C653A2057696C6C205472756D70207361792022766F746522203330206F72206D6F72652074696D657320647572696E672056697267696E69612072616C6C79206F6E204E6F7620323F2C206465736372697074696F6E3A20446F6E616C64205472756D7020686173207363686564756C656420612072616C6C79206F6E204E6F76656D626572203220696E2053616C656D2C2056697267696E696120287365653A2068747470733A2F2F6576656E742E646F6E616C646A7472756D702E636F6D2F6576656E74732F707265736964656E742D646F6E616C642D6A2D7472756D702D746F2D686F6C642D612D72616C6C792D696E2D73616C656D2D76697267696E6961292E0A0A54686973206D61726B65742077696C6C207265736F6C766520746F202259657322206966205472756D7020736179732022766F746522203330206F72206D6F72652074696D657320647572696E6720746865697220617070656172616E63652061742074686973206576656E742E204F74686572776973652C20746865206D61726B65742077696C6C207265736F6C766520746F20224E6F222E0A0A416E79207573616765206F6620746865207465726D207265676172646C657373206F6620636F6E746578742077696C6C20636F756E7420746F7761726420746865207265736F6C7574696F6E206F662074686973206D61726B65742E0A0A506C7572616C697A6174696F6E2F706F7373657373697665206F6620746865207465726D2077696C6C20636F756E7420746F7761726420746865207265736F6C7574696F6E206F662074686973206D61726B65742C20686F7765766572206F7468657220666F726D732077696C6C204E4F5420636F756E742E0A0A436F6D706F756E6420776F7264732077696C6C20636F756E74206173206C6F6E672061732022766F7465222069732070617274206F662074686520636F6D706F756E6420776F726420616E64207265666572656E63657320746865206D65616E696E672077686963682072656665727320746F206120666F726D616C20696E6469636174696F6E206F6620612063686F696365206265747765656E2074776F206F72206D6F72652063616E64696461746573206F7220636F7572736573206F6620616374696F6E2C20657870726573736564207479706963616C6C79207468726F75676820612062616C6C6F74206F7220612073686F77206F662068616E6473206F7220627920766F6963652E0A0A496620746869732063616E64696461746520646F6573206E6F74206170706561722061742074686973206576656E742C206F7220696620746865206576656E74206973206F74686572776973652063616E63656C6C6564206F722064656C61796564206265796F6E64204E6F76656D62657220322C2074686973206D61726B65742077696C6C207265736F6C766520746F20224E6F222E0A0A546865207265736F6C7574696F6E20736F757263652077696C6C2062652074686520766964656F206F6620746865207370656563682E207265735F646174613A2070313A20302C2070323A20312C2070333A20302E352E20576865726520703120636F72726573706F6E647320746F204E6F2C20703220746F205965732C20703320746F20756E6B6E6F776E2F35302D35302E2055706461746573206D61646520627920746865207175657374696F6E2063726561746F7220766961207468652062756C6C6574696E20626F61726420617420307836413944323232363136433930466341353735346364313333336346443962376662366134463734206173206465736372696265642062792068747470733A2F2F706F6C79676F6E7363616E2E636F6D2F74782F3078613134663031623131356334393133363234666333663530386639363066346465613235323735386537336332386635663037663865313964376263613036362073686F756C6420626520636F6E736964657265642E2C696E697469616C697A65723A393134333063616432643339373537363634393937313766613064363661373864383134653563352C6F6F5265717565737465723A366139643232323631366339306663613537353463643133333363666439623766623661346637342C6368696C645265717565737465723A656533616665333437643563373433313730343165323631386334393533346461663838376332342C6368696C64436861696E49643A313337, encryptedVote=0xB205D7FDBC59D4F3A51CED953FC1BB4C025561992F917E75FA726809D472A88B12231522BEF1ABE4D67A0C3F5643B1D4ACEC9F5E5B64C6F38ECF35DB7A96EC5AF06A8A097261B94147C7D3E51D1BC07116F6DCBC2828A8A00A9AEE5CD64772CBA370BC0CDEC3AB78694B4197455FC4DE610AA8B4FEBAFA69D3C3ACF395C94B9140B65911BF852D80B7651D92566B93ED7C1D76E330F513F61D10194CEAC9E28D38D4B8EA4FA6091EC9BBBE418BCAE491B12346D4D53F747DF61A86EA6BC44BB087572F20F30B19C8AD5CAEAD4F68260597 )
208 VotingV2.UpdatedReward( voter=0x4c0deE7F...b5a00fF1d, newReward=483357149044503275, lastUpdateTime=1730845655 )
209 VotingV2.VoteCommitted( voter=0x4c0deE7F...b5a00fF1d, caller=[Sender] 0x4cd6ac17782d95dc7a8ee2106ff8de4a52984b01, roundId=10016, identifier=5945535F4F525F4E4F5F51554552590000000000000000000000000000000000, time=1730614228, ancillaryData=0x713A207469746C653A2057696C6C205472756D70207361792022766F746522203235206F72206D6F726520647572696E6720477265656E73626F726F2C204E432072616C6C793F2C206465736372697074696F6E3A20446F6E616C64205472756D7020686173207363686564756C656420612072616C6C79206F6E204E6F76656D626572203220696E20477265656E73626F726F2C204E6F727468204361726F6C696E6120287365653A2068747470733A2F2F6576656E742E646F6E616C646A7472756D702E636F6D2F6576656E74732F707265736964656E742D646F6E616C642D6A2D7472756D702D746F2D686F6C642D612D72616C6C792D696E2D677265656E73626F726F2D6E63292E0A0A54686973206D61726B65742077696C6C207265736F6C766520746F202259657322206966205472756D7020736179732022766F746522203235206F72206D6F72652074696D657320647572696E6720746865697220617070656172616E63652061742074686973206576656E742E204F74686572776973652C20746865206D61726B65742077696C6C207265736F6C766520746F20224E6F222E0A0A416E79207573616765206F6620746865207465726D207265676172646C657373206F6620636F6E746578742077696C6C20636F756E7420746F7761726420746865207265736F6C7574696F6E206F662074686973206D61726B65742E0A0A506C7572616C697A6174696F6E2F706F7373657373697665206F6620746865207465726D2077696C6C20636F756E7420746F7761726420746865207265736F6C7574696F6E206F662074686973206D61726B65742C20686F7765766572206F7468657220666F726D732077696C6C204E4F5420636F756E742E0A0A436F6D706F756E6420776F7264732077696C6C20636F756E74206173206C6F6E672061732022766F7465222069732070617274206F662074686520636F6D706F756E6420776F726420616E64207265666572656E63657320746865206D65616E696E672077686963682072656665727320746F206120666F726D616C2065787072657373696F6E206F662063686F696365206F72206F70696E696F6E20696E20616E20656C656374696F6E2E0A0A496620746869732063616E64696461746520646F6573206E6F74206170706561722061742074686973206576656E742C206F7220696620746865206576656E74206973206F74686572776973652063616E63656C6C6564206F722064656C61796564206265796F6E64204E6F76656D62657220322C2074686973206D61726B65742077696C6C207265736F6C766520746F20224E6F222E0A0A546865207265736F6C7574696F6E20736F757263652077696C6C2062652074686520766964656F206F6620746865207370656563682E207265735F646174613A2070313A20302C2070323A20312C2070333A20302E352E20576865726520703120636F72726573706F6E647320746F204E6F2C20703220746F205965732C20703320746F20756E6B6E6F776E2F35302D35302E2055706461746573206D61646520627920746865207175657374696F6E2063726561746F7220766961207468652062756C6C6574696E20626F61726420617420307836413944323232363136433930466341353735346364313333336346443962376662366134463734206173206465736372696265642062792068747470733A2F2F706F6C79676F6E7363616E2E636F6D2F74782F3078613134663031623131356334393133363234666333663530386639363066346465613235323735386537336332386635663037663865313964376263613036362073686F756C6420626520636F6E736964657265642E2C696E697469616C697A65723A393134333063616432643339373537363634393937313766613064363661373864383134653563352C6F6F5265717565737465723A366139643232323631366339306663613537353463643133333363666439623766623661346637342C6368696C645265717565737465723A656533616665333437643563373433313730343165323631386334393533346461663838376332342C6368696C64436861696E49643A313337 )
210 VotingV2.EncryptedVote( caller=[Sender] 0x4cd6ac17782d95dc7a8ee2106ff8de4a52984b01, roundId=10016, identifier=5945535F4F525F4E4F5F51554552590000000000000000000000000000000000, time=1730614228, ancillaryData=0x713A207469746C653A2057696C6C205472756D70207361792022766F746522203235206F72206D6F726520647572696E6720477265656E73626F726F2C204E432072616C6C793F2C206465736372697074696F6E3A20446F6E616C64205472756D7020686173207363686564756C656420612072616C6C79206F6E204E6F76656D626572203220696E20477265656E73626F726F2C204E6F727468204361726F6C696E6120287365653A2068747470733A2F2F6576656E742E646F6E616C646A7472756D702E636F6D2F6576656E74732F707265736964656E742D646F6E616C642D6A2D7472756D702D746F2D686F6C642D612D72616C6C792D696E2D677265656E73626F726F2D6E63292E0A0A54686973206D61726B65742077696C6C207265736F6C766520746F202259657322206966205472756D7020736179732022766F746522203235206F72206D6F72652074696D657320647572696E6720746865697220617070656172616E63652061742074686973206576656E742E204F74686572776973652C20746865206D61726B65742077696C6C207265736F6C766520746F20224E6F222E0A0A416E79207573616765206F6620746865207465726D207265676172646C657373206F6620636F6E746578742077696C6C20636F756E7420746F7761726420746865207265736F6C7574696F6E206F662074686973206D61726B65742E0A0A506C7572616C697A6174696F6E2F706F7373657373697665206F6620746865207465726D2077696C6C20636F756E7420746F7761726420746865207265736F6C7574696F6E206F662074686973206D61726B65742C20686F7765766572206F7468657220666F726D732077696C6C204E4F5420636F756E742E0A0A436F6D706F756E6420776F7264732077696C6C20636F756E74206173206C6F6E672061732022766F7465222069732070617274206F662074686520636F6D706F756E6420776F726420616E64207265666572656E63657320746865206D65616E696E672077686963682072656665727320746F206120666F726D616C2065787072657373696F6E206F662063686F696365206F72206F70696E696F6E20696E20616E20656C656374696F6E2E0A0A496620746869732063616E64696461746520646F6573206E6F74206170706561722061742074686973206576656E742C206F7220696620746865206576656E74206973206F74686572776973652063616E63656C6C6564206F722064656C61796564206265796F6E64204E6F76656D62657220322C2074686973206D61726B65742077696C6C207265736F6C766520746F20224E6F222E0A0A546865207265736F6C7574696F6E20736F757263652077696C6C2062652074686520766964656F206F6620746865207370656563682E207265735F646174613A2070313A20302C2070323A20312C2070333A20302E352E20576865726520703120636F72726573706F6E647320746F204E6F2C20703220746F205965732C20703320746F20756E6B6E6F776E2F35302D35302E2055706461746573206D61646520627920746865207175657374696F6E2063726561746F7220766961207468652062756C6C6574696E20626F61726420617420307836413944323232363136433930466341353735346364313333336346443962376662366134463734206173206465736372696265642062792068747470733A2F2F706F6C79676F6E7363616E2E636F6D2F74782F3078613134663031623131356334393133363234666333663530386639363066346465613235323735386537336332386635663037663865313964376263613036362073686F756C6420626520636F6E736964657265642E2C696E697469616C697A65723A393134333063616432643339373537363634393937313766613064363661373864383134653563352C6F6F5265717565737465723A366139643232323631366339306663613537353463643133333363666439623766623661346637342C6368696C645265717565737465723A656533616665333437643563373433313730343165323631386334393533346461663838376332342C6368696C64436861696E49643A313337, encryptedVote=0x62471FD25396474D1E4BF83230A55617027043B9189F5CA09C193EF2C0CA2EC17B7145C6541B25F25493EFB7FDA984386A144EEC22283973E463E36DD909DB2861B5F485A759C9D5B3982E72DD642C4A489C16CFB90831192C30B4F5BE42BDF0F36A1D8F2F5C104EBBD5FCAD739F4CBC434F92269D3A3E648EB581BD2F9F2174D26E2557302C3E798F4BF01CF41EE6EEEBD17F9485EA68BE0876C725F9D42AAF2C865BD8CF9BE9D89AD0897AB70E3BC8D44342978E86AEF1D7373BDEF4ADDD15C9377D8C16E0FFED77E643A6AF0576E1CC )
211 VotingV2.UpdatedReward( voter=0x4c0deE7F...b5a00fF1d, newReward=483357149044503275, lastUpdateTime=1730845655 )
212 VotingV2.VoteCommitted( voter=0x4c0deE7F...b5a00fF1d, caller=[Sender] 0x4cd6ac17782d95dc7a8ee2106ff8de4a52984b01, roundId=10016, identifier=5945535F4F525F4E4F5F51554552590000000000000000000000000000000000, time=1730618526, ancillaryData=0x713A207469746C653A20426172726961756C742076732E2053746F6C747A6675732C206465736372697074696F6E3A20546869732069732061206D61726B6574206F6E2077686574686572204D6172632D416E64726520426172726961756C74206F722044757374696E2053746F6C747A6675732077696C6C2077696E20746865697220626F75742E0A0A4966204D6172632D416E64726520426172726961756C74206973206465636C61726564207468652077696E6E6572206F66207468697320626F75742C2074686973206D61726B65742077696C6C207265736F6C766520746F20E2809C426172726961756C742EE2809D2049662044757374696E2053746F6C747A667573206973206465636C61726564207468652077696E6E6572206F66207468697320626F75742C2074686973206D61726B65742077696C6C207265736F6C766520746F20E2809C53746F6C747A667573E2809D2E0A0A49662074686973206669676874206973206465636C61726564206120647261772C206F7220696620666F7220616E7920726561736F6E20746865206D61746368206973206E6F742073636F7265642C20706F7374706F6E6564206166746572204E6F76656D6265722031362C20323032342C2031313A353920504D2045542C206F722063616E63656C65642C2074686973206D61726B65742077696C6C207265736F6C76652035302D35302E207265735F646174613A2070313A20302C2070323A20312C2070333A20302E352E20576865726520703120636F72726573706F6E647320746F204E6F2C20703220746F205965732C20703320746F20756E6B6E6F776E2F35302D35302E2055706461746573206D61646520627920746865207175657374696F6E2063726561746F7220766961207468652062756C6C6574696E20626F61726420617420307836413944323232363136433930466341353735346364313333336346443962376662366134463734206173206465736372696265642062792068747470733A2F2F706F6C79676F6E7363616E2E636F6D2F74782F3078613134663031623131356334393133363234666333663530386639363066346465613235323735386537336332386635663037663865313964376263613036362073686F756C6420626520636F6E736964657265642E2C696E697469616C697A65723A393134333063616432643339373537363634393937313766613064363661373864383134653563352C6F6F5265717565737465723A366139643232323631366339306663613537353463643133333363666439623766623661346637342C6368696C645265717565737465723A656533616665333437643563373433313730343165323631386334393533346461663838376332342C6368696C64436861696E49643A313337 )
213 VotingV2.EncryptedVote( caller=[Sender] 0x4cd6ac17782d95dc7a8ee2106ff8de4a52984b01, roundId=10016, identifier=5945535F4F525F4E4F5F51554552590000000000000000000000000000000000, time=1730618526, ancillaryData=0x713A207469746C653A20426172726961756C742076732E2053746F6C747A6675732C206465736372697074696F6E3A20546869732069732061206D61726B6574206F6E2077686574686572204D6172632D416E64726520426172726961756C74206F722044757374696E2053746F6C747A6675732077696C6C2077696E20746865697220626F75742E0A0A4966204D6172632D416E64726520426172726961756C74206973206465636C61726564207468652077696E6E6572206F66207468697320626F75742C2074686973206D61726B65742077696C6C207265736F6C766520746F20E2809C426172726961756C742EE2809D2049662044757374696E2053746F6C747A667573206973206465636C61726564207468652077696E6E6572206F66207468697320626F75742C2074686973206D61726B65742077696C6C207265736F6C766520746F20E2809C53746F6C747A667573E2809D2E0A0A49662074686973206669676874206973206465636C61726564206120647261772C206F7220696620666F7220616E7920726561736F6E20746865206D61746368206973206E6F742073636F7265642C20706F7374706F6E6564206166746572204E6F76656D6265722031362C20323032342C2031313A353920504D2045542C206F722063616E63656C65642C2074686973206D61726B65742077696C6C207265736F6C76652035302D35302E207265735F646174613A2070313A20302C2070323A20312C2070333A20302E352E20576865726520703120636F72726573706F6E647320746F204E6F2C20703220746F205965732C20703320746F20756E6B6E6F776E2F35302D35302E2055706461746573206D61646520627920746865207175657374696F6E2063726561746F7220766961207468652062756C6C6574696E20626F61726420617420307836413944323232363136433930466341353735346364313333336346443962376662366134463734206173206465736372696265642062792068747470733A2F2F706F6C79676F6E7363616E2E636F6D2F74782F3078613134663031623131356334393133363234666333663530386639363066346465613235323735386537336332386635663037663865313964376263613036362073686F756C6420626520636F6E736964657265642E2C696E697469616C697A65723A393134333063616432643339373537363634393937313766613064363661373864383134653563352C6F6F5265717565737465723A366139643232323631366339306663613537353463643133333363666439623766623661346637342C6368696C645265717565737465723A656533616665333437643563373433313730343165323631386334393533346461663838376332342C6368696C64436861696E49643A313337, encryptedVote=0x1B3E5D14591B5997761F12E690D3244F031520227602542450B92A45618CBB63B1D67992911E0CC747834B79DF6BA1478B7AAD766E6BBE7F6FF3D5CE7B807F6C4705A0B9190CE1F1503D3A7F7D38F1744548F625297188A59755DEEA783E74C3629689C92687D098F3BC7F0763A8CB218BA499541AACE1FED814610E3E46E173E05AFDF3E43DBA526E151844683EF46D52E8ED730546AB4F0DECC96B72A04D36B4628830DA35CC43A56D2171122E0396DBBE78E750964CD3C35CCE9D3715DB24EA )
214 VotingV2.UpdatedReward( voter=0x4c0deE7F...b5a00fF1d, newReward=483357149044503275, lastUpdateTime=1730845655 )
215 VotingV2.VoteCommitted( voter=0x4c0deE7F...b5a00fF1d, caller=[Sender] 0x4cd6ac17782d95dc7a8ee2106ff8de4a52984b01, roundId=10016, identifier=5945535F4F525F4E4F5F51554552590000000000000000000000000000000000, time=1730654141, ancillaryData=0x713A207469746C653A2057696C6C204361726C6F73205361696E7A2077696E20746865204272617A696C69616E204772616E6420507269783F2C206465736372697074696F6E3A2054686973206D61726B65742077696C6C207265736F6C766520746F20E2809C596573E2809D206966204361726C6F73205361696E7A2077696E73207468652032303234204272617A696C69616E204772616E642050726978207363686564756C656420666F72204E6F76656D62657220332C20323032342E204F74686572776973652C2074686973206D61726B65742077696C6C207265736F6C766520746F20E2809C4E6F2EE2809D0A0A4966207468652032303234204272617A696C69616E204772616E6420507269782069732063616E63656C6564206F722072657363686564756C656420746F20612064617465206166746572204E6F76656D6265722031372C20323032342C2074686973206D61726B65742077696C6C207265736F6C766520746F20E2809C4E6F2EE2809D0A0A546865207265736F6C7574696F6E20736F757263652077696C6C20626520746865206F6666696369616C20466F726D756C612031207765627369746520616E64206372656469626C652073706F727473206E657773207265706F7274696E672E2C207265735F646174613A2070313A20302C2070323A20312C2070333A20302E352E20576865726520703120636F72726573706F6E647320746F204E6F2C20703220746F205965732C20703320746F20756E6B6E6F776E2E20546869732072657175657374204D555354206F6E6C79207265736F6C766520746F207031206F722070322E202055706461746573206D61646520627920746865207175657374696F6E2063726561746F7220766961207468652062756C6C6574696E20626F617264206174203078324635653336383463623146333138656335316230304564626133386437394163326330614139642073686F756C6420626520636F6E736964657265642E2C696E697469616C697A65723A393134333063616432643339373537363634393937313766613064363661373864383134653563352C6F6F5265717565737465723A326635653336383463623166333138656335316230306564626133386437396163326330616139642C6368696C645265717565737465723A656533616665333437643563373433313730343165323631386334393533346461663838376332342C6368696C64436861696E49643A313337 )
216 VotingV2.EncryptedVote( caller=[Sender] 0x4cd6ac17782d95dc7a8ee2106ff8de4a52984b01, roundId=10016, identifier=5945535F4F525F4E4F5F51554552590000000000000000000000000000000000, time=1730654141, ancillaryData=0x713A207469746C653A2057696C6C204361726C6F73205361696E7A2077696E20746865204272617A696C69616E204772616E6420507269783F2C206465736372697074696F6E3A2054686973206D61726B65742077696C6C207265736F6C766520746F20E2809C596573E2809D206966204361726C6F73205361696E7A2077696E73207468652032303234204272617A696C69616E204772616E642050726978207363686564756C656420666F72204E6F76656D62657220332C20323032342E204F74686572776973652C2074686973206D61726B65742077696C6C207265736F6C766520746F20E2809C4E6F2EE2809D0A0A4966207468652032303234204272617A696C69616E204772616E6420507269782069732063616E63656C6564206F722072657363686564756C656420746F20612064617465206166746572204E6F76656D6265722031372C20323032342C2074686973206D61726B65742077696C6C207265736F6C766520746F20E2809C4E6F2EE2809D0A0A546865207265736F6C7574696F6E20736F757263652077696C6C20626520746865206F6666696369616C20466F726D756C612031207765627369746520616E64206372656469626C652073706F727473206E657773207265706F7274696E672E2C207265735F646174613A2070313A20302C2070323A20312C2070333A20302E352E20576865726520703120636F72726573706F6E647320746F204E6F2C20703220746F205965732C20703320746F20756E6B6E6F776E2E20546869732072657175657374204D555354206F6E6C79207265736F6C766520746F207031206F722070322E202055706461746573206D61646520627920746865207175657374696F6E2063726561746F7220766961207468652062756C6C6574696E20626F617264206174203078324635653336383463623146333138656335316230304564626133386437394163326330614139642073686F756C6420626520636F6E736964657265642E2C696E697469616C697A65723A393134333063616432643339373537363634393937313766613064363661373864383134653563352C6F6F5265717565737465723A326635653336383463623166333138656335316230306564626133386437396163326330616139642C6368696C645265717565737465723A656533616665333437643563373433313730343165323631386334393533346461663838376332342C6368696C64436861696E49643A313337, encryptedVote=0x10F2A035AAABD821579D5A02304477F80200EB1366A4840C9BF7E34D357DFF5F483DF8999D5ECF3F468DC6E8F77E57578C666B80D9CE366F9A81131F8B225F4AFAB24C22B974B77FEADE848FEC77C6B915C40CA4BCB680ACE85C4B343FD0325C6B494E448ED7937152D483DA66B9F7019587EE7C62C10F85AEC11D5A5C88296B9055F893285A83E88C8DFA3BA7E562B139427A759E19303EA3F391C6FF94C6554148815E83650F75D58BB8E8866ED3BE04465B4E06DE4274B19BD98A10A14277F5CA2DE2B0C2ABCEFC046EF286DC448EFB0B8F5389CD20C4B6EEEFF47FAC59E112E54C750FB18AFA80380058A4A6E2FC1B38CAF0C623FD6126AFEB192A7CB46D44C67E4F26B9C1118DEAE27AED158B8BA6 )
217 VotingV2.UpdatedReward( voter=0x4c0deE7F...b5a00fF1d, newReward=483357149044503275, lastUpdateTime=1730845655 )
218 VotingV2.VoteCommitted( voter=0x4c0deE7F...b5a00fF1d, caller=[Sender] 0x4cd6ac17782d95dc7a8ee2106ff8de4a52984b01, roundId=10016, identifier=5945535F4F525F4E4F5F51554552590000000000000000000000000000000000, time=1730657292, ancillaryData=0x713A207469746C653A2057696C6C2053657267696F20506572657A2077696E20746865204272617A696C69616E204772616E6420507269783F2C206465736372697074696F6E3A2054686973206D61726B65742077696C6C207265736F6C766520746F20E2809C596573E2809D2069662053657267696F20506572657A2077696E73207468652032303234204272617A696C69616E204772616E642050726978207363686564756C656420666F72204E6F76656D62657220332C20323032342E204F74686572776973652C2074686973206D61726B65742077696C6C207265736F6C766520746F20E2809C4E6F2EE2809D0A0A4966207468652032303234204272617A696C69616E204772616E6420507269782069732063616E63656C6564206F722072657363686564756C656420746F20612064617465206166746572204E6F76656D6265722031372C20323032342C2074686973206D61726B65742077696C6C207265736F6C766520746F20E2809C4E6F2EE2809D0A0A546865207265736F6C7574696F6E20736F757263652077696C6C20626520746865206F6666696369616C20466F726D756C612031207765627369746520616E64206372656469626C652073706F727473206E657773207265706F7274696E672E2C207265735F646174613A2070313A20302C2070323A20312C2070333A20302E352E20576865726520703120636F72726573706F6E647320746F204E6F2C20703220746F205965732C20703320746F20756E6B6E6F776E2E20546869732072657175657374204D555354206F6E6C79207265736F6C766520746F207031206F722070322E202055706461746573206D61646520627920746865207175657374696F6E2063726561746F7220766961207468652062756C6C6574696E20626F617264206174203078324635653336383463623146333138656335316230304564626133386437394163326330614139642073686F756C6420626520636F6E736964657265642E2C696E697469616C697A65723A393134333063616432643339373537363634393937313766613064363661373864383134653563352C6F6F5265717565737465723A326635653336383463623166333138656335316230306564626133386437396163326330616139642C6368696C645265717565737465723A656533616665333437643563373433313730343165323631386334393533346461663838376332342C6368696C64436861696E49643A313337 )
219 VotingV2.EncryptedVote( caller=[Sender] 0x4cd6ac17782d95dc7a8ee2106ff8de4a52984b01, roundId=10016, identifier=5945535F4F525F4E4F5F51554552590000000000000000000000000000000000, time=1730657292, ancillaryData=0x713A207469746C653A2057696C6C2053657267696F20506572657A2077696E20746865204272617A696C69616E204772616E6420507269783F2C206465736372697074696F6E3A2054686973206D61726B65742077696C6C207265736F6C766520746F20E2809C596573E2809D2069662053657267696F20506572657A2077696E73207468652032303234204272617A696C69616E204772616E642050726978207363686564756C656420666F72204E6F76656D62657220332C20323032342E204F74686572776973652C2074686973206D61726B65742077696C6C207265736F6C766520746F20E2809C4E6F2EE2809D0A0A4966207468652032303234204272617A696C69616E204772616E6420507269782069732063616E63656C6564206F722072657363686564756C656420746F20612064617465206166746572204E6F76656D6265722031372C20323032342C2074686973206D61726B65742077696C6C207265736F6C766520746F20E2809C4E6F2EE2809D0A0A546865207265736F6C7574696F6E20736F757263652077696C6C20626520746865206F6666696369616C20466F726D756C612031207765627369746520616E64206372656469626C652073706F727473206E657773207265706F7274696E672E2C207265735F646174613A2070313A20302C2070323A20312C2070333A20302E352E20576865726520703120636F72726573706F6E647320746F204E6F2C20703220746F205965732C20703320746F20756E6B6E6F776E2E20546869732072657175657374204D555354206F6E6C79207265736F6C766520746F207031206F722070322E202055706461746573206D61646520627920746865207175657374696F6E2063726561746F7220766961207468652062756C6C6574696E20626F617264206174203078324635653336383463623146333138656335316230304564626133386437394163326330614139642073686F756C6420626520636F6E736964657265642E2C696E697469616C697A65723A393134333063616432643339373537363634393937313766613064363661373864383134653563352C6F6F5265717565737465723A326635653336383463623166333138656335316230306564626133386437396163326330616139642C6368696C645265717565737465723A656533616665333437643563373433313730343165323631386334393533346461663838376332342C6368696C64436861696E49643A313337, encryptedVote=0xE92FADF5D4C2A2274C9B873B987FA9E0033D6A74183353D14F3B9AF45D7261607F1FC056B0F594913ECDEB326B85D4DE0D9BDEA00125E831B84FB1E7A21A0BD6B83A16EAFA27D94A66BB793D19D0CC3B447D50DAEB6EA7B8B6D5B3F1E84CE63FCC099AE2C4389C62DE2BB7C8D5E51B06D71BEB1ACD7517A2DB8D176612183C8B813671A10F7AA45A47177B5847F628954D4730B4EC8C6A0C13BE47314DE2E0DA01030E8A79C770AD34097DF10651CAC2A7BA4617C47F5570167B89DFE1480F2A674C6DD5F22654E21418C8FFFC55936CBFDD6DBFA72AC093B4B78B6BDA7E25DE0CC60EA3734CA57D280D227A33EDCF84EA71C6C08821EEB468D15EC913BFE28BC83A72703B7E274FCFFC932BD3FE20CB0A )
220 VotingV2.UpdatedReward( voter=0x4c0deE7F...b5a00fF1d, newReward=483357149044503275, lastUpdateTime=1730845655 )
221 VotingV2.VoteCommitted( voter=0x4c0deE7F...b5a00fF1d, caller=[Sender] 0x4cd6ac17782d95dc7a8ee2106ff8de4a52984b01, roundId=10016, identifier=5945535F4F525F4E4F5F51554552590000000000000000000000000000000000, time=1730657300, ancillaryData=0x713A207469746C653A2057696C6C204F7363617220506961737472692077696E20746865204272617A696C69616E204772616E6420507269783F2C206465736372697074696F6E3A2054686973206D61726B65742077696C6C207265736F6C766520746F20E2809C596573E2809D206966204F7363617220506961737472692077696E73207468652032303234204272617A696C69616E204772616E642050726978207363686564756C656420666F72204E6F76656D62657220332C20323032342E204F74686572776973652C2074686973206D61726B65742077696C6C207265736F6C766520746F20E2809C4E6F2EE2809D0A0A4966207468652032303234204272617A696C69616E204772616E6420507269782069732063616E63656C6564206F722072657363686564756C656420746F20612064617465206166746572204E6F76656D6265722031372C20323032342C2074686973206D61726B65742077696C6C207265736F6C766520746F20E2809C4E6F2EE2809D0A0A546865207265736F6C7574696F6E20736F757263652077696C6C20626520746865206F6666696369616C20466F726D756C612031207765627369746520616E64206372656469626C652073706F727473206E657773207265706F7274696E672E2C207265735F646174613A2070313A20302C2070323A20312C2070333A20302E352E20576865726520703120636F72726573706F6E647320746F204E6F2C20703220746F205965732C20703320746F20756E6B6E6F776E2E20546869732072657175657374204D555354206F6E6C79207265736F6C766520746F207031206F722070322E202055706461746573206D61646520627920746865207175657374696F6E2063726561746F7220766961207468652062756C6C6574696E20626F617264206174203078324635653336383463623146333138656335316230304564626133386437394163326330614139642073686F756C6420626520636F6E736964657265642E2C696E697469616C697A65723A393134333063616432643339373537363634393937313766613064363661373864383134653563352C6F6F5265717565737465723A326635653336383463623166333138656335316230306564626133386437396163326330616139642C6368696C645265717565737465723A656533616665333437643563373433313730343165323631386334393533346461663838376332342C6368696C64436861696E49643A313337 )
222 VotingV2.EncryptedVote( caller=[Sender] 0x4cd6ac17782d95dc7a8ee2106ff8de4a52984b01, roundId=10016, identifier=5945535F4F525F4E4F5F51554552590000000000000000000000000000000000, time=1730657300, ancillaryData=0x713A207469746C653A2057696C6C204F7363617220506961737472692077696E20746865204272617A696C69616E204772616E6420507269783F2C206465736372697074696F6E3A2054686973206D61726B65742077696C6C207265736F6C766520746F20E2809C596573E2809D206966204F7363617220506961737472692077696E73207468652032303234204272617A696C69616E204772616E642050726978207363686564756C656420666F72204E6F76656D62657220332C20323032342E204F74686572776973652C2074686973206D61726B65742077696C6C207265736F6C766520746F20E2809C4E6F2EE2809D0A0A4966207468652032303234204272617A696C69616E204772616E6420507269782069732063616E63656C6564206F722072657363686564756C656420746F20612064617465206166746572204E6F76656D6265722031372C20323032342C2074686973206D61726B65742077696C6C207265736F6C766520746F20E2809C4E6F2EE2809D0A0A546865207265736F6C7574696F6E20736F757263652077696C6C20626520746865206F6666696369616C20466F726D756C612031207765627369746520616E64206372656469626C652073706F727473206E657773207265706F7274696E672E2C207265735F646174613A2070313A20302C2070323A20312C2070333A20302E352E20576865726520703120636F72726573706F6E647320746F204E6F2C20703220746F205965732C20703320746F20756E6B6E6F776E2E20546869732072657175657374204D555354206F6E6C79207265736F6C766520746F207031206F722070322E202055706461746573206D61646520627920746865207175657374696F6E2063726561746F7220766961207468652062756C6C6574696E20626F617264206174203078324635653336383463623146333138656335316230304564626133386437394163326330614139642073686F756C6420626520636F6E736964657265642E2C696E697469616C697A65723A393134333063616432643339373537363634393937313766613064363661373864383134653563352C6F6F5265717565737465723A326635653336383463623166333138656335316230306564626133386437396163326330616139642C6368696C645265717565737465723A656533616665333437643563373433313730343165323631386334393533346461663838376332342C6368696C64436861696E49643A313337, encryptedVote=0xE0FAC80D3A0BB598B302C964C474BFDE0225D0E43C3DBD2B8D539F7373F9F03582119936CF8A38D6BFBF618AB2A4A402ADE28C4D2D913D6DC1B5206B8AAB209CD76076436492B555FA7DCC23C257960D6B48943EC666B62991D2C854AA857FC053F9CD7E05509E55393ACDFC92C21C7D11A374B70EDB5372F953D225B26A85C6E4839545E8AA7F615D28D580A6ABA59785DB14AC10A43E5F6110401C06D563BB078D638751E6CB1507FE247FE4B452E50963F0C561A60E26581BEBEB7C359A200DB6EAF35683FA46B2A49DAEDDF1F513A4F17842885F98EF94E5445341E0FC2DD20210ED92AAE7A45BFC671B14A0C9DE60AC362E92983CAE128F1271FFC37948F7420332E1EAE4EC6BA1CB4FBE0E43D9C4 )
223 VotingV2.UpdatedReward( voter=0x4c0deE7F...b5a00fF1d, newReward=483357149044503275, lastUpdateTime=1730845655 )
224 VotingV2.VoteCommitted( voter=0x4c0deE7F...b5a00fF1d, caller=[Sender] 0x4cd6ac17782d95dc7a8ee2106ff8de4a52984b01, roundId=10016, identifier=5945535F4F525F4E4F5F51554552590000000000000000000000000000000000, time=1730657296, ancillaryData=0x713A207469746C653A2057696C6C2047656F7267652052757373656C6C2077696E20746865204272617A696C69616E204772616E6420507269783F2C206465736372697074696F6E3A2054686973206D61726B65742077696C6C207265736F6C766520746F20E2809C596573E2809D2069662047656F7267652052757373656C6C2077696E73207468652032303234204272617A696C69616E204772616E642050726978207363686564756C656420666F72204E6F76656D62657220332C20323032342E204F74686572776973652C2074686973206D61726B65742077696C6C207265736F6C766520746F20E2809C4E6F2EE2809D0A0A4966207468652032303234204272617A696C69616E204772616E6420507269782069732063616E63656C6564206F722072657363686564756C656420746F20612064617465206166746572204E6F76656D6265722031372C20323032342C2074686973206D61726B65742077696C6C207265736F6C766520746F20E2809C4E6F2EE2809D0A0A546865207265736F6C7574696F6E20736F757263652077696C6C20626520746865206F6666696369616C20466F726D756C612031207765627369746520616E64206372656469626C652073706F727473206E657773207265706F7274696E672E2C207265735F646174613A2070313A20302C2070323A20312C2070333A20302E352E20576865726520703120636F72726573706F6E647320746F204E6F2C20703220746F205965732C20703320746F20756E6B6E6F776E2E20546869732072657175657374204D555354206F6E6C79207265736F6C766520746F207031206F722070322E202055706461746573206D61646520627920746865207175657374696F6E2063726561746F7220766961207468652062756C6C6574696E20626F617264206174203078324635653336383463623146333138656335316230304564626133386437394163326330614139642073686F756C6420626520636F6E736964657265642E2C696E697469616C697A65723A393134333063616432643339373537363634393937313766613064363661373864383134653563352C6F6F5265717565737465723A326635653336383463623166333138656335316230306564626133386437396163326330616139642C6368696C645265717565737465723A656533616665333437643563373433313730343165323631386334393533346461663838376332342C6368696C64436861696E49643A313337 )
225 VotingV2.EncryptedVote( caller=[Sender] 0x4cd6ac17782d95dc7a8ee2106ff8de4a52984b01, roundId=10016, identifier=5945535F4F525F4E4F5F51554552590000000000000000000000000000000000, time=1730657296, ancillaryData=0x713A207469746C653A2057696C6C2047656F7267652052757373656C6C2077696E20746865204272617A696C69616E204772616E6420507269783F2C206465736372697074696F6E3A2054686973206D61726B65742077696C6C207265736F6C766520746F20E2809C596573E2809D2069662047656F7267652052757373656C6C2077696E73207468652032303234204272617A696C69616E204772616E642050726978207363686564756C656420666F72204E6F76656D62657220332C20323032342E204F74686572776973652C2074686973206D61726B65742077696C6C207265736F6C766520746F20E2809C4E6F2EE2809D0A0A4966207468652032303234204272617A696C69616E204772616E6420507269782069732063616E63656C6564206F722072657363686564756C656420746F20612064617465206166746572204E6F76656D6265722031372C20323032342C2074686973206D61726B65742077696C6C207265736F6C766520746F20E2809C4E6F2EE2809D0A0A546865207265736F6C7574696F6E20736F757263652077696C6C20626520746865206F6666696369616C20466F726D756C612031207765627369746520616E64206372656469626C652073706F727473206E657773207265706F7274696E672E2C207265735F646174613A2070313A20302C2070323A20312C2070333A20302E352E20576865726520703120636F72726573706F6E647320746F204E6F2C20703220746F205965732C20703320746F20756E6B6E6F776E2E20546869732072657175657374204D555354206F6E6C79207265736F6C766520746F207031206F722070322E202055706461746573206D61646520627920746865207175657374696F6E2063726561746F7220766961207468652062756C6C6574696E20626F617264206174203078324635653336383463623146333138656335316230304564626133386437394163326330614139642073686F756C6420626520636F6E736964657265642E2C696E697469616C697A65723A393134333063616432643339373537363634393937313766613064363661373864383134653563352C6F6F5265717565737465723A326635653336383463623166333138656335316230306564626133386437396163326330616139642C6368696C645265717565737465723A656533616665333437643563373433313730343165323631386334393533346461663838376332342C6368696C64436861696E49643A313337, encryptedVote=0xB42D662653AAF2B86FB8B67319AACC2602BB27122B034DCDF5B24FC28A3B53E3D25199343E6D22951C9B581999E2F44151A81C13B72612966CDD48BC7AAC0E5C4AB3F0E056962ECEAD94C72F79C0915F9FA21D552799550FA1374C31C06290AF5C18B69170B7086337B1A10172FE6F09B2DDBED800C1B12E00360E087C884BB24D30B70E4F72334C871197D81229BD355A350DEC3E3F616ABF9367FDAC360DFA8E5011BA52674BAB3BBB2C6164A398C920455F7931CB2F958E424D89F2F94C47D249AEAF11E85DD98CB0A8447FEFF79BC7672A7A8055CF8541FD35051CD7DA0EB4B371A92C456A4F4B5A42907D2D4BD43A5595273F4ECB427D59DBAB6DBC71AF5C3767B3EF2B0EF1E54E486E87F92E1B33 )
226 VotingV2.UpdatedReward( voter=0x4c0deE7F...b5a00fF1d, newReward=483357149044503275, lastUpdateTime=1730845655 )
227 VotingV2.VoteCommitted( voter=0x4c0deE7F...b5a00fF1d, caller=[Sender] 0x4cd6ac17782d95dc7a8ee2106ff8de4a52984b01, roundId=10016, identifier=5945535F4F525F4E4F5F51554552590000000000000000000000000000000000, time=1730657642, ancillaryData=0x713A207469746C653A2057696C6C204D6178205665727374617070656E2077696E20746865204272617A696C69616E204772616E6420507269783F2C206465736372697074696F6E3A2054686973206D61726B65742077696C6C207265736F6C766520746F20E2809C596573E2809D206966204D6178205665727374617070656E2077696E73207468652032303234204272617A696C69616E204772616E642050726978207363686564756C656420666F72204E6F76656D62657220332C20323032342E204F74686572776973652C2074686973206D61726B65742077696C6C207265736F6C766520746F20E2809C4E6F2EE2809D0A0A4966207468652032303234204272617A696C69616E204772616E6420507269782069732063616E63656C6564206F722072657363686564756C656420746F20612064617465206166746572204E6F76656D6265722031372C20323032342C2074686973206D61726B65742077696C6C207265736F6C766520746F20E2809C4E6F2EE2809D0A0A546865207265736F6C7574696F6E20736F757263652077696C6C20626520746865206F6666696369616C20466F726D756C612031207765627369746520616E64206372656469626C652073706F727473206E657773207265706F7274696E672E2C207265735F646174613A2070313A20302C2070323A20312C2070333A20302E352E20576865726520703120636F72726573706F6E647320746F204E6F2C20703220746F205965732C20703320746F20756E6B6E6F776E2E20546869732072657175657374204D555354206F6E6C79207265736F6C766520746F207031206F722070322E202055706461746573206D61646520627920746865207175657374696F6E2063726561746F7220766961207468652062756C6C6574696E20626F617264206174203078324635653336383463623146333138656335316230304564626133386437394163326330614139642073686F756C6420626520636F6E736964657265642E2C696E697469616C697A65723A393134333063616432643339373537363634393937313766613064363661373864383134653563352C6F6F5265717565737465723A326635653336383463623166333138656335316230306564626133386437396163326330616139642C6368696C645265717565737465723A656533616665333437643563373433313730343165323631386334393533346461663838376332342C6368696C64436861696E49643A313337 )
228 VotingV2.EncryptedVote( caller=[Sender] 0x4cd6ac17782d95dc7a8ee2106ff8de4a52984b01, roundId=10016, identifier=5945535F4F525F4E4F5F51554552590000000000000000000000000000000000, time=1730657642, ancillaryData=0x713A207469746C653A2057696C6C204D6178205665727374617070656E2077696E20746865204272617A696C69616E204772616E6420507269783F2C206465736372697074696F6E3A2054686973206D61726B65742077696C6C207265736F6C766520746F20E2809C596573E2809D206966204D6178205665727374617070656E2077696E73207468652032303234204272617A696C69616E204772616E642050726978207363686564756C656420666F72204E6F76656D62657220332C20323032342E204F74686572776973652C2074686973206D61726B65742077696C6C207265736F6C766520746F20E2809C4E6F2EE2809D0A0A4966207468652032303234204272617A696C69616E204772616E6420507269782069732063616E63656C6564206F722072657363686564756C656420746F20612064617465206166746572204E6F76656D6265722031372C20323032342C2074686973206D61726B65742077696C6C207265736F6C766520746F20E2809C4E6F2EE2809D0A0A546865207265736F6C7574696F6E20736F757263652077696C6C20626520746865206F6666696369616C20466F726D756C612031207765627369746520616E64206372656469626C652073706F727473206E657773207265706F7274696E672E2C207265735F646174613A2070313A20302C2070323A20312C2070333A20302E352E20576865726520703120636F72726573706F6E647320746F204E6F2C20703220746F205965732C20703320746F20756E6B6E6F776E2E20546869732072657175657374204D555354206F6E6C79207265736F6C766520746F207031206F722070322E202055706461746573206D61646520627920746865207175657374696F6E2063726561746F7220766961207468652062756C6C6574696E20626F617264206174203078324635653336383463623146333138656335316230304564626133386437394163326330614139642073686F756C6420626520636F6E736964657265642E2C696E697469616C697A65723A393134333063616432643339373537363634393937313766613064363661373864383134653563352C6F6F5265717565737465723A326635653336383463623166333138656335316230306564626133386437396163326330616139642C6368696C645265717565737465723A656533616665333437643563373433313730343165323631386334393533346461663838376332342C6368696C64436861696E49643A313337, encryptedVote=0x22B2D0179157FD6ED88C06252A9DEF2B025ABF7936BD93E9C41DD0D9E0B97EF2B14837617799215AC185D70309E62E560A58913A9869D2DDA7EA249D82FE3DCFB308CD6B3D63B9067D682598CE23ED3E62DE066B9028E5B209C29E6625D059E684560120C5EC0BEAA1108D18E56FD25B4FE366380BC51111B8FDEAAB678A814BC1AA119A33C324D3E13B37F36B79A7CC8F7CBA15B97562AF39C44CD4186EC88385E353DF4AFD0BA4D39F4D753E079DD6FF16A384468FCD1C7D4B5F51E135CFB305B9FB248BD6059E00348211713A46DF76129C280914B0068AADB4A7744333357CEB6E059514F65043AF2CA042DA3E6582936EC971A6BF1DDA26D957ED934C11FF348C70DAEB10A744993A033D5D214F8A )

Account State Difference:

  Address   Before After State Difference Code
0x004395ed...f93Bd34ac
0x4CD6ac17...a52984B01
0.228429868860994741 Eth
Nonce: 61
0.218615649963730549 Eth
Nonce: 62
0.009814218897264192
(beaverbuild)
19.981295890338969176 Eth19.982910306103263788 Eth0.001614415764294612

Execution Trace

VotingV2.multicall( data=[FtMkdFlFU19PUl9OT19RVUVSWQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGcpGsUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoCMMZodQEUbjmy6t+r8SVEEY50B3op/0QmnXM11Qnbq1AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAByAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGQXE6IHRpdGxlOiBXaWxsIEhhcnJpcyBsZWFkIGluIFJDUCBieSAwLTAuNCBvbiBOb3YgND8sIGRlc2NyaXB0aW9uOiBUaGlzIGlzIGEgbWFya2V0IG9uIHRoZSBSQ1AgUG9sbGluZyBBdmVyYWdlIG1hcmdpbiBiZXR3ZWVuIERvbmFsZCBUcnVtcCBhbmQgS2FtYWxhIEhhcnJpcyBhcyBvZiBOb3ZlbWJlciA0LCAyMDI0LCAxMjowMCBQTSBFVC4gVGhlIHNwcmVhZCByZWZlcmVuY2VkIGluIHRoZSBmaXJzdCB0YWJsZSBvbiB0aGUgIjIwMjQgR2VuZXJhbCBFbGVjdGlvbjogVHJ1bXAgdnMuIEhhcnJpcyIgcGFnZSBhdCBodHRwczovL3d3dy5yZWFsY2xlYXJwb2xsaW5nLmNvbS9wb2xscy9wcmVzaWRlbnQvZ2VuZXJhbC8yMDI0L3RydW1wLXZzLWhhcnJpcyB3aWxsIGJlIHVzZWQgdG8gcmVzb2x2ZSB0aGlzIG1hcmtldC4KClRoaXMgbWFya2V0IHdpbGwgcmVzb2x2ZSB0byAnWWVzJyBpZiBiZXR3ZWVuIEhhcnJpcyAwLjAgKGluY2x1c2l2ZSkgYW5kIEhhcnJpcyArMC40IChpbmNsdXNpdmUpIHBlcmNlbnRhZ2UgcG9pbnRzLiBPdGhlcndpc2UsIHRoaXMgbWFya2V0IHdpbGwgcmVzb2x2ZSB0byAnTm8nLgoKVGhlIFJDUCBQb2xsaW5nIEF2ZXJhZ2Ugd2lsbCBiZSBjaGVja2VkIG9uIE5vdmVtYmVyIDQsIDEyOjAwIFBNIEVULgoKUGxlYXNlIG5vdGUsIHRoaXMgbWFya2V0IHJlZmVycyBzcGVjaWZpY2FsbHkgdG8gdGhlIG1hcmdpbiBmb3IgUkNQIHBvbGxpbmcgYXZlcmFnZSBhcyBwcmVzZW50ZWQgaW4gdGhlIGFmb3JlbWVudGlvbmVkIGNoYXJ0IGluIHRoZSBjb2x1bW4gdGl0bGVkICdTcHJlYWQnLiBUaGlzIGluY2x1ZGVzIGFueSBhZGp1c3RtZW50cyBvciBtZXRob2RvbG9neSBjaGFuZ2VzIG1hZGUgYnkgUkNQIGluIHRoZWlyIGNhbGN1bGF0aW9uIG9mIHRoZSBwb2xsaW5nIGF2ZXJhZ2Ugb3IgdGhlIGRhdGUgcmFuZ2UgdXNlZC4KCklmIHRoZSBSQ1AgUG9sbGluZyBBdmVyYWdlIG1hcmdpbiBkYXRhIGJldHdlZW4gS2FtYWxhIEhhcnJpcyBhbmQgRG9uYWxkIFRydW1wIGlzIG5vdCBhdmFpbGFibGUgYnkgTm92ZW1iZXIgOCwgMjAyNCwgMTE6NTkgUE0gRVQsIGFub3RoZXIgY3JlZGlibGUgc291cmNlIG9mIHBvbGxpbmcgZGF0YSBhcyBvZiBOb3ZlbWJlciA0LCAxMjowMCBQTSBFVCB3aWxsIGJlIHVzZWQgZm9yIG1hcmtldCByZXNvbHV0aW9uLiwgcmVzX2RhdGE6IHAxOiAwLCBwMjogMSwgcDM6IDAuNS4gV2hlcmUgcDEgY29ycmVzcG9uZHMgdG8gTm8sIHAyIHRvIFllcywgcDMgdG8gdW5rbm93bi4gVGhpcyByZXF1ZXN0IE1VU1Qgb25seSByZXNvbHZlIHRvIHAxIG9yIHAyLiAgVXBkYXRlcyBtYWRlIGJ5IHRoZSBxdWVzdGlvbiBjcmVhdG9yIHZpYSB0aGUgYnVsbGV0aW4gYm9hcmQgYXQgMHgyRjVlMzY4NGNiMUYzMThlYzUxYjAwRWRiYTM4ZDc5QWMyYzBhQTlkIHNob3VsZCBiZSBjb25zaWRlcmVkLixpbml0aWFsaXplcjo5MTQzMGNhZDJkMzk3NTc2NjQ5OTcxN2ZhMGQ2NmE3OGQ4MTRlNWM1LG9vUmVxdWVzdGVyOjJmNWUzNjg0Y2IxZjMxOGVjNTFiMDBlZGJhMzhkNzlhYzJjMGFhOWQsY2hpbGRSZXF1ZXN0ZXI6ZWUzYWZlMzQ3ZDVjNzQzMTcwNDFlMjYxOGM0OTUzNGRhZjg4N2MyNCxjaGlsZENoYWluSWQ6MTM3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADBcupaRoyOzJeJOqdLeyH8mwLDyP+juZlfaRgBpmF+Ov/jc55VO43AFrBV9VFzKaM+RHjUUOldiyNsCKl/FMYnBdoKBg7PKFKinY+ebeCSHx/IZK1taYxG5WtqUuQ9O9+uAH8gZAcKiIrGlOhTbwDxQlkCKIulzb2eYtv46Nu4K0XHXxccW3UTT9Ox0Wa7nEsAzi+hoMb2KRCr0Dbe5zH/nxxFk68tWqC03N1NfBVC1WS/BH2URUDG11BY/Z4Sn694tQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=, FtMkdFlFU19PUl9OT19RVUVSWQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGcoXs8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAp+gLj3tjtvI59slxE8jkYDhfM6xoTQTmx1K1FtuIhqAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFcXE6IHRpdGxlOiBXaWxsIFRydW1wIHNheSAic2tpYmlkaSIgYmVmb3JlIHRoZSBlbGVjdGlvbj8sIGRlc2NyaXB0aW9uOiBUaGlzIG1hcmtldCB3aWxsIHJlc29sdmUgdG8g4oCcWWVz4oCdIGlmIERvbmFsZCBUcnVtcCBwdWJsaWNseSBtZW50aW9ucyB0aGUgd29yZCAic2tpYmlkaSIgYmV0d2VlbiBTZXB0ZW1iZXIgMTcgYW5kIE5vdmVtYmVyIDQsIDIwMjQsIDExOjU5IFBNIEVULiBPdGhlcndpc2UsIHRoaXMgbWFya2V0IHdpbGwgcmVzb2x2ZSB0byDigJxOb+KAnS4KCkEg4oCYbWVudGlvbuKAmSBpbmNsdWRlcyB0aGUgZm9sbG93aW5nOgoKLUEgdmVyYmFsIHVzYWdlIG9mIHRoZSB3b3JkKHMpICJza2liaWRpIi4KLUFueSB3cml0dGVuIHVzYWdlIG9mIHRoZSB3b3JkKHMpICJza2liaWRpIiBwdWJsaXNoZWQgdGhyb3VnaCBUcnVtcCdzIHNvY2lhbCBtZWRpYSBvciBvdGhlciBvZmZpY2lhbCBjb21tdW5pY2F0aW9uIGNoYW5uZWxzIHJlZ2FyZGxlc3Mgb2YgY2FwaXRhbGl6YXRpb24uCgpBbnkgdXNhZ2Ugb2YgdGhlIHdvcmQgcmVnYXJkbGVzcyBvZiBjb250ZXh0IHdpbGwgY291bnQgdG93YXJkIHRoZSByZXNvbHV0aW9uIG9mIHRoaXMgbWFya2V0LgoKUGx1cmFsaXphdGlvbi9wb3NzZXNzaXZlIG9mIHRoZSB3b3JkIHdpbGwgY291bnQgdG93YXJkIHRoZSByZXNvbHV0aW9uIG9mIHRoaXMgbWFya2V0LCBob3dldmVyIG90aGVyIGZvcm1zIHdpbGwgTk9UIGNvdW50LgoKVGhlIHJlc29sdXRpb24gc291cmNlIGZvciB0aGlzIG1hcmtldCB3aWxsIGJlIGZvb3RhZ2Ugb2YgRG9uYWxkIFRydW1wIHRha2VuIHdpdGhpbiB0aGUgbWVudGlvbmVkIHRpbWVmcmFtZSwgYXMgd2VsbCBhcyBvZmZpY2lhbCBjb21tdW5pY2F0aW9ucyBmcm9tIERvbmFsZCBUcnVtcC4gcmVzX2RhdGE6IHAxOiAwLCBwMjogMSwgcDM6IDAuNS4gV2hlcmUgcDEgY29ycmVzcG9uZHMgdG8gTm8sIHAyIHRvIFllcywgcDMgdG8gdW5rbm93bi81MC01MC4gVXBkYXRlcyBtYWRlIGJ5IHRoZSBxdWVzdGlvbiBjcmVhdG9yIHZpYSB0aGUgYnVsbGV0aW4gYm9hcmQgYXQgMHg2QTlEMjIyNjE2QzkwRmNBNTc1NGNkMTMzM2NGRDliN2ZiNmE0Rjc0IGFzIGRlc2NyaWJlZCBieSBodHRwczovL3BvbHlnb25zY2FuLmNvbS90eC8weGExNGYwMWIxMTVjNDkxMzYyNGZjM2Y1MDhmOTYwZjRkZWEyNTI3NThlNzNjMjhmNWYwN2Y4ZTE5ZDdiY2EwNjYgc2hvdWxkIGJlIGNvbnNpZGVyZWQuLGluaXRpYWxpemVyOjkxNDMwY2FkMmQzOTc1NzY2NDk5NzE3ZmEwZDY2YTc4ZDgxNGU1YzUsb29SZXF1ZXN0ZXI6NmE5ZDIyMjYxNmM5MGZjYTU3NTRjZDEzMzNjZmQ5YjdmYjZhNGY3NCxjaGlsZFJlcXVlc3RlcjplZTNhZmUzNDdkNWM3NDMxNzA0MWUyNjE4YzQ5NTM0ZGFmODg3YzI0LGNoaWxkQ2hhaW5JZDoxMzcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEUwUVK4cpWFJHs05TEPXwTEDDcxQEsGYUqmwfbuknAglijRDnSF9sgg4QU9DDw35g0aH9eASxXzTVIaEG/oskTyfJU4Gr+dpJHHV8rLQ2C/pmIgRLJmwE6dBZBlogjSD5zLPb6rDbBLk/YI1KxyKVZyExBTT3ZC2s46SQKBonvOIXYb136pL0CRFdWCL1qcasGnVRJg1t1IzxLPJW1iyKLQc+SP/B00ACdr3RFqRTMzjYjM+GjYjibtOw34y2UgP6Z1S3TNPrOZSiW7iv147KXwlbBHhYb5TTtPBIUFmbqux65h1MeS2/XGSR9ISvxmgafpDxeeosBDwDoPRA80jw/wVGe1klI2gaepgChaGV7CDUQAAAAAAAAAAAAAAAAAAAA==, FtMkdFlFU19PUl9OT19RVUVSWQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGcnv2YAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoJi4Z+4OVA61iI+A/OwzF0y3JgvQl1GlgThIc0T64gZ2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADkXE6IHRpdGxlOiBXaWxsIFNlcmdpbyBQZXJleiB3aW4gdGhlIEJyYXppbGlhbiBHcmFuZCBQcml4PywgZGVzY3JpcHRpb246IFRoaXMgbWFya2V0IHdpbGwgcmVzb2x2ZSB0byDigJxZZXPigJ0gaWYgU2VyZ2lvIFBlcmV6IHdpbnMgdGhlIDIwMjQgQnJhemlsaWFuIEdyYW5kIFByaXggc2NoZWR1bGVkIGZvciBOb3ZlbWJlciAzLCAyMDI0LiBPdGhlcndpc2UsIHRoaXMgbWFya2V0IHdpbGwgcmVzb2x2ZSB0byDigJxOby7igJ0KCklmIHRoZSAyMDI0IEJyYXppbGlhbiBHcmFuZCBQcml4IGlzIGNhbmNlbGVkIG9yIHJlc2NoZWR1bGVkIHRvIGEgZGF0ZSBhZnRlciBOb3ZlbWJlciAxNywgMjAyNCwgdGhpcyBtYXJrZXQgd2lsbCByZXNvbHZlIHRvIOKAnE5vLuKAnQoKVGhlIHJlc29sdXRpb24gc291cmNlIHdpbGwgYmUgdGhlIG9mZmljaWFsIEZvcm11bGEgMSB3ZWJzaXRlIGFuZCBjcmVkaWJsZSBzcG9ydHMgbmV3cyByZXBvcnRpbmcuLCByZXNfZGF0YTogcDE6IDAsIHAyOiAxLCBwMzogMC41LiBXaGVyZSBwMSBjb3JyZXNwb25kcyB0byBObywgcDIgdG8gWWVzLCBwMyB0byB1bmtub3duLiBUaGlzIHJlcXVlc3QgTVVTVCBvbmx5IHJlc29sdmUgdG8gcDEgb3IgcDIuICBVcGRhdGVzIG1hZGUgYnkgdGhlIHF1ZXN0aW9uIGNyZWF0b3IgdmlhIHRoZSBidWxsZXRpbiBib2FyZCBhdCAweDJGNWUzNjg0Y2IxRjMxOGVjNTFiMDBFZGJhMzhkNzlBYzJjMGFBOWQgc2hvdWxkIGJlIGNvbnNpZGVyZWQuLGluaXRpYWxpemVyOjkxNDMwY2FkMmQzOTc1NzY2NDk5NzE3ZmEwZDY2YTc4ZDgxNGU1YzUsb29SZXF1ZXN0ZXI6MmY1ZTM2ODRjYjFmMzE4ZWM1MWIwMGVkYmEzOGQ3OWFjMmMwYWE5ZCxjaGlsZFJlcXVlc3RlcjplZTNhZmUzNDdkNWM3NDMxNzA0MWUyNjE4YzQ5NTM0ZGFmODg3YzI0LGNoaWxkQ2hhaW5JZDoxMzcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEcfjQdT2GDMzpFTZbBcLzGoDXMDXANPusHeRR+czZB8r7ZLEQupVenjrOZ8V+oyY7Fk7JCotK/AaXZg3E7jwsOJFHc5PzfzVI+m5qlWxs+YvN2FzfqrBXCIHvO59CdWBIJkGuRayTsocI8vijgcTglHS7YJeL49ZS8T1F/act+bVcphTweGfk3XxKos3eUn2zfnBJqO6/bneINOi5AwaiDjEwFtN+9CD8rARRUG4/s3Pwt69o641+qj2psEDg3ScuEMlv/Q/Ny2EIyDPg9FZteb4N5nagJ7xJe6vEqt7kfR2nJLPGnrFPoeztyDNtCV0AIAkIfPzi1wuDgZHIECTG7fhSvdUsBbCPaFmPx2oV2cFHwAAAAAAAAAAAAAAAAAAAA==, FtMkdFlFU19PUl9OT19RVUVSWQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGcmvoEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoISI9053fHBFnTb/NmHTTfQIrPgCT5P54oKVhHBGTqDtAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAByAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGXnE6IHRpdGxlOiBXaWxsIFRydW1wIHNheSAidm90ZSIgMzAgb3IgbW9yZSB0aW1lcyBkdXJpbmcgVmlyZ2luaWEgcmFsbHkgb24gTm92IDI/LCBkZXNjcmlwdGlvbjogRG9uYWxkIFRydW1wIGhhcyBzY2hlZHVsZWQgYSByYWxseSBvbiBOb3ZlbWJlciAyIGluIFNhbGVtLCBWaXJnaW5pYSAoc2VlOiBodHRwczovL2V2ZW50LmRvbmFsZGp0cnVtcC5jb20vZXZlbnRzL3ByZXNpZGVudC1kb25hbGQtai10cnVtcC10by1ob2xkLWEtcmFsbHktaW4tc2FsZW0tdmlyZ2luaWEpLgoKVGhpcyBtYXJrZXQgd2lsbCByZXNvbHZlIHRvICJZZXMiIGlmIFRydW1wIHNheXMgInZvdGUiIDMwIG9yIG1vcmUgdGltZXMgZHVyaW5nIHRoZWlyIGFwcGVhcmFuY2UgYXQgdGhpcyBldmVudC4gT3RoZXJ3aXNlLCB0aGUgbWFya2V0IHdpbGwgcmVzb2x2ZSB0byAiTm8iLgoKQW55IHVzYWdlIG9mIHRoZSB0ZXJtIHJlZ2FyZGxlc3Mgb2YgY29udGV4dCB3aWxsIGNvdW50IHRvd2FyZCB0aGUgcmVzb2x1dGlvbiBvZiB0aGlzIG1hcmtldC4KClBsdXJhbGl6YXRpb24vcG9zc2Vzc2l2ZSBvZiB0aGUgdGVybSB3aWxsIGNvdW50IHRvd2FyZCB0aGUgcmVzb2x1dGlvbiBvZiB0aGlzIG1hcmtldCwgaG93ZXZlciBvdGhlciBmb3JtcyB3aWxsIE5PVCBjb3VudC4KCkNvbXBvdW5kIHdvcmRzIHdpbGwgY291bnQgYXMgbG9uZyBhcyAidm90ZSIgaXMgcGFydCBvZiB0aGUgY29tcG91bmQgd29yZCBhbmQgcmVmZXJlbmNlcyB0aGUgbWVhbmluZyB3aGljaCByZWZlcnMgdG8gYSBmb3JtYWwgaW5kaWNhdGlvbiBvZiBhIGNob2ljZSBiZXR3ZWVuIHR3byBvciBtb3JlIGNhbmRpZGF0ZXMgb3IgY291cnNlcyBvZiBhY3Rpb24sIGV4cHJlc3NlZCB0eXBpY2FsbHkgdGhyb3VnaCBhIGJhbGxvdCBvciBhIHNob3cgb2YgaGFuZHMgb3IgYnkgdm9pY2UuCgpJZiB0aGlzIGNhbmRpZGF0ZSBkb2VzIG5vdCBhcHBlYXIgYXQgdGhpcyBldmVudCwgb3IgaWYgdGhlIGV2ZW50IGlzIG90aGVyd2lzZSBjYW5jZWxsZWQgb3IgZGVsYXllZCBiZXlvbmQgTm92ZW1iZXIgMiwgdGhpcyBtYXJrZXQgd2lsbCByZXNvbHZlIHRvICJObyIuCgpUaGUgcmVzb2x1dGlvbiBzb3VyY2Ugd2lsbCBiZSB0aGUgdmlkZW8gb2YgdGhlIHNwZWVjaC4gcmVzX2RhdGE6IHAxOiAwLCBwMjogMSwgcDM6IDAuNS4gV2hlcmUgcDEgY29ycmVzcG9uZHMgdG8gTm8sIHAyIHRvIFllcywgcDMgdG8gdW5rbm93bi81MC01MC4gVXBkYXRlcyBtYWRlIGJ5IHRoZSBxdWVzdGlvbiBjcmVhdG9yIHZpYSB0aGUgYnVsbGV0aW4gYm9hcmQgYXQgMHg2QTlEMjIyNjE2QzkwRmNBNTc1NGNkMTMzM2NGRDliN2ZiNmE0Rjc0IGFzIGRlc2NyaWJlZCBieSBodHRwczovL3BvbHlnb25zY2FuLmNvbS90eC8weGExNGYwMWIxMTVjNDkxMzYyNGZjM2Y1MDhmOTYwZjRkZWEyNTI3NThlNzNjMjhmNWYwN2Y4ZTE5ZDdiY2EwNjYgc2hvdWxkIGJlIGNvbnNpZGVyZWQuLGluaXRpYWxpemVyOjkxNDMwY2FkMmQzOTc1NzY2NDk5NzE3ZmEwZDY2YTc4ZDgxNGU1YzUsb29SZXF1ZXN0ZXI6NmE5ZDIyMjYxNmM5MGZjYTU3NTRjZDEzMzNjZmQ5YjdmYjZhNGY3NCxjaGlsZFJlcXVlc3RlcjplZTNhZmUzNDdkNWM3NDMxNzA0MWUyNjE4YzQ5NTM0ZGFmODg3YzI0LGNoaWxkQ2hhaW5JZDoxMzcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADRsgXX/bxZ1POlHO2VP8G7TAJVYZkvkX51+nJoCdRyqIsSIxUivvGr5NZ6DD9WQ7HUrOyfXltkxvOOzzXbepbsWvBqiglyYblBR8fT5R0bwHEW9ty8KCiooAqa7lzWR3LLo3C8DN7Dq3hpS0GXRV/E3mEKqLT+uvpp08Os85XJS5FAtlkRv4UtgLdlHZJWa5PtfB124zD1E/YdEBlM6snijTjUuOpPpgkeybu+QYvK5JGxI0bU1T90ffYahuprxEuwh1cvIPMLGcitXK6tT2gmBZcAAAAAAAAAAAAAAAAAAAA=, FtMkdFlFU19PUl9OT19RVUVSWQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGcnE9QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoFOIT05Jfj9CshTCw7BUUNP4FI0GdFgs7D3NZrVASJ7rAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF/nE6IHRpdGxlOiBXaWxsIFRydW1wIHNheSAidm90ZSIgMjUgb3IgbW9yZSBkdXJpbmcgR3JlZW5zYm9ybywgTkMgcmFsbHk/LCBkZXNjcmlwdGlvbjogRG9uYWxkIFRydW1wIGhhcyBzY2hlZHVsZWQgYSByYWxseSBvbiBOb3ZlbWJlciAyIGluIEdyZWVuc2Jvcm8sIE5vcnRoIENhcm9saW5hIChzZWU6IGh0dHBzOi8vZXZlbnQuZG9uYWxkanRydW1wLmNvbS9ldmVudHMvcHJlc2lkZW50LWRvbmFsZC1qLXRydW1wLXRvLWhvbGQtYS1yYWxseS1pbi1ncmVlbnNib3JvLW5jKS4KClRoaXMgbWFya2V0IHdpbGwgcmVzb2x2ZSB0byAiWWVzIiBpZiBUcnVtcCBzYXlzICJ2b3RlIiAyNSBvciBtb3JlIHRpbWVzIGR1cmluZyB0aGVpciBhcHBlYXJhbmNlIGF0IHRoaXMgZXZlbnQuIE90aGVyd2lzZSwgdGhlIG1hcmtldCB3aWxsIHJlc29sdmUgdG8gIk5vIi4KCkFueSB1c2FnZSBvZiB0aGUgdGVybSByZWdhcmRsZXNzIG9mIGNvbnRleHQgd2lsbCBjb3VudCB0b3dhcmQgdGhlIHJlc29sdXRpb24gb2YgdGhpcyBtYXJrZXQuCgpQbHVyYWxpemF0aW9uL3Bvc3Nlc3NpdmUgb2YgdGhlIHRlcm0gd2lsbCBjb3VudCB0b3dhcmQgdGhlIHJlc29sdXRpb24gb2YgdGhpcyBtYXJrZXQsIGhvd2V2ZXIgb3RoZXIgZm9ybXMgd2lsbCBOT1QgY291bnQuCgpDb21wb3VuZCB3b3JkcyB3aWxsIGNvdW50IGFzIGxvbmcgYXMgInZvdGUiIGlzIHBhcnQgb2YgdGhlIGNvbXBvdW5kIHdvcmQgYW5kIHJlZmVyZW5jZXMgdGhlIG1lYW5pbmcgd2hpY2ggcmVmZXJzIHRvIGEgZm9ybWFsIGV4cHJlc3Npb24gb2YgY2hvaWNlIG9yIG9waW5pb24gaW4gYW4gZWxlY3Rpb24uCgpJZiB0aGlzIGNhbmRpZGF0ZSBkb2VzIG5vdCBhcHBlYXIgYXQgdGhpcyBldmVudCwgb3IgaWYgdGhlIGV2ZW50IGlzIG90aGVyd2lzZSBjYW5jZWxsZWQgb3IgZGVsYXllZCBiZXlvbmQgTm92ZW1iZXIgMiwgdGhpcyBtYXJrZXQgd2lsbCByZXNvbHZlIHRvICJObyIuCgpUaGUgcmVzb2x1dGlvbiBzb3VyY2Ugd2lsbCBiZSB0aGUgdmlkZW8gb2YgdGhlIHNwZWVjaC4gcmVzX2RhdGE6IHAxOiAwLCBwMjogMSwgcDM6IDAuNS4gV2hlcmUgcDEgY29ycmVzcG9uZHMgdG8gTm8sIHAyIHRvIFllcywgcDMgdG8gdW5rbm93bi81MC01MC4gVXBkYXRlcyBtYWRlIGJ5IHRoZSBxdWVzdGlvbiBjcmVhdG9yIHZpYSB0aGUgYnVsbGV0aW4gYm9hcmQgYXQgMHg2QTlEMjIyNjE2QzkwRmNBNTc1NGNkMTMzM2NGRDliN2ZiNmE0Rjc0IGFzIGRlc2NyaWJlZCBieSBodHRwczovL3BvbHlnb25zY2FuLmNvbS90eC8weGExNGYwMWIxMTVjNDkxMzYyNGZjM2Y1MDhmOTYwZjRkZWEyNTI3NThlNzNjMjhmNWYwN2Y4ZTE5ZDdiY2EwNjYgc2hvdWxkIGJlIGNvbnNpZGVyZWQuLGluaXRpYWxpemVyOjkxNDMwY2FkMmQzOTc1NzY2NDk5NzE3ZmEwZDY2YTc4ZDgxNGU1YzUsb29SZXF1ZXN0ZXI6NmE5ZDIyMjYxNmM5MGZjYTU3NTRjZDEzMzNjZmQ5YjdmYjZhNGY3NCxjaGlsZFJlcXVlc3RlcjplZTNhZmUzNDdkNWM3NDMxNzA0MWUyNjE4YzQ5NTM0ZGFmODg3YzI0LGNoaWxkQ2hhaW5JZDoxMzcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADRYkcf0lOWR00eS/gyMKVWFwJwQ7kYn1ygnBk+8sDKLsF7cUXGVBsl8lST77f9qYQ4ahRO7CIoOXPkY+Nt2QnbKGG19IWnWcnVs5guct1kLEpInBbPuQgxGSwwtPW+Qr3w82odjy9cEE671fytc59MvENPkiadOj5kjrWBvS+fIXTSbiVXMCw+eY9L8Bz0Hubu69F/lIXqaL4Idscl+dQqryyGW9jPm+nYmtCJercOO8jUQ0KXjoau8dc3O970rd0VyTd9jBbg/+135kOmrwV24cwAAAAAAAAAAAAAAAAAAAA=, FtMkdFlFU19PUl9OT19RVUVSWQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGcnJJ4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoB8IZGNJaA/hYIPLdejffmXi6eO8AOp/rEicKs/dUAOmAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEBnE6IHRpdGxlOiBCYXJyaWF1bHQgdnMuIFN0b2x0emZ1cywgZGVzY3JpcHRpb246IFRoaXMgaXMgYSBtYXJrZXQgb24gd2hldGhlciBNYXJjLUFuZHJlIEJhcnJpYXVsdCBvciBEdXN0aW4gU3RvbHR6ZnVzIHdpbGwgd2luIHRoZWlyIGJvdXQuCgpJZiBNYXJjLUFuZHJlIEJhcnJpYXVsdCBpcyBkZWNsYXJlZCB0aGUgd2lubmVyIG9mIHRoaXMgYm91dCwgdGhpcyBtYXJrZXQgd2lsbCByZXNvbHZlIHRvIOKAnEJhcnJpYXVsdC7igJ0gSWYgRHVzdGluIFN0b2x0emZ1cyBpcyBkZWNsYXJlZCB0aGUgd2lubmVyIG9mIHRoaXMgYm91dCwgdGhpcyBtYXJrZXQgd2lsbCByZXNvbHZlIHRvIOKAnFN0b2x0emZ1c+KAnS4KCklmIHRoaXMgZmlnaHQgaXMgZGVjbGFyZWQgYSBkcmF3LCBvciBpZiBmb3IgYW55IHJlYXNvbiB0aGUgbWF0Y2ggaXMgbm90IHNjb3JlZCwgcG9zdHBvbmVkIGFmdGVyIE5vdmVtYmVyIDE2LCAyMDI0LCAxMTo1OSBQTSBFVCwgb3IgY2FuY2VsZWQsIHRoaXMgbWFya2V0IHdpbGwgcmVzb2x2ZSA1MC01MC4gcmVzX2RhdGE6IHAxOiAwLCBwMjogMSwgcDM6IDAuNS4gV2hlcmUgcDEgY29ycmVzcG9uZHMgdG8gTm8sIHAyIHRvIFllcywgcDMgdG8gdW5rbm93bi81MC01MC4gVXBkYXRlcyBtYWRlIGJ5IHRoZSBxdWVzdGlvbiBjcmVhdG9yIHZpYSB0aGUgYnVsbGV0aW4gYm9hcmQgYXQgMHg2QTlEMjIyNjE2QzkwRmNBNTc1NGNkMTMzM2NGRDliN2ZiNmE0Rjc0IGFzIGRlc2NyaWJlZCBieSBodHRwczovL3BvbHlnb25zY2FuLmNvbS90eC8weGExNGYwMWIxMTVjNDkxMzYyNGZjM2Y1MDhmOTYwZjRkZWEyNTI3NThlNzNjMjhmNWYwN2Y4ZTE5ZDdiY2EwNjYgc2hvdWxkIGJlIGNvbnNpZGVyZWQuLGluaXRpYWxpemVyOjkxNDMwY2FkMmQzOTc1NzY2NDk5NzE3ZmEwZDY2YTc4ZDgxNGU1YzUsb29SZXF1ZXN0ZXI6NmE5ZDIyMjYxNmM5MGZjYTU3NTRjZDEzMzNjZmQ5YjdmYjZhNGY3NCxjaGlsZFJlcXVlc3RlcjplZTNhZmUzNDdkNWM3NDMxNzA0MWUyNjE4YzQ5NTM0ZGFmODg3YzI0LGNoaWxkQ2hhaW5JZDoxMzcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADBGz5dFFkbWZd2HxLmkNMkTwMVICJ2AlQkULkqRWGMu2Ox1nmSkR4Mx0eDS3nfa6FHi3qtdm5rvn9v89XOe4B/bEcFoLkZDOHxUD06f3048XRFSPYlKXGIpZdV3up4PnTDYpaJySaH0JjzvH8HY6jLIYukmVQarOH+2BRhDj5G4XPgWv3z5D26Um4VGERoPvRtUujtcwVGq08N7MlrcqBNNrRiiDDaNcxDpW0hcRIuA5bbvnjnUJZM08Nczp03Fdsk6gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=, FtMkdFlFU19PUl9OT19RVUVSWQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGcnr70AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoMMDrVjBJ7VKUlOMhjbNH+HFw6Sebvo8eXz8bKrDOTxMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADkXE6IHRpdGxlOiBXaWxsIENhcmxvcyBTYWlueiB3aW4gdGhlIEJyYXppbGlhbiBHcmFuZCBQcml4PywgZGVzY3JpcHRpb246IFRoaXMgbWFya2V0IHdpbGwgcmVzb2x2ZSB0byDigJxZZXPigJ0gaWYgQ2FybG9zIFNhaW56IHdpbnMgdGhlIDIwMjQgQnJhemlsaWFuIEdyYW5kIFByaXggc2NoZWR1bGVkIGZvciBOb3ZlbWJlciAzLCAyMDI0LiBPdGhlcndpc2UsIHRoaXMgbWFya2V0IHdpbGwgcmVzb2x2ZSB0byDigJxOby7igJ0KCklmIHRoZSAyMDI0IEJyYXppbGlhbiBHcmFuZCBQcml4IGlzIGNhbmNlbGVkIG9yIHJlc2NoZWR1bGVkIHRvIGEgZGF0ZSBhZnRlciBOb3ZlbWJlciAxNywgMjAyNCwgdGhpcyBtYXJrZXQgd2lsbCByZXNvbHZlIHRvIOKAnE5vLuKAnQoKVGhlIHJlc29sdXRpb24gc291cmNlIHdpbGwgYmUgdGhlIG9mZmljaWFsIEZvcm11bGEgMSB3ZWJzaXRlIGFuZCBjcmVkaWJsZSBzcG9ydHMgbmV3cyByZXBvcnRpbmcuLCByZXNfZGF0YTogcDE6IDAsIHAyOiAxLCBwMzogMC41LiBXaGVyZSBwMSBjb3JyZXNwb25kcyB0byBObywgcDIgdG8gWWVzLCBwMyB0byB1bmtub3duLiBUaGlzIHJlcXVlc3QgTVVTVCBvbmx5IHJlc29sdmUgdG8gcDEgb3IgcDIuICBVcGRhdGVzIG1hZGUgYnkgdGhlIHF1ZXN0aW9uIGNyZWF0b3IgdmlhIHRoZSBidWxsZXRpbiBib2FyZCBhdCAweDJGNWUzNjg0Y2IxRjMxOGVjNTFiMDBFZGJhMzhkNzlBYzJjMGFBOWQgc2hvdWxkIGJlIGNvbnNpZGVyZWQuLGluaXRpYWxpemVyOjkxNDMwY2FkMmQzOTc1NzY2NDk5NzE3ZmEwZDY2YTc4ZDgxNGU1YzUsb29SZXF1ZXN0ZXI6MmY1ZTM2ODRjYjFmMzE4ZWM1MWIwMGVkYmEzOGQ3OWFjMmMwYWE5ZCxjaGlsZFJlcXVlc3RlcjplZTNhZmUzNDdkNWM3NDMxNzA0MWUyNjE4YzQ5NTM0ZGFmODg3YzI0LGNoaWxkQ2hhaW5JZDoxMzcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABERDyoDWqq9ghV51aAjBEd/gCAOsTZqSEDJv34001ff9fSD34mZ1ezz9Gjcbo935XV4xma4DZzjZvmoETH4siX0r6skwiuXS3f+rehI/sd8a5FcQMpLy2gKzoXEs0P9AyXGtJTkSO15NxUtSD2ma59wGVh+58YsEPha7BHVpciClrkFX4kyhag+iMjfo7p+VisTlCenWeGTA+o/ORxv+UxlVBSIFeg2UPddWLuOiGbtO+BEZbTgbeQnSxm9mKEKFCd/XKLeKwwqvO/ARu8obcRI77C49Tic0gxLbu7/R/rFnhEuVMdQ+xivqAOABYpKbi/Bs4yvDGI/1hJq/rGSp8tG1Exn5PJrnBEY3q4nrtFYuLpgAAAAAAAAAAAAAAAAAAAA==, FtMkdFlFU19PUl9OT19RVUVSWQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGcnvAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoF5hADecaP/aM70A4VrEKUNsMSEzxd6Ylv9RVJWoJJqpAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADkXE6IHRpdGxlOiBXaWxsIFNlcmdpbyBQZXJleiB3aW4gdGhlIEJyYXppbGlhbiBHcmFuZCBQcml4PywgZGVzY3JpcHRpb246IFRoaXMgbWFya2V0IHdpbGwgcmVzb2x2ZSB0byDigJxZZXPigJ0gaWYgU2VyZ2lvIFBlcmV6IHdpbnMgdGhlIDIwMjQgQnJhemlsaWFuIEdyYW5kIFByaXggc2NoZWR1bGVkIGZvciBOb3ZlbWJlciAzLCAyMDI0LiBPdGhlcndpc2UsIHRoaXMgbWFya2V0IHdpbGwgcmVzb2x2ZSB0byDigJxOby7igJ0KCklmIHRoZSAyMDI0IEJyYXppbGlhbiBHcmFuZCBQcml4IGlzIGNhbmNlbGVkIG9yIHJlc2NoZWR1bGVkIHRvIGEgZGF0ZSBhZnRlciBOb3ZlbWJlciAxNywgMjAyNCwgdGhpcyBtYXJrZXQgd2lsbCByZXNvbHZlIHRvIOKAnE5vLuKAnQoKVGhlIHJlc29sdXRpb24gc291cmNlIHdpbGwgYmUgdGhlIG9mZmljaWFsIEZvcm11bGEgMSB3ZWJzaXRlIGFuZCBjcmVkaWJsZSBzcG9ydHMgbmV3cyByZXBvcnRpbmcuLCByZXNfZGF0YTogcDE6IDAsIHAyOiAxLCBwMzogMC41LiBXaGVyZSBwMSBjb3JyZXNwb25kcyB0byBObywgcDIgdG8gWWVzLCBwMyB0byB1bmtub3duLiBUaGlzIHJlcXVlc3QgTVVTVCBvbmx5IHJlc29sdmUgdG8gcDEgb3IgcDIuICBVcGRhdGVzIG1hZGUgYnkgdGhlIHF1ZXN0aW9uIGNyZWF0b3IgdmlhIHRoZSBidWxsZXRpbiBib2FyZCBhdCAweDJGNWUzNjg0Y2IxRjMxOGVjNTFiMDBFZGJhMzhkNzlBYzJjMGFBOWQgc2hvdWxkIGJlIGNvbnNpZGVyZWQuLGluaXRpYWxpemVyOjkxNDMwY2FkMmQzOTc1NzY2NDk5NzE3ZmEwZDY2YTc4ZDgxNGU1YzUsb29SZXF1ZXN0ZXI6MmY1ZTM2ODRjYjFmMzE4ZWM1MWIwMGVkYmEzOGQ3OWFjMmMwYWE5ZCxjaGlsZFJlcXVlc3RlcjplZTNhZmUzNDdkNWM3NDMxNzA0MWUyNjE4YzQ5NTM0ZGFmODg3YzI0LGNoaWxkQ2hhaW5JZDoxMzcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEekvrfXUwqInTJuHO5h/qeADPWp0GDNT0U87mvRdcmFgfx/AVrD1lJE+zesya4XU3g2b3qABJegxuE+x56IaC9a4Ohbq+ifZSma7eT0Z0Mw7RH1Q2utup7i21bPx6EzmP8wJmuLEOJxi3iu3yNXlGwbXG+sazXUXotuNF2YSGDyLgTZxoQ96pFpHF3tYR/YolU1HMLTsjGoME75HMU3i4NoBAw6KecdwrTQJffEGUcrCp7pGF8R/VXAWe4nf4UgPKmdMbdXyJlTiFBjI//xVk2y/3W2/pyrAk7S3i2vafiXeDMYOo3NMpX0oDSJ6M+3PhOpxxsCIIe60aNFeyRO/4ovIOnJwO34nT8/8kyvT/iDLCgAAAAAAAAAAAAAAAAAAAA==, FtMkdFlFU19PUl9OT19RVUVSWQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGcnvBQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoMEeb3uJXGK6pI0QpR8U6Liy6mwSTUJi7voViI4konQzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADk3E6IHRpdGxlOiBXaWxsIE9zY2FyIFBpYXN0cmkgd2luIHRoZSBCcmF6aWxpYW4gR3JhbmQgUHJpeD8sIGRlc2NyaXB0aW9uOiBUaGlzIG1hcmtldCB3aWxsIHJlc29sdmUgdG8g4oCcWWVz4oCdIGlmIE9zY2FyIFBpYXN0cmkgd2lucyB0aGUgMjAyNCBCcmF6aWxpYW4gR3JhbmQgUHJpeCBzY2hlZHVsZWQgZm9yIE5vdmVtYmVyIDMsIDIwMjQuIE90aGVyd2lzZSwgdGhpcyBtYXJrZXQgd2lsbCByZXNvbHZlIHRvIOKAnE5vLuKAnQoKSWYgdGhlIDIwMjQgQnJhemlsaWFuIEdyYW5kIFByaXggaXMgY2FuY2VsZWQgb3IgcmVzY2hlZHVsZWQgdG8gYSBkYXRlIGFmdGVyIE5vdmVtYmVyIDE3LCAyMDI0LCB0aGlzIG1hcmtldCB3aWxsIHJlc29sdmUgdG8g4oCcTm8u4oCdCgpUaGUgcmVzb2x1dGlvbiBzb3VyY2Ugd2lsbCBiZSB0aGUgb2ZmaWNpYWwgRm9ybXVsYSAxIHdlYnNpdGUgYW5kIGNyZWRpYmxlIHNwb3J0cyBuZXdzIHJlcG9ydGluZy4sIHJlc19kYXRhOiBwMTogMCwgcDI6IDEsIHAzOiAwLjUuIFdoZXJlIHAxIGNvcnJlc3BvbmRzIHRvIE5vLCBwMiB0byBZZXMsIHAzIHRvIHVua25vd24uIFRoaXMgcmVxdWVzdCBNVVNUIG9ubHkgcmVzb2x2ZSB0byBwMSBvciBwMi4gIFVwZGF0ZXMgbWFkZSBieSB0aGUgcXVlc3Rpb24gY3JlYXRvciB2aWEgdGhlIGJ1bGxldGluIGJvYXJkIGF0IDB4MkY1ZTM2ODRjYjFGMzE4ZWM1MWIwMEVkYmEzOGQ3OUFjMmMwYUE5ZCBzaG91bGQgYmUgY29uc2lkZXJlZC4saW5pdGlhbGl6ZXI6OTE0MzBjYWQyZDM5NzU3NjY0OTk3MTdmYTBkNjZhNzhkODE0ZTVjNSxvb1JlcXVlc3RlcjoyZjVlMzY4NGNiMWYzMThlYzUxYjAwZWRiYTM4ZDc5YWMyYzBhYTlkLGNoaWxkUmVxdWVzdGVyOmVlM2FmZTM0N2Q1Yzc0MzE3MDQxZTI2MThjNDk1MzRkYWY4ODdjMjQsY2hpbGRDaGFpbklkOjEzNwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEeD6yA06C7WYswLJZMR0v94CJdDkPD29K41Tn3Nz+fA1ghGZNs+KONa/v2GKsqSkAq3ijE0tkT1twbUga4qrIJzXYHZDZJK1Vfp9zCPCV5YNa0iUPsZmtimR0shUqoV/wFP5zX4FUJ5VOTrN/JLCHH0Ro3S3DttTcvlT0iWyaoXG5IOVReiqf2FdKNWApqull4XbFKwQpD5fYRBAHAbVY7sHjWOHUebLFQf+JH/ktFLlCWPwxWGmDiZYG+vrfDWaIA226vNWg/pGsqSdrt3x9ROk8XhCiF+Y75TlRFNB4Pwt0gIQ7ZKq56Rb/GcbFKDJ3mCsNi6SmDyuEo8Scf/DeUj3QgMy4erk7Guhy0++DkPZxAAAAAAAAAAAAAAAAAAAAA==, FtMkdFlFU19PUl9OT19RVUVSWQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGcnvBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoGYZ5CpgPYdSYGihT90WDCxTB9pUDlxaDU4wUV1jEWrBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADlXE6IHRpdGxlOiBXaWxsIEdlb3JnZSBSdXNzZWxsIHdpbiB0aGUgQnJhemlsaWFuIEdyYW5kIFByaXg/LCBkZXNjcmlwdGlvbjogVGhpcyBtYXJrZXQgd2lsbCByZXNvbHZlIHRvIOKAnFllc+KAnSBpZiBHZW9yZ2UgUnVzc2VsbCB3aW5zIHRoZSAyMDI0IEJyYXppbGlhbiBHcmFuZCBQcml4IHNjaGVkdWxlZCBmb3IgTm92ZW1iZXIgMywgMjAyNC4gT3RoZXJ3aXNlLCB0aGlzIG1hcmtldCB3aWxsIHJlc29sdmUgdG8g4oCcTm8u4oCdCgpJZiB0aGUgMjAyNCBCcmF6aWxpYW4gR3JhbmQgUHJpeCBpcyBjYW5jZWxlZCBvciByZXNjaGVkdWxlZCB0byBhIGRhdGUgYWZ0ZXIgTm92ZW1iZXIgMTcsIDIwMjQsIHRoaXMgbWFya2V0IHdpbGwgcmVzb2x2ZSB0byDigJxOby7igJ0KClRoZSByZXNvbHV0aW9uIHNvdXJjZSB3aWxsIGJlIHRoZSBvZmZpY2lhbCBGb3JtdWxhIDEgd2Vic2l0ZSBhbmQgY3JlZGlibGUgc3BvcnRzIG5ld3MgcmVwb3J0aW5nLiwgcmVzX2RhdGE6IHAxOiAwLCBwMjogMSwgcDM6IDAuNS4gV2hlcmUgcDEgY29ycmVzcG9uZHMgdG8gTm8sIHAyIHRvIFllcywgcDMgdG8gdW5rbm93bi4gVGhpcyByZXF1ZXN0IE1VU1Qgb25seSByZXNvbHZlIHRvIHAxIG9yIHAyLiAgVXBkYXRlcyBtYWRlIGJ5IHRoZSBxdWVzdGlvbiBjcmVhdG9yIHZpYSB0aGUgYnVsbGV0aW4gYm9hcmQgYXQgMHgyRjVlMzY4NGNiMUYzMThlYzUxYjAwRWRiYTM4ZDc5QWMyYzBhQTlkIHNob3VsZCBiZSBjb25zaWRlcmVkLixpbml0aWFsaXplcjo5MTQzMGNhZDJkMzk3NTc2NjQ5OTcxN2ZhMGQ2NmE3OGQ4MTRlNWM1LG9vUmVxdWVzdGVyOjJmNWUzNjg0Y2IxZjMxOGVjNTFiMDBlZGJhMzhkNzlhYzJjMGFhOWQsY2hpbGRSZXF1ZXN0ZXI6ZWUzYWZlMzQ3ZDVjNzQzMTcwNDFlMjYxOGM0OTUzNGRhZjg4N2MyNCxjaGlsZENoYWluSWQ6MTM3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABEbQtZiZTqvK4b7i2cxmqzCYCuycSKwNNzfWyT8KKO1Pj0lGZND5tIpUcm1gZmeL0QVGoHBO3JhKWbN1IvHqsDlxKs/DgVpYuzq2Uxy95wJFfn6IdVSeZVQ+hN0wxwGKQr1wYtpFwtwhjN7GhAXL+bwmy3b7YAMGxLgA2Dgh8iEuyTTC3Dk9yM0yHEZfYEim9NVo1Dew+P2Fqv5Nn/aw2DfqOUBG6UmdLqzu7LGFko5jJIEVfeTHLL5WOQk2J8vlMR9JJrq8R6F3ZjLCoRH/v95vHZyp6gFXPhUH9NQUc19oOtLNxqSxFak9LWkKQfS1L1DpVlSc/TstCfVnbq228ca9cN2ez7ysO8eVOSG6H+S4bMwAAAAAAAAAAAAAAAAAAAA==, FtMkdFlFU19PUl9OT19RVUVSWQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGcnvWoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoNITWVkZDEMCRkTDp6KEaGKhTgT0iWee/wtnR8smInsvAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADlXE6IHRpdGxlOiBXaWxsIE1heCBWZXJzdGFwcGVuIHdpbiB0aGUgQnJhemlsaWFuIEdyYW5kIFByaXg/LCBkZXNjcmlwdGlvbjogVGhpcyBtYXJrZXQgd2lsbCByZXNvbHZlIHRvIOKAnFllc+KAnSBpZiBNYXggVmVyc3RhcHBlbiB3aW5zIHRoZSAyMDI0IEJyYXppbGlhbiBHcmFuZCBQcml4IHNjaGVkdWxlZCBmb3IgTm92ZW1iZXIgMywgMjAyNC4gT3RoZXJ3aXNlLCB0aGlzIG1hcmtldCB3aWxsIHJlc29sdmUgdG8g4oCcTm8u4oCdCgpJZiB0aGUgMjAyNCBCcmF6aWxpYW4gR3JhbmQgUHJpeCBpcyBjYW5jZWxlZCBvciByZXNjaGVkdWxlZCB0byBhIGRhdGUgYWZ0ZXIgTm92ZW1iZXIgMTcsIDIwMjQsIHRoaXMgbWFya2V0IHdpbGwgcmVzb2x2ZSB0byDigJxOby7igJ0KClRoZSByZXNvbHV0aW9uIHNvdXJjZSB3aWxsIGJlIHRoZSBvZmZpY2lhbCBGb3JtdWxhIDEgd2Vic2l0ZSBhbmQgY3JlZGlibGUgc3BvcnRzIG5ld3MgcmVwb3J0aW5nLiwgcmVzX2RhdGE6IHAxOiAwLCBwMjogMSwgcDM6IDAuNS4gV2hlcmUgcDEgY29ycmVzcG9uZHMgdG8gTm8sIHAyIHRvIFllcywgcDMgdG8gdW5rbm93bi4gVGhpcyByZXF1ZXN0IE1VU1Qgb25seSByZXNvbHZlIHRvIHAxIG9yIHAyLiAgVXBkYXRlcyBtYWRlIGJ5IHRoZSBxdWVzdGlvbiBjcmVhdG9yIHZpYSB0aGUgYnVsbGV0aW4gYm9hcmQgYXQgMHgyRjVlMzY4NGNiMUYzMThlYzUxYjAwRWRiYTM4ZDc5QWMyYzBhQTlkIHNob3VsZCBiZSBjb25zaWRlcmVkLixpbml0aWFsaXplcjo5MTQzMGNhZDJkMzk3NTc2NjQ5OTcxN2ZhMGQ2NmE3OGQ4MTRlNWM1LG9vUmVxdWVzdGVyOjJmNWUzNjg0Y2IxZjMxOGVjNTFiMDBlZGJhMzhkNzlhYzJjMGFhOWQsY2hpbGRSZXF1ZXN0ZXI6ZWUzYWZlMzQ3ZDVjNzQzMTcwNDFlMjYxOGM0OTUzNGRhZjg4N2MyNCxjaGlsZENoYWluSWQ6MTM3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABESKy0BeRV/1u2IwGJSqd7ysCWr95Nr2T6cQd0NnguX7ysUg3YXeZIVrBhdcDCeYuVgpYkTqYadLdp+oknYL+Pc+zCM1rPWO5Bn1oJZjOI+0+Yt4Ga5Ao5bIJwp5mJdBZ5oRWASDF7AvqoRCNGOVv0ltP42Y4C8UREbj96qtnioFLwaoRmjPDJNPhOzfza3mnzI98uhW5dWKvOcRM1BhuyIOF41PfSv0LpNOfTXU+B53W/xajhEaPzRx9S19R4TXPswW5+ySL1gWeADSCEXE6Rt92EpwoCRSwBoqttKd0QzM1fOtuBZUU9lBDryygQto+ZYKTbslxpr8d2ibZV+2TTBH/NIxw2usQp0SZOgM9XSFPigAAAAAAAAAAAAAAAAAAAA==] ) => ( results=[, , , , , , , , , , ] )
  • VotingV2.commitAndEmitEncryptedVote( identifier=5945535F4F525F4E4F5F51554552590000000000000000000000000000000000, time=1730747077, ancillaryData=0x713A207469746C653A2057696C6C20486172726973206C65616420696E2052435020627920302D302E34206F6E204E6F7620343F2C206465736372697074696F6E3A20546869732069732061206D61726B6574206F6E207468652052435020506F6C6C696E672041766572616765206D617267696E206265747765656E20446F6E616C64205472756D7020616E64204B616D616C6120486172726973206173206F66204E6F76656D62657220342C20323032342C2031323A303020504D2045542E2054686520737072656164207265666572656E63656420696E20746865206669727374207461626C65206F6E207468652022323032342047656E6572616C20456C656374696F6E3A205472756D702076732E204861727269732220706167652061742068747470733A2F2F7777772E7265616C636C656172706F6C6C696E672E636F6D2F706F6C6C732F707265736964656E742F67656E6572616C2F323032342F7472756D702D76732D6861727269732077696C6C206265207573656420746F207265736F6C76652074686973206D61726B65742E0A0A54686973206D61726B65742077696C6C207265736F6C766520746F202759657327206966206265747765656E2048617272697320302E302028696E636C75736976652920616E6420486172726973202B302E342028696E636C7573697665292070657263656E7461676520706F696E74732E204F74686572776973652C2074686973206D61726B65742077696C6C207265736F6C766520746F20274E6F272E0A0A5468652052435020506F6C6C696E6720417665726167652077696C6C20626520636865636B6564206F6E204E6F76656D62657220342C2031323A303020504D2045542E0A0A506C65617365206E6F74652C2074686973206D61726B657420726566657273207370656369666963616C6C7920746F20746865206D617267696E20666F722052435020706F6C6C696E6720617665726167652061732070726573656E74656420696E207468652061666F72656D656E74696F6E656420636861727420696E2074686520636F6C756D6E207469746C65642027537072656164272E205468697320696E636C7564657320616E792061646A7573746D656E7473206F72206D6574686F646F6C6F6779206368616E676573206D6164652062792052435020696E2074686569722063616C63756C6174696F6E206F662074686520706F6C6C696E672061766572616765206F722074686520646174652072616E676520757365642E0A0A4966207468652052435020506F6C6C696E672041766572616765206D617267696E2064617461206265747765656E204B616D616C612048617272697320616E6420446F6E616C64205472756D70206973206E6F7420617661696C61626C65206279204E6F76656D62657220382C20323032342C2031313A353920504D2045542C20616E6F74686572206372656469626C6520736F75726365206F6620706F6C6C696E672064617461206173206F66204E6F76656D62657220342C2031323A303020504D2045542077696C6C206265207573656420666F72206D61726B6574207265736F6C7574696F6E2E2C207265735F646174613A2070313A20302C2070323A20312C2070333A20302E352E20576865726520703120636F72726573706F6E647320746F204E6F2C20703220746F205965732C20703320746F20756E6B6E6F776E2E20546869732072657175657374204D555354206F6E6C79207265736F6C766520746F207031206F722070322E202055706461746573206D61646520627920746865207175657374696F6E2063726561746F7220766961207468652062756C6C6574696E20626F617264206174203078324635653336383463623146333138656335316230304564626133386437394163326330614139642073686F756C6420626520636F6E736964657265642E2C696E697469616C697A65723A393134333063616432643339373537363634393937313766613064363661373864383134653563352C6F6F5265717565737465723A326635653336383463623166333138656335316230306564626133386437396163326330616139642C6368696C645265717565737465723A656533616665333437643563373433313730343165323631386334393533346461663838376332342C6368696C64436861696E49643A313337, hash=230C6687501146E39B2EADFABF12544118E74077A29FF44269D7335D509DBAB5, encryptedVote=0x72EA5A468C8ECC97893AA74B7B21FC9B02C3C8FFA3B9995F691801A6617E3AFFE3739E553B8DC016B055F5517329A33E4478D450E95D8B236C08A97F14C62705DA0A060ECF2852A29D8F9E6DE0921F1FC864AD6D698C46E56B6A52E43D3BDFAE007F2064070A888AC694E8536F00F1425902288BA5CDBD9E62DBF8E8DBB82B45C75F171C5B75134FD3B1D166BB9C4B00CE2FA1A0C6F62910ABD036DEE731FF9F1C4593AF2D5AA0B4DCDD4D7C1542D564BF047D944540C6D75058FD9E129FAF78B5 )
    • FixedSlashSlashingLibrary.calcSlashing( totalStaked=19775261355633541525732120, totalVotes=17954264455794440328819977, totalCorrectVotes=17394841752000586864363462, priceRequestIndex=425, isGovernance=False ) => ( wrongVoteSlashPerToken=1000000000000000, noVoteSlashPerToken=1000000000000000 )
    • FixedSlashSlashingLibrary.calcSlashing( totalStaked=19775261355633541525732120, totalVotes=17954264455794440328819977, totalCorrectVotes=17953864455794440328819977, priceRequestIndex=426, isGovernance=False ) => ( wrongVoteSlashPerToken=1000000000000000, noVoteSlashPerToken=1000000000000000 )
    • FixedSlashSlashingLibrary.calcSlashing( totalStaked=19775261355633541525732120, totalVotes=17954207200794440328819977, totalCorrectVotes=17394786557000586864363462, priceRequestIndex=427, isGovernance=False ) => ( wrongVoteSlashPerToken=1000000000000000, noVoteSlashPerToken=1000000000000000 )
    • FixedSlashSlashingLibrary.calcSlashing( totalStaked=19775261355633541525732120, totalVotes=17559467809864933396978530, totalCorrectVotes=17374172398965979556402701, priceRequestIndex=428, isGovernance=False ) => ( wrongVoteSlashPerToken=1000000000000000, noVoteSlashPerToken=1000000000000000 )
    • VotingV2.commitAndEmitEncryptedVote( identifier=5945535F4F525F4E4F5F51554552590000000000000000000000000000000000, time=1730698959, ancillaryData=0x713A207469746C653A2057696C6C205472756D70207361792022736B696269646922206265666F72652074686520656C656374696F6E3F2C206465736372697074696F6E3A2054686973206D61726B65742077696C6C207265736F6C766520746F20E2809C596573E2809D20696620446F6E616C64205472756D70207075626C69636C79206D656E74696F6E732074686520776F72642022736B696269646922206265747765656E2053657074656D62657220313720616E64204E6F76656D62657220342C20323032342C2031313A353920504D2045542E204F74686572776973652C2074686973206D61726B65742077696C6C207265736F6C766520746F20E2809C4E6FE2809D2E0A0A4120E280986D656E74696F6EE2809920696E636C756465732074686520666F6C6C6F77696E673A0A0A2D412076657262616C207573616765206F662074686520776F72642873292022736B6962696469222E0A2D416E79207772697474656E207573616765206F662074686520776F72642873292022736B696269646922207075626C6973686564207468726F756768205472756D70277320736F6369616C206D65646961206F72206F74686572206F6666696369616C20636F6D6D756E69636174696F6E206368616E6E656C73207265676172646C657373206F66206361706974616C697A6174696F6E2E0A0A416E79207573616765206F662074686520776F7264207265676172646C657373206F6620636F6E746578742077696C6C20636F756E7420746F7761726420746865207265736F6C7574696F6E206F662074686973206D61726B65742E0A0A506C7572616C697A6174696F6E2F706F7373657373697665206F662074686520776F72642077696C6C20636F756E7420746F7761726420746865207265736F6C7574696F6E206F662074686973206D61726B65742C20686F7765766572206F7468657220666F726D732077696C6C204E4F5420636F756E742E0A0A546865207265736F6C7574696F6E20736F7572636520666F722074686973206D61726B65742077696C6C20626520666F6F74616765206F6620446F6E616C64205472756D702074616B656E2077697468696E20746865206D656E74696F6E65642074696D656672616D652C2061732077656C6C206173206F6666696369616C20636F6D6D756E69636174696F6E732066726F6D20446F6E616C64205472756D702E207265735F646174613A2070313A20302C2070323A20312C2070333A20302E352E20576865726520703120636F72726573706F6E647320746F204E6F2C20703220746F205965732C20703320746F20756E6B6E6F776E2F35302D35302E2055706461746573206D61646520627920746865207175657374696F6E2063726561746F7220766961207468652062756C6C6574696E20626F61726420617420307836413944323232363136433930466341353735346364313333336346443962376662366134463734206173206465736372696265642062792068747470733A2F2F706F6C79676F6E7363616E2E636F6D2F74782F3078613134663031623131356334393133363234666333663530386639363066346465613235323735386537336332386635663037663865313964376263613036362073686F756C6420626520636F6E736964657265642E2C696E697469616C697A65723A393134333063616432643339373537363634393937313766613064363661373864383134653563352C6F6F5265717565737465723A366139643232323631366339306663613537353463643133333363666439623766623661346637342C6368696C645265717565737465723A656533616665333437643563373433313730343165323631386334393533346461663838376332342C6368696C64436861696E49643A313337, hash=0A7E80B8F7B63B6F239F6C97113C8E460385F33AC684D04E6C752B516DB8886A, encryptedVote=0x4C1454AE1CA561491ECD394C43D7C131030DCC5012C19852A9B07DBBA49C08258A34439D217DB20838414F430F0DF9834687F5E012C57CD35486841BFA2C913C9F254E06AFE7692471D5F2B2D0D82FE99888112C99B013A741641968823483E732CF6FAAC36C12E4FD82352B1C8A559C84C414D3DD90B6B38E9240A0689EF3885D86F5DFAA4BD0244575608BD6A71AB069D5449835B75233C4B3C95B58B228B41CF923FF074D0009DAF7445A914CCCE362333E1A362389BB4EC37E32D9480FE99D52DD334FACE652896EE2BF5E3B297C256C11E161BE534ED3C12141666EABB1EB987531E4B6FD719247D212BF19A069FA43C5E7A8B010F00E83D103CD23C3FC1519ED64948DA069EA600A168657B08351 )
    • VotingV2.commitAndEmitEncryptedVote( identifier=5945535F4F525F4E4F5F51554552590000000000000000000000000000000000, time=1730658150, ancillaryData=0x713A207469746C653A2057696C6C2053657267696F20506572657A2077696E20746865204272617A696C69616E204772616E6420507269783F2C206465736372697074696F6E3A2054686973206D61726B65742077696C6C207265736F6C766520746F20E2809C596573E2809D2069662053657267696F20506572657A2077696E73207468652032303234204272617A696C69616E204772616E642050726978207363686564756C656420666F72204E6F76656D62657220332C20323032342E204F74686572776973652C2074686973206D61726B65742077696C6C207265736F6C766520746F20E2809C4E6F2EE2809D0A0A4966207468652032303234204272617A696C69616E204772616E6420507269782069732063616E63656C6564206F722072657363686564756C656420746F20612064617465206166746572204E6F76656D6265722031372C20323032342C2074686973206D61726B65742077696C6C207265736F6C766520746F20E2809C4E6F2EE2809D0A0A546865207265736F6C7574696F6E20736F757263652077696C6C20626520746865206F6666696369616C20466F726D756C612031207765627369746520616E64206372656469626C652073706F727473206E657773207265706F7274696E672E2C207265735F646174613A2070313A20302C2070323A20312C2070333A20302E352E20576865726520703120636F72726573706F6E647320746F204E6F2C20703220746F205965732C20703320746F20756E6B6E6F776E2E20546869732072657175657374204D555354206F6E6C79207265736F6C766520746F207031206F722070322E202055706461746573206D61646520627920746865207175657374696F6E2063726561746F7220766961207468652062756C6C6574696E20626F617264206174203078324635653336383463623146333138656335316230304564626133386437394163326330614139642073686F756C6420626520636F6E736964657265642E2C696E697469616C697A65723A393134333063616432643339373537363634393937313766613064363661373864383134653563352C6F6F5265717565737465723A326635653336383463623166333138656335316230306564626133386437396163326330616139642C6368696C645265717565737465723A656533616665333437643563373433313730343165323631386334393533346461663838376332342C6368696C64436861696E49643A313337, hash=98B867EE0E540EB5888F80FCEC33174CB7260BD09751A58138487344FAE20676, encryptedVote=0xC7E341D4F6183333A454D96C170BCC6A035CC0D700D3EEB0779147E733641F2BED92C442EA557A78EB399F15FA8C98EC593B242A2D2BF01A5D983713B8F0B0E2451DCE4FCDFCD523E9B9AA55B1B3E62F3761737EAAC15C2207BCEE7D09D581209906B916B24ECA1C23CBE28E07138251D2ED825E2F8F594BC4F517F69CB7E6D5729853C1E19F9375F12A8B377949F6CDF9C126A3BAFDB9DE20D3A2E40C1A8838C4C05B4DFBD083F2B0114541B8FECDCFC2DEBDA3AE35FAA8F6A6C10383749CB84325BFF43F372D842320CF83D159B5E6F83799DA809EF125EEAF12AB7B91F4769C92CF1A7AC53E87B3B720CDB4257400802421F3F38B5C2E0E06472040931BB7E14AF754B016C23DA1663F1DA85767051F )
    • VotingV2.commitAndEmitEncryptedVote( identifier=5945535F4F525F4E4F5F51554552590000000000000000000000000000000000, time=1730592385, ancillaryData=0x713A207469746C653A2057696C6C205472756D70207361792022766F746522203330206F72206D6F72652074696D657320647572696E672056697267696E69612072616C6C79206F6E204E6F7620323F2C206465736372697074696F6E3A20446F6E616C64205472756D7020686173207363686564756C656420612072616C6C79206F6E204E6F76656D626572203220696E2053616C656D2C2056697267696E696120287365653A2068747470733A2F2F6576656E742E646F6E616C646A7472756D702E636F6D2F6576656E74732F707265736964656E742D646F6E616C642D6A2D7472756D702D746F2D686F6C642D612D72616C6C792D696E2D73616C656D2D76697267696E6961292E0A0A54686973206D61726B65742077696C6C207265736F6C766520746F202259657322206966205472756D7020736179732022766F746522203330206F72206D6F72652074696D657320647572696E6720746865697220617070656172616E63652061742074686973206576656E742E204F74686572776973652C20746865206D61726B65742077696C6C207265736F6C766520746F20224E6F222E0A0A416E79207573616765206F6620746865207465726D207265676172646C657373206F6620636F6E746578742077696C6C20636F756E7420746F7761726420746865207265736F6C7574696F6E206F662074686973206D61726B65742E0A0A506C7572616C697A6174696F6E2F706F7373657373697665206F6620746865207465726D2077696C6C20636F756E7420746F7761726420746865207265736F6C7574696F6E206F662074686973206D61726B65742C20686F7765766572206F7468657220666F726D732077696C6C204E4F5420636F756E742E0A0A436F6D706F756E6420776F7264732077696C6C20636F756E74206173206C6F6E672061732022766F7465222069732070617274206F662074686520636F6D706F756E6420776F726420616E64207265666572656E63657320746865206D65616E696E672077686963682072656665727320746F206120666F726D616C20696E6469636174696F6E206F6620612063686F696365206265747765656E2074776F206F72206D6F72652063616E64696461746573206F7220636F7572736573206F6620616374696F6E2C20657870726573736564207479706963616C6C79207468726F75676820612062616C6C6F74206F7220612073686F77206F662068616E6473206F7220627920766F6963652E0A0A496620746869732063616E64696461746520646F6573206E6F74206170706561722061742074686973206576656E742C206F7220696620746865206576656E74206973206F74686572776973652063616E63656C6C6564206F722064656C61796564206265796F6E64204E6F76656D62657220322C2074686973206D61726B65742077696C6C207265736F6C766520746F20224E6F222E0A0A546865207265736F6C7574696F6E20736F757263652077696C6C2062652074686520766964656F206F6620746865207370656563682E207265735F646174613A2070313A20302C2070323A20312C2070333A20302E352E20576865726520703120636F72726573706F6E647320746F204E6F2C20703220746F205965732C20703320746F20756E6B6E6F776E2F35302D35302E2055706461746573206D61646520627920746865207175657374696F6E2063726561746F7220766961207468652062756C6C6574696E20626F61726420617420307836413944323232363136433930466341353735346364313333336346443962376662366134463734206173206465736372696265642062792068747470733A2F2F706F6C79676F6E7363616E2E636F6D2F74782F3078613134663031623131356334393133363234666333663530386639363066346465613235323735386537336332386635663037663865313964376263613036362073686F756C6420626520636F6E736964657265642E2C696E697469616C697A65723A393134333063616432643339373537363634393937313766613064363661373864383134653563352C6F6F5265717565737465723A366139643232323631366339306663613537353463643133333363666439623766623661346637342C6368696C645265717565737465723A656533616665333437643563373433313730343165323631386334393533346461663838376332342C6368696C64436861696E49643A313337, hash=8488F74E777C70459D36FF3661D34DF408ACF8024F93F9E282958470464EA0ED, encryptedVote=0xB205D7FDBC59D4F3A51CED953FC1BB4C025561992F917E75FA726809D472A88B12231522BEF1ABE4D67A0C3F5643B1D4ACEC9F5E5B64C6F38ECF35DB7A96EC5AF06A8A097261B94147C7D3E51D1BC07116F6DCBC2828A8A00A9AEE5CD64772CBA370BC0CDEC3AB78694B4197455FC4DE610AA8B4FEBAFA69D3C3ACF395C94B9140B65911BF852D80B7651D92566B93ED7C1D76E330F513F61D10194CEAC9E28D38D4B8EA4FA6091EC9BBBE418BCAE491B12346D4D53F747DF61A86EA6BC44BB087572F20F30B19C8AD5CAEAD4F68260597 )
    • VotingV2.commitAndEmitEncryptedVote( identifier=5945535F4F525F4E4F5F51554552590000000000000000000000000000000000, time=1730614228, ancillaryData=0x713A207469746C653A2057696C6C205472756D70207361792022766F746522203235206F72206D6F726520647572696E6720477265656E73626F726F2C204E432072616C6C793F2C206465736372697074696F6E3A20446F6E616C64205472756D7020686173207363686564756C656420612072616C6C79206F6E204E6F76656D626572203220696E20477265656E73626F726F2C204E6F727468204361726F6C696E6120287365653A2068747470733A2F2F6576656E742E646F6E616C646A7472756D702E636F6D2F6576656E74732F707265736964656E742D646F6E616C642D6A2D7472756D702D746F2D686F6C642D612D72616C6C792D696E2D677265656E73626F726F2D6E63292E0A0A54686973206D61726B65742077696C6C207265736F6C766520746F202259657322206966205472756D7020736179732022766F746522203235206F72206D6F72652074696D657320647572696E6720746865697220617070656172616E63652061742074686973206576656E742E204F74686572776973652C20746865206D61726B65742077696C6C207265736F6C766520746F20224E6F222E0A0A416E79207573616765206F6620746865207465726D207265676172646C657373206F6620636F6E746578742077696C6C20636F756E7420746F7761726420746865207265736F6C7574696F6E206F662074686973206D61726B65742E0A0A506C7572616C697A6174696F6E2F706F7373657373697665206F6620746865207465726D2077696C6C20636F756E7420746F7761726420746865207265736F6C7574696F6E206F662074686973206D61726B65742C20686F7765766572206F7468657220666F726D732077696C6C204E4F5420636F756E742E0A0A436F6D706F756E6420776F7264732077696C6C20636F756E74206173206C6F6E672061732022766F7465222069732070617274206F662074686520636F6D706F756E6420776F726420616E64207265666572656E63657320746865206D65616E696E672077686963682072656665727320746F206120666F726D616C2065787072657373696F6E206F662063686F696365206F72206F70696E696F6E20696E20616E20656C656374696F6E2E0A0A496620746869732063616E64696461746520646F6573206E6F74206170706561722061742074686973206576656E742C206F7220696620746865206576656E74206973206F74686572776973652063616E63656C6C6564206F722064656C61796564206265796F6E64204E6F76656D62657220322C2074686973206D61726B65742077696C6C207265736F6C766520746F20224E6F222E0A0A546865207265736F6C7574696F6E20736F757263652077696C6C2062652074686520766964656F206F6620746865207370656563682E207265735F646174613A2070313A20302C2070323A20312C2070333A20302E352E20576865726520703120636F72726573706F6E647320746F204E6F2C20703220746F205965732C20703320746F20756E6B6E6F776E2F35302D35302E2055706461746573206D61646520627920746865207175657374696F6E2063726561746F7220766961207468652062756C6C6574696E20626F61726420617420307836413944323232363136433930466341353735346364313333336346443962376662366134463734206173206465736372696265642062792068747470733A2F2F706F6C79676F6E7363616E2E636F6D2F74782F3078613134663031623131356334393133363234666333663530386639363066346465613235323735386537336332386635663037663865313964376263613036362073686F756C6420626520636F6E736964657265642E2C696E697469616C697A65723A393134333063616432643339373537363634393937313766613064363661373864383134653563352C6F6F5265717565737465723A366139643232323631366339306663613537353463643133333363666439623766623661346637342C6368696C645265717565737465723A656533616665333437643563373433313730343165323631386334393533346461663838376332342C6368696C64436861696E49643A313337, hash=53884F4E497E3F42B214C2C3B05450D3F8148D0674582CEC3DCD66B540489EEB, encryptedVote=0x62471FD25396474D1E4BF83230A55617027043B9189F5CA09C193EF2C0CA2EC17B7145C6541B25F25493EFB7FDA984386A144EEC22283973E463E36DD909DB2861B5F485A759C9D5B3982E72DD642C4A489C16CFB90831192C30B4F5BE42BDF0F36A1D8F2F5C104EBBD5FCAD739F4CBC434F92269D3A3E648EB581BD2F9F2174D26E2557302C3E798F4BF01CF41EE6EEEBD17F9485EA68BE0876C725F9D42AAF2C865BD8CF9BE9D89AD0897AB70E3BC8D44342978E86AEF1D7373BDEF4ADDD15C9377D8C16E0FFED77E643A6AF0576E1CC )
    • VotingV2.commitAndEmitEncryptedVote( identifier=5945535F4F525F4E4F5F51554552590000000000000000000000000000000000, time=1730618526, ancillaryData=0x713A207469746C653A20426172726961756C742076732E2053746F6C747A6675732C206465736372697074696F6E3A20546869732069732061206D61726B6574206F6E2077686574686572204D6172632D416E64726520426172726961756C74206F722044757374696E2053746F6C747A6675732077696C6C2077696E20746865697220626F75742E0A0A4966204D6172632D416E64726520426172726961756C74206973206465636C61726564207468652077696E6E6572206F66207468697320626F75742C2074686973206D61726B65742077696C6C207265736F6C766520746F20E2809C426172726961756C742EE2809D2049662044757374696E2053746F6C747A667573206973206465636C61726564207468652077696E6E6572206F66207468697320626F75742C2074686973206D61726B65742077696C6C207265736F6C766520746F20E2809C53746F6C747A667573E2809D2E0A0A49662074686973206669676874206973206465636C61726564206120647261772C206F7220696620666F7220616E7920726561736F6E20746865206D61746368206973206E6F742073636F7265642C20706F7374706F6E6564206166746572204E6F76656D6265722031362C20323032342C2031313A353920504D2045542C206F722063616E63656C65642C2074686973206D61726B65742077696C6C207265736F6C76652035302D35302E207265735F646174613A2070313A20302C2070323A20312C2070333A20302E352E20576865726520703120636F72726573706F6E647320746F204E6F2C20703220746F205965732C20703320746F20756E6B6E6F776E2F35302D35302E2055706461746573206D61646520627920746865207175657374696F6E2063726561746F7220766961207468652062756C6C6574696E20626F61726420617420307836413944323232363136433930466341353735346364313333336346443962376662366134463734206173206465736372696265642062792068747470733A2F2F706F6C79676F6E7363616E2E636F6D2F74782F3078613134663031623131356334393133363234666333663530386639363066346465613235323735386537336332386635663037663865313964376263613036362073686F756C6420626520636F6E736964657265642E2C696E697469616C697A65723A393134333063616432643339373537363634393937313766613064363661373864383134653563352C6F6F5265717565737465723A366139643232323631366339306663613537353463643133333363666439623766623661346637342C6368696C645265717565737465723A656533616665333437643563373433313730343165323631386334393533346461663838376332342C6368696C64436861696E49643A313337, hash=1F08646349680FE16083CB75E8DF7E65E2E9E3BC00EA7FAC489C2ACFDD5003A6, encryptedVote=0x1B3E5D14591B5997761F12E690D3244F031520227602542450B92A45618CBB63B1D67992911E0CC747834B79DF6BA1478B7AAD766E6BBE7F6FF3D5CE7B807F6C4705A0B9190CE1F1503D3A7F7D38F1744548F625297188A59755DEEA783E74C3629689C92687D098F3BC7F0763A8CB218BA499541AACE1FED814610E3E46E173E05AFDF3E43DBA526E151844683EF46D52E8ED730546AB4F0DECC96B72A04D36B4628830DA35CC43A56D2171122E0396DBBE78E750964CD3C35CCE9D3715DB24EA )
    • VotingV2.commitAndEmitEncryptedVote( identifier=5945535F4F525F4E4F5F51554552590000000000000000000000000000000000, time=1730654141, ancillaryData=0x713A207469746C653A2057696C6C204361726C6F73205361696E7A2077696E20746865204272617A696C69616E204772616E6420507269783F2C206465736372697074696F6E3A2054686973206D61726B65742077696C6C207265736F6C766520746F20E2809C596573E2809D206966204361726C6F73205361696E7A2077696E73207468652032303234204272617A696C69616E204772616E642050726978207363686564756C656420666F72204E6F76656D62657220332C20323032342E204F74686572776973652C2074686973206D61726B65742077696C6C207265736F6C766520746F20E2809C4E6F2EE2809D0A0A4966207468652032303234204272617A696C69616E204772616E6420507269782069732063616E63656C6564206F722072657363686564756C656420746F20612064617465206166746572204E6F76656D6265722031372C20323032342C2074686973206D61726B65742077696C6C207265736F6C766520746F20E2809C4E6F2EE2809D0A0A546865207265736F6C7574696F6E20736F757263652077696C6C20626520746865206F6666696369616C20466F726D756C612031207765627369746520616E64206372656469626C652073706F727473206E657773207265706F7274696E672E2C207265735F646174613A2070313A20302C2070323A20312C2070333A20302E352E20576865726520703120636F72726573706F6E647320746F204E6F2C20703220746F205965732C20703320746F20756E6B6E6F776E2E20546869732072657175657374204D555354206F6E6C79207265736F6C766520746F207031206F722070322E202055706461746573206D61646520627920746865207175657374696F6E2063726561746F7220766961207468652062756C6C6574696E20626F617264206174203078324635653336383463623146333138656335316230304564626133386437394163326330614139642073686F756C6420626520636F6E736964657265642E2C696E697469616C697A65723A393134333063616432643339373537363634393937313766613064363661373864383134653563352C6F6F5265717565737465723A326635653336383463623166333138656335316230306564626133386437396163326330616139642C6368696C645265717565737465723A656533616665333437643563373433313730343165323631386334393533346461663838376332342C6368696C64436861696E49643A313337, hash=C303AD58C127B54A52538C8636CD1FE1C5C3A49E6EFA3C797CFC6CAAC3393C4C, encryptedVote=0x10F2A035AAABD821579D5A02304477F80200EB1366A4840C9BF7E34D357DFF5F483DF8999D5ECF3F468DC6E8F77E57578C666B80D9CE366F9A81131F8B225F4AFAB24C22B974B77FEADE848FEC77C6B915C40CA4BCB680ACE85C4B343FD0325C6B494E448ED7937152D483DA66B9F7019587EE7C62C10F85AEC11D5A5C88296B9055F893285A83E88C8DFA3BA7E562B139427A759E19303EA3F391C6FF94C6554148815E83650F75D58BB8E8866ED3BE04465B4E06DE4274B19BD98A10A14277F5CA2DE2B0C2ABCEFC046EF286DC448EFB0B8F5389CD20C4B6EEEFF47FAC59E112E54C750FB18AFA80380058A4A6E2FC1B38CAF0C623FD6126AFEB192A7CB46D44C67E4F26B9C1118DEAE27AED158B8BA6 )
    • VotingV2.commitAndEmitEncryptedVote( identifier=5945535F4F525F4E4F5F51554552590000000000000000000000000000000000, time=1730657292, ancillaryData=0x713A207469746C653A2057696C6C2053657267696F20506572657A2077696E20746865204272617A696C69616E204772616E6420507269783F2C206465736372697074696F6E3A2054686973206D61726B65742077696C6C207265736F6C766520746F20E2809C596573E2809D2069662053657267696F20506572657A2077696E73207468652032303234204272617A696C69616E204772616E642050726978207363686564756C656420666F72204E6F76656D62657220332C20323032342E204F74686572776973652C2074686973206D61726B65742077696C6C207265736F6C766520746F20E2809C4E6F2EE2809D0A0A4966207468652032303234204272617A696C69616E204772616E6420507269782069732063616E63656C6564206F722072657363686564756C656420746F20612064617465206166746572204E6F76656D6265722031372C20323032342C2074686973206D61726B65742077696C6C207265736F6C766520746F20E2809C4E6F2EE2809D0A0A546865207265736F6C7574696F6E20736F757263652077696C6C20626520746865206F6666696369616C20466F726D756C612031207765627369746520616E64206372656469626C652073706F727473206E657773207265706F7274696E672E2C207265735F646174613A2070313A20302C2070323A20312C2070333A20302E352E20576865726520703120636F72726573706F6E647320746F204E6F2C20703220746F205965732C20703320746F20756E6B6E6F776E2E20546869732072657175657374204D555354206F6E6C79207265736F6C766520746F207031206F722070322E202055706461746573206D61646520627920746865207175657374696F6E2063726561746F7220766961207468652062756C6C6574696E20626F617264206174203078324635653336383463623146333138656335316230304564626133386437394163326330614139642073686F756C6420626520636F6E736964657265642E2C696E697469616C697A65723A393134333063616432643339373537363634393937313766613064363661373864383134653563352C6F6F5265717565737465723A326635653336383463623166333138656335316230306564626133386437396163326330616139642C6368696C645265717565737465723A656533616665333437643563373433313730343165323631386334393533346461663838376332342C6368696C64436861696E49643A313337, hash=5E6100379C68FFDA33BD00E15AC429436C312133C5DE9896FF515495A8249AA9, encryptedVote=0xE92FADF5D4C2A2274C9B873B987FA9E0033D6A74183353D14F3B9AF45D7261607F1FC056B0F594913ECDEB326B85D4DE0D9BDEA00125E831B84FB1E7A21A0BD6B83A16EAFA27D94A66BB793D19D0CC3B447D50DAEB6EA7B8B6D5B3F1E84CE63FCC099AE2C4389C62DE2BB7C8D5E51B06D71BEB1ACD7517A2DB8D176612183C8B813671A10F7AA45A47177B5847F628954D4730B4EC8C6A0C13BE47314DE2E0DA01030E8A79C770AD34097DF10651CAC2A7BA4617C47F5570167B89DFE1480F2A674C6DD5F22654E21418C8FFFC55936CBFDD6DBFA72AC093B4B78B6BDA7E25DE0CC60EA3734CA57D280D227A33EDCF84EA71C6C08821EEB468D15EC913BFE28BC83A72703B7E274FCFFC932BD3FE20CB0A )
    • VotingV2.commitAndEmitEncryptedVote( identifier=5945535F4F525F4E4F5F51554552590000000000000000000000000000000000, time=1730657300, ancillaryData=0x713A207469746C653A2057696C6C204F7363617220506961737472692077696E20746865204272617A696C69616E204772616E6420507269783F2C206465736372697074696F6E3A2054686973206D61726B65742077696C6C207265736F6C766520746F20E2809C596573E2809D206966204F7363617220506961737472692077696E73207468652032303234204272617A696C69616E204772616E642050726978207363686564756C656420666F72204E6F76656D62657220332C20323032342E204F74686572776973652C2074686973206D61726B65742077696C6C207265736F6C766520746F20E2809C4E6F2EE2809D0A0A4966207468652032303234204272617A696C69616E204772616E6420507269782069732063616E63656C6564206F722072657363686564756C656420746F20612064617465206166746572204E6F76656D6265722031372C20323032342C2074686973206D61726B65742077696C6C207265736F6C766520746F20E2809C4E6F2EE2809D0A0A546865207265736F6C7574696F6E20736F757263652077696C6C20626520746865206F6666696369616C20466F726D756C612031207765627369746520616E64206372656469626C652073706F727473206E657773207265706F7274696E672E2C207265735F646174613A2070313A20302C2070323A20312C2070333A20302E352E20576865726520703120636F72726573706F6E647320746F204E6F2C20703220746F205965732C20703320746F20756E6B6E6F776E2E20546869732072657175657374204D555354206F6E6C79207265736F6C766520746F207031206F722070322E202055706461746573206D61646520627920746865207175657374696F6E2063726561746F7220766961207468652062756C6C6574696E20626F617264206174203078324635653336383463623146333138656335316230304564626133386437394163326330614139642073686F756C6420626520636F6E736964657265642E2C696E697469616C697A65723A393134333063616432643339373537363634393937313766613064363661373864383134653563352C6F6F5265717565737465723A326635653336383463623166333138656335316230306564626133386437396163326330616139642C6368696C645265717565737465723A656533616665333437643563373433313730343165323631386334393533346461663838376332342C6368696C64436861696E49643A313337, hash=C11E6F7B895C62BAA48D10A51F14E8B8B2EA6C124D4262EEFA15888E24A27433, encryptedVote=0xE0FAC80D3A0BB598B302C964C474BFDE0225D0E43C3DBD2B8D539F7373F9F03582119936CF8A38D6BFBF618AB2A4A402ADE28C4D2D913D6DC1B5206B8AAB209CD76076436492B555FA7DCC23C257960D6B48943EC666B62991D2C854AA857FC053F9CD7E05509E55393ACDFC92C21C7D11A374B70EDB5372F953D225B26A85C6E4839545E8AA7F615D28D580A6ABA59785DB14AC10A43E5F6110401C06D563BB078D638751E6CB1507FE247FE4B452E50963F0C561A60E26581BEBEB7C359A200DB6EAF35683FA46B2A49DAEDDF1F513A4F17842885F98EF94E5445341E0FC2DD20210ED92AAE7A45BFC671B14A0C9DE60AC362E92983CAE128F1271FFC37948F7420332E1EAE4EC6BA1CB4FBE0E43D9C4 )
    • VotingV2.commitAndEmitEncryptedVote( identifier=5945535F4F525F4E4F5F51554552590000000000000000000000000000000000, time=1730657296, ancillaryData=0x713A207469746C653A2057696C6C2047656F7267652052757373656C6C2077696E20746865204272617A696C69616E204772616E6420507269783F2C206465736372697074696F6E3A2054686973206D61726B65742077696C6C207265736F6C766520746F20E2809C596573E2809D2069662047656F7267652052757373656C6C2077696E73207468652032303234204272617A696C69616E204772616E642050726978207363686564756C656420666F72204E6F76656D62657220332C20323032342E204F74686572776973652C2074686973206D61726B65742077696C6C207265736F6C766520746F20E2809C4E6F2EE2809D0A0A4966207468652032303234204272617A696C69616E204772616E6420507269782069732063616E63656C6564206F722072657363686564756C656420746F20612064617465206166746572204E6F76656D6265722031372C20323032342C2074686973206D61726B65742077696C6C207265736F6C766520746F20E2809C4E6F2EE2809D0A0A546865207265736F6C7574696F6E20736F757263652077696C6C20626520746865206F6666696369616C20466F726D756C612031207765627369746520616E64206372656469626C652073706F727473206E657773207265706F7274696E672E2C207265735F646174613A2070313A20302C2070323A20312C2070333A20302E352E20576865726520703120636F72726573706F6E647320746F204E6F2C20703220746F205965732C20703320746F20756E6B6E6F776E2E20546869732072657175657374204D555354206F6E6C79207265736F6C766520746F207031206F722070322E202055706461746573206D61646520627920746865207175657374696F6E2063726561746F7220766961207468652062756C6C6574696E20626F617264206174203078324635653336383463623146333138656335316230304564626133386437394163326330614139642073686F756C6420626520636F6E736964657265642E2C696E697469616C697A65723A393134333063616432643339373537363634393937313766613064363661373864383134653563352C6F6F5265717565737465723A326635653336383463623166333138656335316230306564626133386437396163326330616139642C6368696C645265717565737465723A656533616665333437643563373433313730343165323631386334393533346461663838376332342C6368696C64436861696E49643A313337, hash=6619E42A603D87526068A14FDD160C2C5307DA540E5C5A0D4E30515D63116AC1, encryptedVote=0xB42D662653AAF2B86FB8B67319AACC2602BB27122B034DCDF5B24FC28A3B53E3D25199343E6D22951C9B581999E2F44151A81C13B72612966CDD48BC7AAC0E5C4AB3F0E056962ECEAD94C72F79C0915F9FA21D552799550FA1374C31C06290AF5C18B69170B7086337B1A10172FE6F09B2DDBED800C1B12E00360E087C884BB24D30B70E4F72334C871197D81229BD355A350DEC3E3F616ABF9367FDAC360DFA8E5011BA52674BAB3BBB2C6164A398C920455F7931CB2F958E424D89F2F94C47D249AEAF11E85DD98CB0A8447FEFF79BC7672A7A8055CF8541FD35051CD7DA0EB4B371A92C456A4F4B5A42907D2D4BD43A5595273F4ECB427D59DBAB6DBC71AF5C3767B3EF2B0EF1E54E486E87F92E1B33 )
    • VotingV2.commitAndEmitEncryptedVote( identifier=5945535F4F525F4E4F5F51554552590000000000000000000000000000000000, time=1730657642, ancillaryData=0x713A207469746C653A2057696C6C204D6178205665727374617070656E2077696E20746865204272617A696C69616E204772616E6420507269783F2C206465736372697074696F6E3A2054686973206D61726B65742077696C6C207265736F6C766520746F20E2809C596573E2809D206966204D6178205665727374617070656E2077696E73207468652032303234204272617A696C69616E204772616E642050726978207363686564756C656420666F72204E6F76656D62657220332C20323032342E204F74686572776973652C2074686973206D61726B65742077696C6C207265736F6C766520746F20E2809C4E6F2EE2809D0A0A4966207468652032303234204272617A696C69616E204772616E6420507269782069732063616E63656C6564206F722072657363686564756C656420746F20612064617465206166746572204E6F76656D6265722031372C20323032342C2074686973206D61726B65742077696C6C207265736F6C766520746F20E2809C4E6F2EE2809D0A0A546865207265736F6C7574696F6E20736F757263652077696C6C20626520746865206F6666696369616C20466F726D756C612031207765627369746520616E64206372656469626C652073706F727473206E657773207265706F7274696E672E2C207265735F646174613A2070313A20302C2070323A20312C2070333A20302E352E20576865726520703120636F72726573706F6E647320746F204E6F2C20703220746F205965732C20703320746F20756E6B6E6F776E2E20546869732072657175657374204D555354206F6E6C79207265736F6C766520746F207031206F722070322E202055706461746573206D61646520627920746865207175657374696F6E2063726561746F7220766961207468652062756C6C6574696E20626F617264206174203078324635653336383463623146333138656335316230304564626133386437394163326330614139642073686F756C6420626520636F6E736964657265642E2C696E697469616C697A65723A393134333063616432643339373537363634393937313766613064363661373864383134653563352C6F6F5265717565737465723A326635653336383463623166333138656335316230306564626133386437396163326330616139642C6368696C645265717565737465723A656533616665333437643563373433313730343165323631386334393533346461663838376332342C6368696C64436861696E49643A313337, hash=D2135959190C43024644C3A7A2846862A14E04F489679EFF0B6747CB26227B2F, encryptedVote=0x22B2D0179157FD6ED88C06252A9DEF2B025ABF7936BD93E9C41DD0D9E0B97EF2B14837617799215AC185D70309E62E560A58913A9869D2DDA7EA249D82FE3DCFB308CD6B3D63B9067D682598CE23ED3E62DE066B9028E5B209C29E6625D059E684560120C5EC0BEAA1108D18E56FD25B4FE366380BC51111B8FDEAAB678A814BC1AA119A33C324D3E13B37F36B79A7CC8F7CBA15B97562AF39C44CD4186EC88385E353DF4AFD0BA4D39F4D753E079DD6FF16A384468FCD1C7D4B5F51E135CFB305B9FB248BD6059E00348211713A46DF76129C280914B0068AADB4A7744333357CEB6E059514F65043AF2CA042DA3E6582936EC971A6BF1DDA26D957ED934C11FF348C70DAEB10A744993A033D5D214F8A )
      File 1 of 2: VotingV2
      // SPDX-License-Identifier: MIT
      // OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)
      pragma solidity ^0.8.0;
      import "../utils/Context.sol";
      /**
       * @dev Contract module which provides a basic access control mechanism, where
       * there is an account (an owner) that can be granted exclusive access to
       * specific functions.
       *
       * By default, the owner account will be the one that deploys the contract. This
       * can later be changed with {transferOwnership}.
       *
       * This module is used through inheritance. It will make available the modifier
       * `onlyOwner`, which can be applied to your functions to restrict their use to
       * the owner.
       */
      abstract contract Ownable is Context {
          address private _owner;
          event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
          /**
           * @dev Initializes the contract setting the deployer as the initial owner.
           */
          constructor() {
              _transferOwnership(_msgSender());
          }
          /**
           * @dev Returns the address of the current owner.
           */
          function owner() public view virtual returns (address) {
              return _owner;
          }
          /**
           * @dev Throws if called by any account other than the owner.
           */
          modifier onlyOwner() {
              require(owner() == _msgSender(), "Ownable: caller is not the owner");
              _;
          }
          /**
           * @dev Leaves the contract without owner. It will not be possible to call
           * `onlyOwner` functions anymore. Can only be called by the current owner.
           *
           * NOTE: Renouncing ownership will leave the contract without an owner,
           * thereby removing any functionality that is only available to the owner.
           */
          function renounceOwnership() public virtual onlyOwner {
              _transferOwnership(address(0));
          }
          /**
           * @dev Transfers ownership of the contract to a new account (`newOwner`).
           * Can only be called by the current owner.
           */
          function transferOwnership(address newOwner) public virtual onlyOwner {
              require(newOwner != address(0), "Ownable: new owner is the zero address");
              _transferOwnership(newOwner);
          }
          /**
           * @dev Transfers ownership of the contract to a new account (`newOwner`).
           * Internal function without access restriction.
           */
          function _transferOwnership(address newOwner) internal virtual {
              address oldOwner = _owner;
              _owner = newOwner;
              emit OwnershipTransferred(oldOwner, newOwner);
          }
      }
      // SPDX-License-Identifier: MIT
      // OpenZeppelin Contracts v4.4.1 (token/ERC20/ERC20.sol)
      pragma solidity ^0.8.0;
      import "./IERC20.sol";
      import "./extensions/IERC20Metadata.sol";
      import "../../utils/Context.sol";
      /**
       * @dev Implementation of the {IERC20} interface.
       *
       * This implementation is agnostic to the way tokens are created. This means
       * that a supply mechanism has to be added in a derived contract using {_mint}.
       * For a generic mechanism see {ERC20PresetMinterPauser}.
       *
       * TIP: For a detailed writeup see our guide
       * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How
       * to implement supply mechanisms].
       *
       * We have followed general OpenZeppelin Contracts guidelines: functions revert
       * instead returning `false` on failure. This behavior is nonetheless
       * conventional and does not conflict with the expectations of ERC20
       * applications.
       *
       * Additionally, an {Approval} event is emitted on calls to {transferFrom}.
       * This allows applications to reconstruct the allowance for all accounts just
       * by listening to said events. Other implementations of the EIP may not emit
       * these events, as it isn't required by the specification.
       *
       * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
       * functions have been added to mitigate the well-known issues around setting
       * allowances. See {IERC20-approve}.
       */
      contract ERC20 is Context, IERC20, IERC20Metadata {
          mapping(address => uint256) private _balances;
          mapping(address => mapping(address => uint256)) private _allowances;
          uint256 private _totalSupply;
          string private _name;
          string private _symbol;
          /**
           * @dev Sets the values for {name} and {symbol}.
           *
           * The default value of {decimals} is 18. To select a different value for
           * {decimals} you should overload it.
           *
           * All two of these values are immutable: they can only be set once during
           * construction.
           */
          constructor(string memory name_, string memory symbol_) {
              _name = name_;
              _symbol = symbol_;
          }
          /**
           * @dev Returns the name of the token.
           */
          function name() public view virtual override returns (string memory) {
              return _name;
          }
          /**
           * @dev Returns the symbol of the token, usually a shorter version of the
           * name.
           */
          function symbol() public view virtual override returns (string memory) {
              return _symbol;
          }
          /**
           * @dev Returns the number of decimals used to get its user representation.
           * For example, if `decimals` equals `2`, a balance of `505` tokens should
           * be displayed to a user as `5.05` (`505 / 10 ** 2`).
           *
           * Tokens usually opt for a value of 18, imitating the relationship between
           * Ether and Wei. This is the value {ERC20} uses, unless this function is
           * overridden;
           *
           * NOTE: This information is only used for _display_ purposes: it in
           * no way affects any of the arithmetic of the contract, including
           * {IERC20-balanceOf} and {IERC20-transfer}.
           */
          function decimals() public view virtual override returns (uint8) {
              return 18;
          }
          /**
           * @dev See {IERC20-totalSupply}.
           */
          function totalSupply() public view virtual override returns (uint256) {
              return _totalSupply;
          }
          /**
           * @dev See {IERC20-balanceOf}.
           */
          function balanceOf(address account) public view virtual override returns (uint256) {
              return _balances[account];
          }
          /**
           * @dev See {IERC20-transfer}.
           *
           * Requirements:
           *
           * - `recipient` cannot be the zero address.
           * - the caller must have a balance of at least `amount`.
           */
          function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
              _transfer(_msgSender(), recipient, amount);
              return true;
          }
          /**
           * @dev See {IERC20-allowance}.
           */
          function allowance(address owner, address spender) public view virtual override returns (uint256) {
              return _allowances[owner][spender];
          }
          /**
           * @dev See {IERC20-approve}.
           *
           * Requirements:
           *
           * - `spender` cannot be the zero address.
           */
          function approve(address spender, uint256 amount) public virtual override returns (bool) {
              _approve(_msgSender(), spender, amount);
              return true;
          }
          /**
           * @dev See {IERC20-transferFrom}.
           *
           * Emits an {Approval} event indicating the updated allowance. This is not
           * required by the EIP. See the note at the beginning of {ERC20}.
           *
           * Requirements:
           *
           * - `sender` and `recipient` cannot be the zero address.
           * - `sender` must have a balance of at least `amount`.
           * - the caller must have allowance for ``sender``'s tokens of at least
           * `amount`.
           */
          function transferFrom(
              address sender,
              address recipient,
              uint256 amount
          ) public virtual override returns (bool) {
              _transfer(sender, recipient, amount);
              uint256 currentAllowance = _allowances[sender][_msgSender()];
              require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance");
              unchecked {
                  _approve(sender, _msgSender(), currentAllowance - amount);
              }
              return true;
          }
          /**
           * @dev Atomically increases the allowance granted to `spender` by the caller.
           *
           * This is an alternative to {approve} that can be used as a mitigation for
           * problems described in {IERC20-approve}.
           *
           * Emits an {Approval} event indicating the updated allowance.
           *
           * Requirements:
           *
           * - `spender` cannot be the zero address.
           */
          function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
              _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue);
              return true;
          }
          /**
           * @dev Atomically decreases the allowance granted to `spender` by the caller.
           *
           * This is an alternative to {approve} that can be used as a mitigation for
           * problems described in {IERC20-approve}.
           *
           * Emits an {Approval} event indicating the updated allowance.
           *
           * Requirements:
           *
           * - `spender` cannot be the zero address.
           * - `spender` must have allowance for the caller of at least
           * `subtractedValue`.
           */
          function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
              uint256 currentAllowance = _allowances[_msgSender()][spender];
              require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
              unchecked {
                  _approve(_msgSender(), spender, currentAllowance - subtractedValue);
              }
              return true;
          }
          /**
           * @dev Moves `amount` of tokens from `sender` to `recipient`.
           *
           * This internal function is equivalent to {transfer}, and can be used to
           * e.g. implement automatic token fees, slashing mechanisms, etc.
           *
           * Emits a {Transfer} event.
           *
           * Requirements:
           *
           * - `sender` cannot be the zero address.
           * - `recipient` cannot be the zero address.
           * - `sender` must have a balance of at least `amount`.
           */
          function _transfer(
              address sender,
              address recipient,
              uint256 amount
          ) internal virtual {
              require(sender != address(0), "ERC20: transfer from the zero address");
              require(recipient != address(0), "ERC20: transfer to the zero address");
              _beforeTokenTransfer(sender, recipient, amount);
              uint256 senderBalance = _balances[sender];
              require(senderBalance >= amount, "ERC20: transfer amount exceeds balance");
              unchecked {
                  _balances[sender] = senderBalance - amount;
              }
              _balances[recipient] += amount;
              emit Transfer(sender, recipient, amount);
              _afterTokenTransfer(sender, recipient, amount);
          }
          /** @dev Creates `amount` tokens and assigns them to `account`, increasing
           * the total supply.
           *
           * Emits a {Transfer} event with `from` set to the zero address.
           *
           * Requirements:
           *
           * - `account` cannot be the zero address.
           */
          function _mint(address account, uint256 amount) internal virtual {
              require(account != address(0), "ERC20: mint to the zero address");
              _beforeTokenTransfer(address(0), account, amount);
              _totalSupply += amount;
              _balances[account] += amount;
              emit Transfer(address(0), account, amount);
              _afterTokenTransfer(address(0), account, amount);
          }
          /**
           * @dev Destroys `amount` tokens from `account`, reducing the
           * total supply.
           *
           * Emits a {Transfer} event with `to` set to the zero address.
           *
           * Requirements:
           *
           * - `account` cannot be the zero address.
           * - `account` must have at least `amount` tokens.
           */
          function _burn(address account, uint256 amount) internal virtual {
              require(account != address(0), "ERC20: burn from the zero address");
              _beforeTokenTransfer(account, address(0), amount);
              uint256 accountBalance = _balances[account];
              require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
              unchecked {
                  _balances[account] = accountBalance - amount;
              }
              _totalSupply -= amount;
              emit Transfer(account, address(0), amount);
              _afterTokenTransfer(account, address(0), amount);
          }
          /**
           * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
           *
           * This internal function is equivalent to `approve`, and can be used to
           * e.g. set automatic allowances for certain subsystems, etc.
           *
           * Emits an {Approval} event.
           *
           * Requirements:
           *
           * - `owner` cannot be the zero address.
           * - `spender` cannot be the zero address.
           */
          function _approve(
              address owner,
              address spender,
              uint256 amount
          ) internal virtual {
              require(owner != address(0), "ERC20: approve from the zero address");
              require(spender != address(0), "ERC20: approve to the zero address");
              _allowances[owner][spender] = amount;
              emit Approval(owner, spender, amount);
          }
          /**
           * @dev Hook that is called before any transfer of tokens. This includes
           * minting and burning.
           *
           * Calling conditions:
           *
           * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
           * will be transferred to `to`.
           * - when `from` is zero, `amount` tokens will be minted for `to`.
           * - when `to` is zero, `amount` of ``from``'s tokens will be burned.
           * - `from` and `to` are never both zero.
           *
           * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
           */
          function _beforeTokenTransfer(
              address from,
              address to,
              uint256 amount
          ) internal virtual {}
          /**
           * @dev Hook that is called after any transfer of tokens. This includes
           * minting and burning.
           *
           * Calling conditions:
           *
           * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
           * has been transferred to `to`.
           * - when `from` is zero, `amount` tokens have been minted for `to`.
           * - when `to` is zero, `amount` of ``from``'s tokens have been burned.
           * - `from` and `to` are never both zero.
           *
           * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
           */
          function _afterTokenTransfer(
              address from,
              address to,
              uint256 amount
          ) internal virtual {}
      }
      // SPDX-License-Identifier: MIT
      // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/ERC20Snapshot.sol)
      pragma solidity ^0.8.0;
      import "../ERC20.sol";
      import "../../../utils/Arrays.sol";
      import "../../../utils/Counters.sol";
      /**
       * @dev This contract extends an ERC20 token with a snapshot mechanism. When a snapshot is created, the balances and
       * total supply at the time are recorded for later access.
       *
       * This can be used to safely create mechanisms based on token balances such as trustless dividends or weighted voting.
       * In naive implementations it's possible to perform a "double spend" attack by reusing the same balance from different
       * accounts. By using snapshots to calculate dividends or voting power, those attacks no longer apply. It can also be
       * used to create an efficient ERC20 forking mechanism.
       *
       * Snapshots are created by the internal {_snapshot} function, which will emit the {Snapshot} event and return a
       * snapshot id. To get the total supply at the time of a snapshot, call the function {totalSupplyAt} with the snapshot
       * id. To get the balance of an account at the time of a snapshot, call the {balanceOfAt} function with the snapshot id
       * and the account address.
       *
       * NOTE: Snapshot policy can be customized by overriding the {_getCurrentSnapshotId} method. For example, having it
       * return `block.number` will trigger the creation of snapshot at the begining of each new block. When overridding this
       * function, be careful about the monotonicity of its result. Non-monotonic snapshot ids will break the contract.
       *
       * Implementing snapshots for every block using this method will incur significant gas costs. For a gas-efficient
       * alternative consider {ERC20Votes}.
       *
       * ==== Gas Costs
       *
       * Snapshots are efficient. Snapshot creation is _O(1)_. Retrieval of balances or total supply from a snapshot is _O(log
       * n)_ in the number of snapshots that have been created, although _n_ for a specific account will generally be much
       * smaller since identical balances in subsequent snapshots are stored as a single entry.
       *
       * There is a constant overhead for normal ERC20 transfers due to the additional snapshot bookkeeping. This overhead is
       * only significant for the first transfer that immediately follows a snapshot for a particular account. Subsequent
       * transfers will have normal cost until the next snapshot, and so on.
       */
      abstract contract ERC20Snapshot is ERC20 {
          // Inspired by Jordi Baylina's MiniMeToken to record historical balances:
          // https://github.com/Giveth/minimd/blob/ea04d950eea153a04c51fa510b068b9dded390cb/contracts/MiniMeToken.sol
          using Arrays for uint256[];
          using Counters for Counters.Counter;
          // Snapshotted values have arrays of ids and the value corresponding to that id. These could be an array of a
          // Snapshot struct, but that would impede usage of functions that work on an array.
          struct Snapshots {
              uint256[] ids;
              uint256[] values;
          }
          mapping(address => Snapshots) private _accountBalanceSnapshots;
          Snapshots private _totalSupplySnapshots;
          // Snapshot ids increase monotonically, with the first value being 1. An id of 0 is invalid.
          Counters.Counter private _currentSnapshotId;
          /**
           * @dev Emitted by {_snapshot} when a snapshot identified by `id` is created.
           */
          event Snapshot(uint256 id);
          /**
           * @dev Creates a new snapshot and returns its snapshot id.
           *
           * Emits a {Snapshot} event that contains the same id.
           *
           * {_snapshot} is `internal` and you have to decide how to expose it externally. Its usage may be restricted to a
           * set of accounts, for example using {AccessControl}, or it may be open to the public.
           *
           * [WARNING]
           * ====
           * While an open way of calling {_snapshot} is required for certain trust minimization mechanisms such as forking,
           * you must consider that it can potentially be used by attackers in two ways.
           *
           * First, it can be used to increase the cost of retrieval of values from snapshots, although it will grow
           * logarithmically thus rendering this attack ineffective in the long term. Second, it can be used to target
           * specific accounts and increase the cost of ERC20 transfers for them, in the ways specified in the Gas Costs
           * section above.
           *
           * We haven't measured the actual numbers; if this is something you're interested in please reach out to us.
           * ====
           */
          function _snapshot() internal virtual returns (uint256) {
              _currentSnapshotId.increment();
              uint256 currentId = _getCurrentSnapshotId();
              emit Snapshot(currentId);
              return currentId;
          }
          /**
           * @dev Get the current snapshotId
           */
          function _getCurrentSnapshotId() internal view virtual returns (uint256) {
              return _currentSnapshotId.current();
          }
          /**
           * @dev Retrieves the balance of `account` at the time `snapshotId` was created.
           */
          function balanceOfAt(address account, uint256 snapshotId) public view virtual returns (uint256) {
              (bool snapshotted, uint256 value) = _valueAt(snapshotId, _accountBalanceSnapshots[account]);
              return snapshotted ? value : balanceOf(account);
          }
          /**
           * @dev Retrieves the total supply at the time `snapshotId` was created.
           */
          function totalSupplyAt(uint256 snapshotId) public view virtual returns (uint256) {
              (bool snapshotted, uint256 value) = _valueAt(snapshotId, _totalSupplySnapshots);
              return snapshotted ? value : totalSupply();
          }
          // Update balance and/or total supply snapshots before the values are modified. This is implemented
          // in the _beforeTokenTransfer hook, which is executed for _mint, _burn, and _transfer operations.
          function _beforeTokenTransfer(
              address from,
              address to,
              uint256 amount
          ) internal virtual override {
              super._beforeTokenTransfer(from, to, amount);
              if (from == address(0)) {
                  // mint
                  _updateAccountSnapshot(to);
                  _updateTotalSupplySnapshot();
              } else if (to == address(0)) {
                  // burn
                  _updateAccountSnapshot(from);
                  _updateTotalSupplySnapshot();
              } else {
                  // transfer
                  _updateAccountSnapshot(from);
                  _updateAccountSnapshot(to);
              }
          }
          function _valueAt(uint256 snapshotId, Snapshots storage snapshots) private view returns (bool, uint256) {
              require(snapshotId > 0, "ERC20Snapshot: id is 0");
              require(snapshotId <= _getCurrentSnapshotId(), "ERC20Snapshot: nonexistent id");
              // When a valid snapshot is queried, there are three possibilities:
              //  a) The queried value was not modified after the snapshot was taken. Therefore, a snapshot entry was never
              //  created for this id, and all stored snapshot ids are smaller than the requested one. The value that corresponds
              //  to this id is the current one.
              //  b) The queried value was modified after the snapshot was taken. Therefore, there will be an entry with the
              //  requested id, and its value is the one to return.
              //  c) More snapshots were created after the requested one, and the queried value was later modified. There will be
              //  no entry for the requested id: the value that corresponds to it is that of the smallest snapshot id that is
              //  larger than the requested one.
              //
              // In summary, we need to find an element in an array, returning the index of the smallest value that is larger if
              // it is not found, unless said value doesn't exist (e.g. when all values are smaller). Arrays.findUpperBound does
              // exactly this.
              uint256 index = snapshots.ids.findUpperBound(snapshotId);
              if (index == snapshots.ids.length) {
                  return (false, 0);
              } else {
                  return (true, snapshots.values[index]);
              }
          }
          function _updateAccountSnapshot(address account) private {
              _updateSnapshot(_accountBalanceSnapshots[account], balanceOf(account));
          }
          function _updateTotalSupplySnapshot() private {
              _updateSnapshot(_totalSupplySnapshots, totalSupply());
          }
          function _updateSnapshot(Snapshots storage snapshots, uint256 currentValue) private {
              uint256 currentId = _getCurrentSnapshotId();
              if (_lastSnapshotId(snapshots.ids) < currentId) {
                  snapshots.ids.push(currentId);
                  snapshots.values.push(currentValue);
              }
          }
          function _lastSnapshotId(uint256[] storage ids) private view returns (uint256) {
              if (ids.length == 0) {
                  return 0;
              } else {
                  return ids[ids.length - 1];
              }
          }
      }
      // SPDX-License-Identifier: MIT
      // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)
      pragma solidity ^0.8.0;
      import "../IERC20.sol";
      /**
       * @dev Interface for the optional metadata functions from the ERC20 standard.
       *
       * _Available since v4.1._
       */
      interface IERC20Metadata is IERC20 {
          /**
           * @dev Returns the name of the token.
           */
          function name() external view returns (string memory);
          /**
           * @dev Returns the symbol of the token.
           */
          function symbol() external view returns (string memory);
          /**
           * @dev Returns the decimals places of the token.
           */
          function decimals() external view returns (uint8);
      }
      // SPDX-License-Identifier: MIT
      // OpenZeppelin Contracts v4.4.1 (token/ERC20/IERC20.sol)
      pragma solidity ^0.8.0;
      /**
       * @dev Interface of the ERC20 standard as defined in the EIP.
       */
      interface IERC20 {
          /**
           * @dev Returns the amount of tokens in existence.
           */
          function totalSupply() external view returns (uint256);
          /**
           * @dev Returns the amount of tokens owned by `account`.
           */
          function balanceOf(address account) external view returns (uint256);
          /**
           * @dev Moves `amount` tokens from the caller's account to `recipient`.
           *
           * Returns a boolean value indicating whether the operation succeeded.
           *
           * Emits a {Transfer} event.
           */
          function transfer(address recipient, uint256 amount) external returns (bool);
          /**
           * @dev Returns the remaining number of tokens that `spender` will be
           * allowed to spend on behalf of `owner` through {transferFrom}. This is
           * zero by default.
           *
           * This value changes when {approve} or {transferFrom} are called.
           */
          function allowance(address owner, address spender) external view returns (uint256);
          /**
           * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
           *
           * Returns a boolean value indicating whether the operation succeeded.
           *
           * IMPORTANT: Beware that changing an allowance with this method brings the risk
           * that someone may use both the old and the new allowance by unfortunate
           * transaction ordering. One possible solution to mitigate this race
           * condition is to first reduce the spender's allowance to 0 and set the
           * desired value afterwards:
           * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
           *
           * Emits an {Approval} event.
           */
          function approve(address spender, uint256 amount) external returns (bool);
          /**
           * @dev Moves `amount` tokens from `sender` to `recipient` using the
           * allowance mechanism. `amount` is then deducted from the caller's
           * allowance.
           *
           * Returns a boolean value indicating whether the operation succeeded.
           *
           * Emits a {Transfer} event.
           */
          function transferFrom(
              address sender,
              address recipient,
              uint256 amount
          ) external returns (bool);
          /**
           * @dev Emitted when `value` tokens are moved from one account (`from`) to
           * another (`to`).
           *
           * Note that `value` may be zero.
           */
          event Transfer(address indexed from, address indexed to, uint256 value);
          /**
           * @dev Emitted when the allowance of a `spender` for an `owner` is set by
           * a call to {approve}. `value` is the new allowance.
           */
          event Approval(address indexed owner, address indexed spender, uint256 value);
      }
      // SPDX-License-Identifier: MIT
      // OpenZeppelin Contracts v4.4.1 (utils/Arrays.sol)
      pragma solidity ^0.8.0;
      import "./math/Math.sol";
      /**
       * @dev Collection of functions related to array types.
       */
      library Arrays {
          /**
           * @dev Searches a sorted `array` and returns the first index that contains
           * a value greater or equal to `element`. If no such index exists (i.e. all
           * values in the array are strictly less than `element`), the array length is
           * returned. Time complexity O(log n).
           *
           * `array` is expected to be sorted in ascending order, and to contain no
           * repeated elements.
           */
          function findUpperBound(uint256[] storage array, uint256 element) internal view returns (uint256) {
              if (array.length == 0) {
                  return 0;
              }
              uint256 low = 0;
              uint256 high = array.length;
              while (low < high) {
                  uint256 mid = Math.average(low, high);
                  // Note that mid will always be strictly less than high (i.e. it will be a valid array index)
                  // because Math.average rounds down (it does integer division with truncation).
                  if (array[mid] > element) {
                      high = mid;
                  } else {
                      low = mid + 1;
                  }
              }
              // At this point `low` is the exclusive upper bound. We will return the inclusive upper bound.
              if (low > 0 && array[low - 1] == element) {
                  return low - 1;
              } else {
                  return low;
              }
          }
      }
      // SPDX-License-Identifier: MIT
      // OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
      pragma solidity ^0.8.0;
      /**
       * @dev Provides information about the current execution context, including the
       * sender of the transaction and its data. While these are generally available
       * via msg.sender and msg.data, they should not be accessed in such a direct
       * manner, since when dealing with meta-transactions the account sending and
       * paying for execution may not be the actual sender (as far as an application
       * is concerned).
       *
       * This contract is only required for intermediate, library-like contracts.
       */
      abstract contract Context {
          function _msgSender() internal view virtual returns (address) {
              return msg.sender;
          }
          function _msgData() internal view virtual returns (bytes calldata) {
              return msg.data;
          }
      }
      // SPDX-License-Identifier: MIT
      // OpenZeppelin Contracts v4.4.1 (utils/Counters.sol)
      pragma solidity ^0.8.0;
      /**
       * @title Counters
       * @author Matt Condon (@shrugs)
       * @dev Provides counters that can only be incremented, decremented or reset. This can be used e.g. to track the number
       * of elements in a mapping, issuing ERC721 ids, or counting request ids.
       *
       * Include with `using Counters for Counters.Counter;`
       */
      library Counters {
          struct Counter {
              // This variable should never be directly accessed by users of the library: interactions must be restricted to
              // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add
              // this feature: see https://github.com/ethereum/solidity/issues/4637
              uint256 _value; // default: 0
          }
          function current(Counter storage counter) internal view returns (uint256) {
              return counter._value;
          }
          function increment(Counter storage counter) internal {
              unchecked {
                  counter._value += 1;
              }
          }
          function decrement(Counter storage counter) internal {
              uint256 value = counter._value;
              require(value > 0, "Counter: decrement overflow");
              unchecked {
                  counter._value = value - 1;
              }
          }
          function reset(Counter storage counter) internal {
              counter._value = 0;
          }
      }
      // SPDX-License-Identifier: MIT
      // OpenZeppelin Contracts v4.4.1 (utils/math/Math.sol)
      pragma solidity ^0.8.0;
      /**
       * @dev Standard math utilities missing in the Solidity language.
       */
      library Math {
          /**
           * @dev Returns the largest of two numbers.
           */
          function max(uint256 a, uint256 b) internal pure returns (uint256) {
              return a >= b ? a : b;
          }
          /**
           * @dev Returns the smallest of two numbers.
           */
          function min(uint256 a, uint256 b) internal pure returns (uint256) {
              return a < b ? a : b;
          }
          /**
           * @dev Returns the average of two numbers. The result is rounded towards
           * zero.
           */
          function average(uint256 a, uint256 b) internal pure returns (uint256) {
              // (a + b) / 2 can overflow.
              return (a & b) + (a ^ b) / 2;
          }
          /**
           * @dev Returns the ceiling of the division of two numbers.
           *
           * This differs from standard division with `/` in that it rounds up instead
           * of rounding down.
           */
          function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
              // (a + b - 1) / b can overflow on addition, so we distribute.
              return a / b + (a % b == 0 ? 0 : 1);
          }
      }
      // SPDX-License-Identifier: MIT
      // OpenZeppelin Contracts v4.4.1 (utils/math/SafeCast.sol)
      pragma solidity ^0.8.0;
      /**
       * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow
       * checks.
       *
       * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can
       * easily result in undesired exploitation or bugs, since developers usually
       * assume that overflows raise errors. `SafeCast` restores this intuition by
       * reverting the transaction when such 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.
       *
       * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing
       * all math on `uint256` and `int256` and then downcasting.
       */
      library SafeCast {
          /**
           * @dev Returns the downcasted uint224 from uint256, reverting on
           * overflow (when the input is greater than largest uint224).
           *
           * Counterpart to Solidity's `uint224` operator.
           *
           * Requirements:
           *
           * - input must fit into 224 bits
           */
          function toUint224(uint256 value) internal pure returns (uint224) {
              require(value <= type(uint224).max, "SafeCast: value doesn't fit in 224 bits");
              return uint224(value);
          }
          /**
           * @dev Returns the downcasted uint128 from uint256, reverting on
           * overflow (when the input is greater than largest uint128).
           *
           * Counterpart to Solidity's `uint128` operator.
           *
           * Requirements:
           *
           * - input must fit into 128 bits
           */
          function toUint128(uint256 value) internal pure returns (uint128) {
              require(value <= type(uint128).max, "SafeCast: value doesn't fit in 128 bits");
              return uint128(value);
          }
          /**
           * @dev Returns the downcasted uint96 from uint256, reverting on
           * overflow (when the input is greater than largest uint96).
           *
           * Counterpart to Solidity's `uint96` operator.
           *
           * Requirements:
           *
           * - input must fit into 96 bits
           */
          function toUint96(uint256 value) internal pure returns (uint96) {
              require(value <= type(uint96).max, "SafeCast: value doesn't fit in 96 bits");
              return uint96(value);
          }
          /**
           * @dev Returns the downcasted uint64 from uint256, reverting on
           * overflow (when the input is greater than largest uint64).
           *
           * Counterpart to Solidity's `uint64` operator.
           *
           * Requirements:
           *
           * - input must fit into 64 bits
           */
          function toUint64(uint256 value) internal pure returns (uint64) {
              require(value <= type(uint64).max, "SafeCast: value doesn't fit in 64 bits");
              return uint64(value);
          }
          /**
           * @dev Returns the downcasted uint32 from uint256, reverting on
           * overflow (when the input is greater than largest uint32).
           *
           * Counterpart to Solidity's `uint32` operator.
           *
           * Requirements:
           *
           * - input must fit into 32 bits
           */
          function toUint32(uint256 value) internal pure returns (uint32) {
              require(value <= type(uint32).max, "SafeCast: value doesn't fit in 32 bits");
              return uint32(value);
          }
          /**
           * @dev Returns the downcasted uint16 from uint256, reverting on
           * overflow (when the input is greater than largest uint16).
           *
           * Counterpart to Solidity's `uint16` operator.
           *
           * Requirements:
           *
           * - input must fit into 16 bits
           */
          function toUint16(uint256 value) internal pure returns (uint16) {
              require(value <= type(uint16).max, "SafeCast: value doesn't fit in 16 bits");
              return uint16(value);
          }
          /**
           * @dev Returns the downcasted uint8 from uint256, reverting on
           * overflow (when the input is greater than largest uint8).
           *
           * Counterpart to Solidity's `uint8` operator.
           *
           * Requirements:
           *
           * - input must fit into 8 bits.
           */
          function toUint8(uint256 value) internal pure returns (uint8) {
              require(value <= type(uint8).max, "SafeCast: value doesn't fit in 8 bits");
              return uint8(value);
          }
          /**
           * @dev Converts a signed int256 into an unsigned uint256.
           *
           * Requirements:
           *
           * - input must be greater than or equal to 0.
           */
          function toUint256(int256 value) internal pure returns (uint256) {
              require(value >= 0, "SafeCast: value must be positive");
              return uint256(value);
          }
          /**
           * @dev Returns the downcasted int128 from int256, reverting on
           * overflow (when the input is less than smallest int128 or
           * greater than largest int128).
           *
           * Counterpart to Solidity's `int128` operator.
           *
           * Requirements:
           *
           * - input must fit into 128 bits
           *
           * _Available since v3.1._
           */
          function toInt128(int256 value) internal pure returns (int128) {
              require(value >= type(int128).min && value <= type(int128).max, "SafeCast: value doesn't fit in 128 bits");
              return int128(value);
          }
          /**
           * @dev Returns the downcasted int64 from int256, reverting on
           * overflow (when the input is less than smallest int64 or
           * greater than largest int64).
           *
           * Counterpart to Solidity's `int64` operator.
           *
           * Requirements:
           *
           * - input must fit into 64 bits
           *
           * _Available since v3.1._
           */
          function toInt64(int256 value) internal pure returns (int64) {
              require(value >= type(int64).min && value <= type(int64).max, "SafeCast: value doesn't fit in 64 bits");
              return int64(value);
          }
          /**
           * @dev Returns the downcasted int32 from int256, reverting on
           * overflow (when the input is less than smallest int32 or
           * greater than largest int32).
           *
           * Counterpart to Solidity's `int32` operator.
           *
           * Requirements:
           *
           * - input must fit into 32 bits
           *
           * _Available since v3.1._
           */
          function toInt32(int256 value) internal pure returns (int32) {
              require(value >= type(int32).min && value <= type(int32).max, "SafeCast: value doesn't fit in 32 bits");
              return int32(value);
          }
          /**
           * @dev Returns the downcasted int16 from int256, reverting on
           * overflow (when the input is less than smallest int16 or
           * greater than largest int16).
           *
           * Counterpart to Solidity's `int16` operator.
           *
           * Requirements:
           *
           * - input must fit into 16 bits
           *
           * _Available since v3.1._
           */
          function toInt16(int256 value) internal pure returns (int16) {
              require(value >= type(int16).min && value <= type(int16).max, "SafeCast: value doesn't fit in 16 bits");
              return int16(value);
          }
          /**
           * @dev Returns the downcasted int8 from int256, reverting on
           * overflow (when the input is less than smallest int8 or
           * greater than largest int8).
           *
           * Counterpart to Solidity's `int8` operator.
           *
           * Requirements:
           *
           * - input must fit into 8 bits.
           *
           * _Available since v3.1._
           */
          function toInt8(int256 value) internal pure returns (int8) {
              require(value >= type(int8).min && value <= type(int8).max, "SafeCast: value doesn't fit in 8 bits");
              return int8(value);
          }
          /**
           * @dev Converts an unsigned uint256 into a signed int256.
           *
           * Requirements:
           *
           * - input must be less than or equal to maxInt256.
           */
          function toInt256(uint256 value) internal pure returns (int256) {
              // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive
              require(value <= uint256(type(int256).max), "SafeCast: value doesn't fit in an int256");
              return int256(value);
          }
      }
      // SPDX-License-Identifier: MIT
      // OpenZeppelin Contracts v4.4.1 (utils/math/SafeMath.sol)
      pragma solidity ^0.8.0;
      // CAUTION
      // This version of SafeMath should only be used with Solidity 0.8 or later,
      // because it relies on the compiler's built in overflow checks.
      /**
       * @dev Wrappers over Solidity's arithmetic operations.
       *
       * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler
       * now has built in overflow checking.
       */
      library SafeMath {
          /**
           * @dev Returns the addition of two unsigned integers, with an overflow flag.
           *
           * _Available since v3.4._
           */
          function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
              unchecked {
                  uint256 c = a + b;
                  if (c < a) return (false, 0);
                  return (true, c);
              }
          }
          /**
           * @dev Returns the substraction of two unsigned integers, with an overflow flag.
           *
           * _Available since v3.4._
           */
          function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
              unchecked {
                  if (b > a) return (false, 0);
                  return (true, a - b);
              }
          }
          /**
           * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
           *
           * _Available since v3.4._
           */
          function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
              unchecked {
                  // 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 (true, 0);
                  uint256 c = a * b;
                  if (c / a != b) return (false, 0);
                  return (true, c);
              }
          }
          /**
           * @dev Returns the division of two unsigned integers, with a division by zero flag.
           *
           * _Available since v3.4._
           */
          function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
              unchecked {
                  if (b == 0) return (false, 0);
                  return (true, a / b);
              }
          }
          /**
           * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
           *
           * _Available since v3.4._
           */
          function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
              unchecked {
                  if (b == 0) return (false, 0);
                  return (true, a % b);
              }
          }
          /**
           * @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) {
              return a + b;
          }
          /**
           * @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) {
              return a - b;
          }
          /**
           * @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) {
              return a * b;
          }
          /**
           * @dev Returns the integer division of two unsigned integers, reverting on
           * division by zero. The result is rounded towards zero.
           *
           * Counterpart to Solidity's `/` operator.
           *
           * Requirements:
           *
           * - The divisor cannot be zero.
           */
          function div(uint256 a, uint256 b) internal pure returns (uint256) {
              return a / b;
          }
          /**
           * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
           * reverting 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) {
              return a % b;
          }
          /**
           * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
           * overflow (when the result is negative).
           *
           * CAUTION: This function is deprecated because it requires allocating memory for the error
           * message unnecessarily. For custom revert reasons use {trySub}.
           *
           * Counterpart to Solidity's `-` operator.
           *
           * Requirements:
           *
           * - Subtraction cannot overflow.
           */
          function sub(
              uint256 a,
              uint256 b,
              string memory errorMessage
          ) internal pure returns (uint256) {
              unchecked {
                  require(b <= a, errorMessage);
                  return a - b;
              }
          }
          /**
           * @dev Returns the integer division of two unsigned integers, reverting with custom message 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,
              string memory errorMessage
          ) internal pure returns (uint256) {
              unchecked {
                  require(b > 0, errorMessage);
                  return a / b;
              }
          }
          /**
           * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
           * reverting with custom message when dividing by zero.
           *
           * CAUTION: This function is deprecated because it requires allocating memory for the error
           * message unnecessarily. For custom revert reasons use {tryMod}.
           *
           * 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,
              string memory errorMessage
          ) internal pure returns (uint256) {
              unchecked {
                  require(b > 0, errorMessage);
                  return a % b;
              }
          }
      }
      // SPDX-License-Identifier: MIT
      // OpenZeppelin Contracts v4.4.1 (utils/math/SignedSafeMath.sol)
      pragma solidity ^0.8.0;
      /**
       * @dev Wrappers over Solidity's arithmetic operations.
       *
       * NOTE: `SignedSafeMath` is no longer needed starting with Solidity 0.8. The compiler
       * now has built in overflow checking.
       */
      library SignedSafeMath {
          /**
           * @dev Returns the multiplication of two signed integers, reverting on
           * overflow.
           *
           * Counterpart to Solidity's `*` operator.
           *
           * Requirements:
           *
           * - Multiplication cannot overflow.
           */
          function mul(int256 a, int256 b) internal pure returns (int256) {
              return a * b;
          }
          /**
           * @dev Returns the integer division of two signed integers. Reverts on
           * division by zero. The result is rounded towards zero.
           *
           * Counterpart to Solidity's `/` operator.
           *
           * Requirements:
           *
           * - The divisor cannot be zero.
           */
          function div(int256 a, int256 b) internal pure returns (int256) {
              return a / b;
          }
          /**
           * @dev Returns the subtraction of two signed integers, reverting on
           * overflow.
           *
           * Counterpart to Solidity's `-` operator.
           *
           * Requirements:
           *
           * - Subtraction cannot overflow.
           */
          function sub(int256 a, int256 b) internal pure returns (int256) {
              return a - b;
          }
          /**
           * @dev Returns the addition of two signed integers, reverting on
           * overflow.
           *
           * Counterpart to Solidity's `+` operator.
           *
           * Requirements:
           *
           * - Addition cannot overflow.
           */
          function add(int256 a, int256 b) internal pure returns (int256) {
              return a + b;
          }
      }
      // SPDX-License-Identifier: AGPL-3.0-only
      pragma solidity ^0.8.0;
      import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
      import "./MultiRole.sol";
      import "../interfaces/ExpandedIERC20.sol";
      /**
       * @title An ERC20 with permissioned burning and minting. The contract deployer will initially
       * be the owner who is capable of adding new roles.
       */
      contract ExpandedERC20 is ExpandedIERC20, ERC20, MultiRole {
          enum Roles {
              // Can set the minter and burner.
              Owner,
              // Addresses that can mint new tokens.
              Minter,
              // Addresses that can burn tokens that address owns.
              Burner
          }
          uint8 _decimals;
          /**
           * @notice Constructs the ExpandedERC20.
           * @param _tokenName The name which describes the new token.
           * @param _tokenSymbol The ticker abbreviation of the name. Ideally < 5 chars.
           * @param _tokenDecimals The number of decimals to define token precision.
           */
          constructor(
              string memory _tokenName,
              string memory _tokenSymbol,
              uint8 _tokenDecimals
          ) ERC20(_tokenName, _tokenSymbol) {
              _decimals = _tokenDecimals;
              _createExclusiveRole(uint256(Roles.Owner), uint256(Roles.Owner), msg.sender);
              _createSharedRole(uint256(Roles.Minter), uint256(Roles.Owner), new address[](0));
              _createSharedRole(uint256(Roles.Burner), uint256(Roles.Owner), new address[](0));
          }
          function decimals() public view virtual override(ERC20) returns (uint8) {
              return _decimals;
          }
          /**
           * @dev Mints `value` tokens to `recipient`, returning true on success.
           * @param recipient address to mint to.
           * @param value amount of tokens to mint.
           * @return True if the mint succeeded, or False.
           */
          function mint(address recipient, uint256 value)
              external
              override
              onlyRoleHolder(uint256(Roles.Minter))
              returns (bool)
          {
              _mint(recipient, value);
              return true;
          }
          /**
           * @dev Burns `value` tokens owned by `msg.sender`.
           * @param value amount of tokens to burn.
           */
          function burn(uint256 value) external override onlyRoleHolder(uint256(Roles.Burner)) {
              _burn(msg.sender, value);
          }
          /**
           * @dev Burns `value` tokens owned by `recipient`.
           * @param recipient address to burn tokens from.
           * @param value amount of tokens to burn.
           * @return True if the burn succeeded, or False.
           */
          function burnFrom(address recipient, uint256 value)
              external
              override
              onlyRoleHolder(uint256(Roles.Burner))
              returns (bool)
          {
              _burn(recipient, value);
              return true;
          }
          /**
           * @notice Add Minter role to account.
           * @dev The caller must have the Owner role.
           * @param account The address to which the Minter role is added.
           */
          function addMinter(address account) external virtual override {
              addMember(uint256(Roles.Minter), account);
          }
          /**
           * @notice Add Burner role to account.
           * @dev The caller must have the Owner role.
           * @param account The address to which the Burner role is added.
           */
          function addBurner(address account) external virtual override {
              addMember(uint256(Roles.Burner), account);
          }
          /**
           * @notice Reset Owner role to account.
           * @dev The caller must have the Owner role.
           * @param account The new holder of the Owner role.
           */
          function resetOwner(address account) external virtual override {
              resetMember(uint256(Roles.Owner), account);
          }
      }
      // SPDX-License-Identifier: AGPL-3.0-only
      pragma solidity ^0.8.0;
      import "@openzeppelin/contracts/utils/math/SafeMath.sol";
      import "@openzeppelin/contracts/utils/math/SignedSafeMath.sol";
      /**
       * @title Library for fixed point arithmetic on uints
       */
      library FixedPoint {
          using SafeMath for uint256;
          using SignedSafeMath for int256;
          // Supports 18 decimals. E.g., 1e18 represents "1", 5e17 represents "0.5".
          // For unsigned values:
          //   This can represent a value up to (2^256 - 1)/10^18 = ~10^59. 10^59 will be stored internally as uint256 10^77.
          uint256 private constant FP_SCALING_FACTOR = 10**18;
          // --------------------------------------- UNSIGNED -----------------------------------------------------------------------------
          struct Unsigned {
              uint256 rawValue;
          }
          /**
           * @notice Constructs an `Unsigned` from an unscaled uint, e.g., `b=5` gets stored internally as `5*(10**18)`.
           * @param a uint to convert into a FixedPoint.
           * @return the converted FixedPoint.
           */
          function fromUnscaledUint(uint256 a) internal pure returns (Unsigned memory) {
              return Unsigned(a.mul(FP_SCALING_FACTOR));
          }
          /**
           * @notice Whether `a` is equal to `b`.
           * @param a a FixedPoint.
           * @param b a uint256.
           * @return True if equal, or False.
           */
          function isEqual(Unsigned memory a, uint256 b) internal pure returns (bool) {
              return a.rawValue == fromUnscaledUint(b).rawValue;
          }
          /**
           * @notice Whether `a` is equal to `b`.
           * @param a a FixedPoint.
           * @param b a FixedPoint.
           * @return True if equal, or False.
           */
          function isEqual(Unsigned memory a, Unsigned memory b) internal pure returns (bool) {
              return a.rawValue == b.rawValue;
          }
          /**
           * @notice Whether `a` is greater than `b`.
           * @param a a FixedPoint.
           * @param b a FixedPoint.
           * @return True if `a > b`, or False.
           */
          function isGreaterThan(Unsigned memory a, Unsigned memory b) internal pure returns (bool) {
              return a.rawValue > b.rawValue;
          }
          /**
           * @notice Whether `a` is greater than `b`.
           * @param a a FixedPoint.
           * @param b a uint256.
           * @return True if `a > b`, or False.
           */
          function isGreaterThan(Unsigned memory a, uint256 b) internal pure returns (bool) {
              return a.rawValue > fromUnscaledUint(b).rawValue;
          }
          /**
           * @notice Whether `a` is greater than `b`.
           * @param a a uint256.
           * @param b a FixedPoint.
           * @return True if `a > b`, or False.
           */
          function isGreaterThan(uint256 a, Unsigned memory b) internal pure returns (bool) {
              return fromUnscaledUint(a).rawValue > b.rawValue;
          }
          /**
           * @notice Whether `a` is greater than or equal to `b`.
           * @param a a FixedPoint.
           * @param b a FixedPoint.
           * @return True if `a >= b`, or False.
           */
          function isGreaterThanOrEqual(Unsigned memory a, Unsigned memory b) internal pure returns (bool) {
              return a.rawValue >= b.rawValue;
          }
          /**
           * @notice Whether `a` is greater than or equal to `b`.
           * @param a a FixedPoint.
           * @param b a uint256.
           * @return True if `a >= b`, or False.
           */
          function isGreaterThanOrEqual(Unsigned memory a, uint256 b) internal pure returns (bool) {
              return a.rawValue >= fromUnscaledUint(b).rawValue;
          }
          /**
           * @notice Whether `a` is greater than or equal to `b`.
           * @param a a uint256.
           * @param b a FixedPoint.
           * @return True if `a >= b`, or False.
           */
          function isGreaterThanOrEqual(uint256 a, Unsigned memory b) internal pure returns (bool) {
              return fromUnscaledUint(a).rawValue >= b.rawValue;
          }
          /**
           * @notice Whether `a` is less than `b`.
           * @param a a FixedPoint.
           * @param b a FixedPoint.
           * @return True if `a < b`, or False.
           */
          function isLessThan(Unsigned memory a, Unsigned memory b) internal pure returns (bool) {
              return a.rawValue < b.rawValue;
          }
          /**
           * @notice Whether `a` is less than `b`.
           * @param a a FixedPoint.
           * @param b a uint256.
           * @return True if `a < b`, or False.
           */
          function isLessThan(Unsigned memory a, uint256 b) internal pure returns (bool) {
              return a.rawValue < fromUnscaledUint(b).rawValue;
          }
          /**
           * @notice Whether `a` is less than `b`.
           * @param a a uint256.
           * @param b a FixedPoint.
           * @return True if `a < b`, or False.
           */
          function isLessThan(uint256 a, Unsigned memory b) internal pure returns (bool) {
              return fromUnscaledUint(a).rawValue < b.rawValue;
          }
          /**
           * @notice Whether `a` is less than or equal to `b`.
           * @param a a FixedPoint.
           * @param b a FixedPoint.
           * @return True if `a <= b`, or False.
           */
          function isLessThanOrEqual(Unsigned memory a, Unsigned memory b) internal pure returns (bool) {
              return a.rawValue <= b.rawValue;
          }
          /**
           * @notice Whether `a` is less than or equal to `b`.
           * @param a a FixedPoint.
           * @param b a uint256.
           * @return True if `a <= b`, or False.
           */
          function isLessThanOrEqual(Unsigned memory a, uint256 b) internal pure returns (bool) {
              return a.rawValue <= fromUnscaledUint(b).rawValue;
          }
          /**
           * @notice Whether `a` is less than or equal to `b`.
           * @param a a uint256.
           * @param b a FixedPoint.
           * @return True if `a <= b`, or False.
           */
          function isLessThanOrEqual(uint256 a, Unsigned memory b) internal pure returns (bool) {
              return fromUnscaledUint(a).rawValue <= b.rawValue;
          }
          /**
           * @notice The minimum of `a` and `b`.
           * @param a a FixedPoint.
           * @param b a FixedPoint.
           * @return the minimum of `a` and `b`.
           */
          function min(Unsigned memory a, Unsigned memory b) internal pure returns (Unsigned memory) {
              return a.rawValue < b.rawValue ? a : b;
          }
          /**
           * @notice The maximum of `a` and `b`.
           * @param a a FixedPoint.
           * @param b a FixedPoint.
           * @return the maximum of `a` and `b`.
           */
          function max(Unsigned memory a, Unsigned memory b) internal pure returns (Unsigned memory) {
              return a.rawValue > b.rawValue ? a : b;
          }
          /**
           * @notice Adds two `Unsigned`s, reverting on overflow.
           * @param a a FixedPoint.
           * @param b a FixedPoint.
           * @return the sum of `a` and `b`.
           */
          function add(Unsigned memory a, Unsigned memory b) internal pure returns (Unsigned memory) {
              return Unsigned(a.rawValue.add(b.rawValue));
          }
          /**
           * @notice Adds an `Unsigned` to an unscaled uint, reverting on overflow.
           * @param a a FixedPoint.
           * @param b a uint256.
           * @return the sum of `a` and `b`.
           */
          function add(Unsigned memory a, uint256 b) internal pure returns (Unsigned memory) {
              return add(a, fromUnscaledUint(b));
          }
          /**
           * @notice Subtracts two `Unsigned`s, reverting on overflow.
           * @param a a FixedPoint.
           * @param b a FixedPoint.
           * @return the difference of `a` and `b`.
           */
          function sub(Unsigned memory a, Unsigned memory b) internal pure returns (Unsigned memory) {
              return Unsigned(a.rawValue.sub(b.rawValue));
          }
          /**
           * @notice Subtracts an unscaled uint256 from an `Unsigned`, reverting on overflow.
           * @param a a FixedPoint.
           * @param b a uint256.
           * @return the difference of `a` and `b`.
           */
          function sub(Unsigned memory a, uint256 b) internal pure returns (Unsigned memory) {
              return sub(a, fromUnscaledUint(b));
          }
          /**
           * @notice Subtracts an `Unsigned` from an unscaled uint256, reverting on overflow.
           * @param a a uint256.
           * @param b a FixedPoint.
           * @return the difference of `a` and `b`.
           */
          function sub(uint256 a, Unsigned memory b) internal pure returns (Unsigned memory) {
              return sub(fromUnscaledUint(a), b);
          }
          /**
           * @notice Multiplies two `Unsigned`s, reverting on overflow.
           * @dev This will "floor" the product.
           * @param a a FixedPoint.
           * @param b a FixedPoint.
           * @return the product of `a` and `b`.
           */
          function mul(Unsigned memory a, Unsigned memory b) internal pure returns (Unsigned memory) {
              // There are two caveats with this computation:
              // 1. Max output for the represented number is ~10^41, otherwise an intermediate value overflows. 10^41 is
              // stored internally as a uint256 ~10^59.
              // 2. Results that can't be represented exactly are truncated not rounded. E.g., 1.4 * 2e-18 = 2.8e-18, which
              // would round to 3, but this computation produces the result 2.
              // No need to use SafeMath because FP_SCALING_FACTOR != 0.
              return Unsigned(a.rawValue.mul(b.rawValue) / FP_SCALING_FACTOR);
          }
          /**
           * @notice Multiplies an `Unsigned` and an unscaled uint256, reverting on overflow.
           * @dev This will "floor" the product.
           * @param a a FixedPoint.
           * @param b a uint256.
           * @return the product of `a` and `b`.
           */
          function mul(Unsigned memory a, uint256 b) internal pure returns (Unsigned memory) {
              return Unsigned(a.rawValue.mul(b));
          }
          /**
           * @notice Multiplies two `Unsigned`s and "ceil's" the product, reverting on overflow.
           * @param a a FixedPoint.
           * @param b a FixedPoint.
           * @return the product of `a` and `b`.
           */
          function mulCeil(Unsigned memory a, Unsigned memory b) internal pure returns (Unsigned memory) {
              uint256 mulRaw = a.rawValue.mul(b.rawValue);
              uint256 mulFloor = mulRaw / FP_SCALING_FACTOR;
              uint256 mod = mulRaw.mod(FP_SCALING_FACTOR);
              if (mod != 0) {
                  return Unsigned(mulFloor.add(1));
              } else {
                  return Unsigned(mulFloor);
              }
          }
          /**
           * @notice Multiplies an `Unsigned` and an unscaled uint256 and "ceil's" the product, reverting on overflow.
           * @param a a FixedPoint.
           * @param b a FixedPoint.
           * @return the product of `a` and `b`.
           */
          function mulCeil(Unsigned memory a, uint256 b) internal pure returns (Unsigned memory) {
              // Since b is an uint, there is no risk of truncation and we can just mul it normally
              return Unsigned(a.rawValue.mul(b));
          }
          /**
           * @notice Divides one `Unsigned` by an `Unsigned`, reverting on overflow or division by 0.
           * @dev This will "floor" the quotient.
           * @param a a FixedPoint numerator.
           * @param b a FixedPoint denominator.
           * @return the quotient of `a` divided by `b`.
           */
          function div(Unsigned memory a, Unsigned memory b) internal pure returns (Unsigned memory) {
              // There are two caveats with this computation:
              // 1. Max value for the number dividend `a` represents is ~10^41, otherwise an intermediate value overflows.
              // 10^41 is stored internally as a uint256 10^59.
              // 2. Results that can't be represented exactly are truncated not rounded. E.g., 2 / 3 = 0.6 repeating, which
              // would round to 0.666666666666666667, but this computation produces the result 0.666666666666666666.
              return Unsigned(a.rawValue.mul(FP_SCALING_FACTOR).div(b.rawValue));
          }
          /**
           * @notice Divides one `Unsigned` by an unscaled uint256, reverting on overflow or division by 0.
           * @dev This will "floor" the quotient.
           * @param a a FixedPoint numerator.
           * @param b a uint256 denominator.
           * @return the quotient of `a` divided by `b`.
           */
          function div(Unsigned memory a, uint256 b) internal pure returns (Unsigned memory) {
              return Unsigned(a.rawValue.div(b));
          }
          /**
           * @notice Divides one unscaled uint256 by an `Unsigned`, reverting on overflow or division by 0.
           * @dev This will "floor" the quotient.
           * @param a a uint256 numerator.
           * @param b a FixedPoint denominator.
           * @return the quotient of `a` divided by `b`.
           */
          function div(uint256 a, Unsigned memory b) internal pure returns (Unsigned memory) {
              return div(fromUnscaledUint(a), b);
          }
          /**
           * @notice Divides one `Unsigned` by an `Unsigned` and "ceil's" the quotient, reverting on overflow or division by 0.
           * @param a a FixedPoint numerator.
           * @param b a FixedPoint denominator.
           * @return the quotient of `a` divided by `b`.
           */
          function divCeil(Unsigned memory a, Unsigned memory b) internal pure returns (Unsigned memory) {
              uint256 aScaled = a.rawValue.mul(FP_SCALING_FACTOR);
              uint256 divFloor = aScaled.div(b.rawValue);
              uint256 mod = aScaled.mod(b.rawValue);
              if (mod != 0) {
                  return Unsigned(divFloor.add(1));
              } else {
                  return Unsigned(divFloor);
              }
          }
          /**
           * @notice Divides one `Unsigned` by an unscaled uint256 and "ceil's" the quotient, reverting on overflow or division by 0.
           * @param a a FixedPoint numerator.
           * @param b a uint256 denominator.
           * @return the quotient of `a` divided by `b`.
           */
          function divCeil(Unsigned memory a, uint256 b) internal pure returns (Unsigned memory) {
              // Because it is possible that a quotient gets truncated, we can't just call "Unsigned(a.rawValue.div(b))"
              // similarly to mulCeil with a uint256 as the second parameter. Therefore we need to convert b into an Unsigned.
              // This creates the possibility of overflow if b is very large.
              return divCeil(a, fromUnscaledUint(b));
          }
          /**
           * @notice Raises an `Unsigned` to the power of an unscaled uint256, reverting on overflow. E.g., `b=2` squares `a`.
           * @dev This will "floor" the result.
           * @param a a FixedPoint numerator.
           * @param b a uint256 denominator.
           * @return output is `a` to the power of `b`.
           */
          function pow(Unsigned memory a, uint256 b) internal pure returns (Unsigned memory output) {
              output = fromUnscaledUint(1);
              for (uint256 i = 0; i < b; i = i.add(1)) {
                  output = mul(output, a);
              }
          }
          // ------------------------------------------------- SIGNED -------------------------------------------------------------
          // Supports 18 decimals. E.g., 1e18 represents "1", 5e17 represents "0.5".
          // For signed values:
          //   This can represent a value up (or down) to +-(2^255 - 1)/10^18 = ~10^58. 10^58 will be stored internally as int256 10^76.
          int256 private constant SFP_SCALING_FACTOR = 10**18;
          struct Signed {
              int256 rawValue;
          }
          function fromSigned(Signed memory a) internal pure returns (Unsigned memory) {
              require(a.rawValue >= 0, "Negative value provided");
              return Unsigned(uint256(a.rawValue));
          }
          function fromUnsigned(Unsigned memory a) internal pure returns (Signed memory) {
              require(a.rawValue <= uint256(type(int256).max), "Unsigned too large");
              return Signed(int256(a.rawValue));
          }
          /**
           * @notice Constructs a `Signed` from an unscaled int, e.g., `b=5` gets stored internally as `5*(10**18)`.
           * @param a int to convert into a FixedPoint.Signed.
           * @return the converted FixedPoint.Signed.
           */
          function fromUnscaledInt(int256 a) internal pure returns (Signed memory) {
              return Signed(a.mul(SFP_SCALING_FACTOR));
          }
          /**
           * @notice Whether `a` is equal to `b`.
           * @param a a FixedPoint.Signed.
           * @param b a int256.
           * @return True if equal, or False.
           */
          function isEqual(Signed memory a, int256 b) internal pure returns (bool) {
              return a.rawValue == fromUnscaledInt(b).rawValue;
          }
          /**
           * @notice Whether `a` is equal to `b`.
           * @param a a FixedPoint.Signed.
           * @param b a FixedPoint.Signed.
           * @return True if equal, or False.
           */
          function isEqual(Signed memory a, Signed memory b) internal pure returns (bool) {
              return a.rawValue == b.rawValue;
          }
          /**
           * @notice Whether `a` is greater than `b`.
           * @param a a FixedPoint.Signed.
           * @param b a FixedPoint.Signed.
           * @return True if `a > b`, or False.
           */
          function isGreaterThan(Signed memory a, Signed memory b) internal pure returns (bool) {
              return a.rawValue > b.rawValue;
          }
          /**
           * @notice Whether `a` is greater than `b`.
           * @param a a FixedPoint.Signed.
           * @param b an int256.
           * @return True if `a > b`, or False.
           */
          function isGreaterThan(Signed memory a, int256 b) internal pure returns (bool) {
              return a.rawValue > fromUnscaledInt(b).rawValue;
          }
          /**
           * @notice Whether `a` is greater than `b`.
           * @param a an int256.
           * @param b a FixedPoint.Signed.
           * @return True if `a > b`, or False.
           */
          function isGreaterThan(int256 a, Signed memory b) internal pure returns (bool) {
              return fromUnscaledInt(a).rawValue > b.rawValue;
          }
          /**
           * @notice Whether `a` is greater than or equal to `b`.
           * @param a a FixedPoint.Signed.
           * @param b a FixedPoint.Signed.
           * @return True if `a >= b`, or False.
           */
          function isGreaterThanOrEqual(Signed memory a, Signed memory b) internal pure returns (bool) {
              return a.rawValue >= b.rawValue;
          }
          /**
           * @notice Whether `a` is greater than or equal to `b`.
           * @param a a FixedPoint.Signed.
           * @param b an int256.
           * @return True if `a >= b`, or False.
           */
          function isGreaterThanOrEqual(Signed memory a, int256 b) internal pure returns (bool) {
              return a.rawValue >= fromUnscaledInt(b).rawValue;
          }
          /**
           * @notice Whether `a` is greater than or equal to `b`.
           * @param a an int256.
           * @param b a FixedPoint.Signed.
           * @return True if `a >= b`, or False.
           */
          function isGreaterThanOrEqual(int256 a, Signed memory b) internal pure returns (bool) {
              return fromUnscaledInt(a).rawValue >= b.rawValue;
          }
          /**
           * @notice Whether `a` is less than `b`.
           * @param a a FixedPoint.Signed.
           * @param b a FixedPoint.Signed.
           * @return True if `a < b`, or False.
           */
          function isLessThan(Signed memory a, Signed memory b) internal pure returns (bool) {
              return a.rawValue < b.rawValue;
          }
          /**
           * @notice Whether `a` is less than `b`.
           * @param a a FixedPoint.Signed.
           * @param b an int256.
           * @return True if `a < b`, or False.
           */
          function isLessThan(Signed memory a, int256 b) internal pure returns (bool) {
              return a.rawValue < fromUnscaledInt(b).rawValue;
          }
          /**
           * @notice Whether `a` is less than `b`.
           * @param a an int256.
           * @param b a FixedPoint.Signed.
           * @return True if `a < b`, or False.
           */
          function isLessThan(int256 a, Signed memory b) internal pure returns (bool) {
              return fromUnscaledInt(a).rawValue < b.rawValue;
          }
          /**
           * @notice Whether `a` is less than or equal to `b`.
           * @param a a FixedPoint.Signed.
           * @param b a FixedPoint.Signed.
           * @return True if `a <= b`, or False.
           */
          function isLessThanOrEqual(Signed memory a, Signed memory b) internal pure returns (bool) {
              return a.rawValue <= b.rawValue;
          }
          /**
           * @notice Whether `a` is less than or equal to `b`.
           * @param a a FixedPoint.Signed.
           * @param b an int256.
           * @return True if `a <= b`, or False.
           */
          function isLessThanOrEqual(Signed memory a, int256 b) internal pure returns (bool) {
              return a.rawValue <= fromUnscaledInt(b).rawValue;
          }
          /**
           * @notice Whether `a` is less than or equal to `b`.
           * @param a an int256.
           * @param b a FixedPoint.Signed.
           * @return True if `a <= b`, or False.
           */
          function isLessThanOrEqual(int256 a, Signed memory b) internal pure returns (bool) {
              return fromUnscaledInt(a).rawValue <= b.rawValue;
          }
          /**
           * @notice The minimum of `a` and `b`.
           * @param a a FixedPoint.Signed.
           * @param b a FixedPoint.Signed.
           * @return the minimum of `a` and `b`.
           */
          function min(Signed memory a, Signed memory b) internal pure returns (Signed memory) {
              return a.rawValue < b.rawValue ? a : b;
          }
          /**
           * @notice The maximum of `a` and `b`.
           * @param a a FixedPoint.Signed.
           * @param b a FixedPoint.Signed.
           * @return the maximum of `a` and `b`.
           */
          function max(Signed memory a, Signed memory b) internal pure returns (Signed memory) {
              return a.rawValue > b.rawValue ? a : b;
          }
          /**
           * @notice Adds two `Signed`s, reverting on overflow.
           * @param a a FixedPoint.Signed.
           * @param b a FixedPoint.Signed.
           * @return the sum of `a` and `b`.
           */
          function add(Signed memory a, Signed memory b) internal pure returns (Signed memory) {
              return Signed(a.rawValue.add(b.rawValue));
          }
          /**
           * @notice Adds an `Signed` to an unscaled int, reverting on overflow.
           * @param a a FixedPoint.Signed.
           * @param b an int256.
           * @return the sum of `a` and `b`.
           */
          function add(Signed memory a, int256 b) internal pure returns (Signed memory) {
              return add(a, fromUnscaledInt(b));
          }
          /**
           * @notice Subtracts two `Signed`s, reverting on overflow.
           * @param a a FixedPoint.Signed.
           * @param b a FixedPoint.Signed.
           * @return the difference of `a` and `b`.
           */
          function sub(Signed memory a, Signed memory b) internal pure returns (Signed memory) {
              return Signed(a.rawValue.sub(b.rawValue));
          }
          /**
           * @notice Subtracts an unscaled int256 from an `Signed`, reverting on overflow.
           * @param a a FixedPoint.Signed.
           * @param b an int256.
           * @return the difference of `a` and `b`.
           */
          function sub(Signed memory a, int256 b) internal pure returns (Signed memory) {
              return sub(a, fromUnscaledInt(b));
          }
          /**
           * @notice Subtracts an `Signed` from an unscaled int256, reverting on overflow.
           * @param a an int256.
           * @param b a FixedPoint.Signed.
           * @return the difference of `a` and `b`.
           */
          function sub(int256 a, Signed memory b) internal pure returns (Signed memory) {
              return sub(fromUnscaledInt(a), b);
          }
          /**
           * @notice Multiplies two `Signed`s, reverting on overflow.
           * @dev This will "floor" the product.
           * @param a a FixedPoint.Signed.
           * @param b a FixedPoint.Signed.
           * @return the product of `a` and `b`.
           */
          function mul(Signed memory a, Signed memory b) internal pure returns (Signed memory) {
              // There are two caveats with this computation:
              // 1. Max output for the represented number is ~10^41, otherwise an intermediate value overflows. 10^41 is
              // stored internally as an int256 ~10^59.
              // 2. Results that can't be represented exactly are truncated not rounded. E.g., 1.4 * 2e-18 = 2.8e-18, which
              // would round to 3, but this computation produces the result 2.
              // No need to use SafeMath because SFP_SCALING_FACTOR != 0.
              return Signed(a.rawValue.mul(b.rawValue) / SFP_SCALING_FACTOR);
          }
          /**
           * @notice Multiplies an `Signed` and an unscaled int256, reverting on overflow.
           * @dev This will "floor" the product.
           * @param a a FixedPoint.Signed.
           * @param b an int256.
           * @return the product of `a` and `b`.
           */
          function mul(Signed memory a, int256 b) internal pure returns (Signed memory) {
              return Signed(a.rawValue.mul(b));
          }
          /**
           * @notice Multiplies two `Signed`s and "ceil's" the product, reverting on overflow.
           * @param a a FixedPoint.Signed.
           * @param b a FixedPoint.Signed.
           * @return the product of `a` and `b`.
           */
          function mulAwayFromZero(Signed memory a, Signed memory b) internal pure returns (Signed memory) {
              int256 mulRaw = a.rawValue.mul(b.rawValue);
              int256 mulTowardsZero = mulRaw / SFP_SCALING_FACTOR;
              // Manual mod because SignedSafeMath doesn't support it.
              int256 mod = mulRaw % SFP_SCALING_FACTOR;
              if (mod != 0) {
                  bool isResultPositive = isLessThan(a, 0) == isLessThan(b, 0);
                  int256 valueToAdd = isResultPositive ? int256(1) : int256(-1);
                  return Signed(mulTowardsZero.add(valueToAdd));
              } else {
                  return Signed(mulTowardsZero);
              }
          }
          /**
           * @notice Multiplies an `Signed` and an unscaled int256 and "ceil's" the product, reverting on overflow.
           * @param a a FixedPoint.Signed.
           * @param b a FixedPoint.Signed.
           * @return the product of `a` and `b`.
           */
          function mulAwayFromZero(Signed memory a, int256 b) internal pure returns (Signed memory) {
              // Since b is an int, there is no risk of truncation and we can just mul it normally
              return Signed(a.rawValue.mul(b));
          }
          /**
           * @notice Divides one `Signed` by an `Signed`, reverting on overflow or division by 0.
           * @dev This will "floor" the quotient.
           * @param a a FixedPoint numerator.
           * @param b a FixedPoint denominator.
           * @return the quotient of `a` divided by `b`.
           */
          function div(Signed memory a, Signed memory b) internal pure returns (Signed memory) {
              // There are two caveats with this computation:
              // 1. Max value for the number dividend `a` represents is ~10^41, otherwise an intermediate value overflows.
              // 10^41 is stored internally as an int256 10^59.
              // 2. Results that can't be represented exactly are truncated not rounded. E.g., 2 / 3 = 0.6 repeating, which
              // would round to 0.666666666666666667, but this computation produces the result 0.666666666666666666.
              return Signed(a.rawValue.mul(SFP_SCALING_FACTOR).div(b.rawValue));
          }
          /**
           * @notice Divides one `Signed` by an unscaled int256, reverting on overflow or division by 0.
           * @dev This will "floor" the quotient.
           * @param a a FixedPoint numerator.
           * @param b an int256 denominator.
           * @return the quotient of `a` divided by `b`.
           */
          function div(Signed memory a, int256 b) internal pure returns (Signed memory) {
              return Signed(a.rawValue.div(b));
          }
          /**
           * @notice Divides one unscaled int256 by an `Signed`, reverting on overflow or division by 0.
           * @dev This will "floor" the quotient.
           * @param a an int256 numerator.
           * @param b a FixedPoint denominator.
           * @return the quotient of `a` divided by `b`.
           */
          function div(int256 a, Signed memory b) internal pure returns (Signed memory) {
              return div(fromUnscaledInt(a), b);
          }
          /**
           * @notice Divides one `Signed` by an `Signed` and "ceil's" the quotient, reverting on overflow or division by 0.
           * @param a a FixedPoint numerator.
           * @param b a FixedPoint denominator.
           * @return the quotient of `a` divided by `b`.
           */
          function divAwayFromZero(Signed memory a, Signed memory b) internal pure returns (Signed memory) {
              int256 aScaled = a.rawValue.mul(SFP_SCALING_FACTOR);
              int256 divTowardsZero = aScaled.div(b.rawValue);
              // Manual mod because SignedSafeMath doesn't support it.
              int256 mod = aScaled % b.rawValue;
              if (mod != 0) {
                  bool isResultPositive = isLessThan(a, 0) == isLessThan(b, 0);
                  int256 valueToAdd = isResultPositive ? int256(1) : int256(-1);
                  return Signed(divTowardsZero.add(valueToAdd));
              } else {
                  return Signed(divTowardsZero);
              }
          }
          /**
           * @notice Divides one `Signed` by an unscaled int256 and "ceil's" the quotient, reverting on overflow or division by 0.
           * @param a a FixedPoint numerator.
           * @param b an int256 denominator.
           * @return the quotient of `a` divided by `b`.
           */
          function divAwayFromZero(Signed memory a, int256 b) internal pure returns (Signed memory) {
              // Because it is possible that a quotient gets truncated, we can't just call "Signed(a.rawValue.div(b))"
              // similarly to mulCeil with an int256 as the second parameter. Therefore we need to convert b into an Signed.
              // This creates the possibility of overflow if b is very large.
              return divAwayFromZero(a, fromUnscaledInt(b));
          }
          /**
           * @notice Raises an `Signed` to the power of an unscaled uint256, reverting on overflow. E.g., `b=2` squares `a`.
           * @dev This will "floor" the result.
           * @param a a FixedPoint.Signed.
           * @param b a uint256 (negative exponents are not allowed).
           * @return output is `a` to the power of `b`.
           */
          function pow(Signed memory a, uint256 b) internal pure returns (Signed memory output) {
              output = fromUnscaledInt(1);
              for (uint256 i = 0; i < b; i = i.add(1)) {
                  output = mul(output, a);
              }
          }
      }
      // SPDX-License-Identifier: AGPL-3.0-only
      pragma solidity ^0.8.0;
      /**
       * @title A contract that provides modifiers to prevent reentrancy to state-changing and view-only methods. This contract
       * is inspired by https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/ReentrancyGuard.sol
       * and https://github.com/balancer-labs/balancer-core/blob/master/contracts/BPool.sol.
       */
      contract Lockable {
          bool private _notEntered;
          constructor() {
              // Storing an initial non-zero value makes deployment a bit more expensive, but in exchange the refund on every
              // call to nonReentrant will be lower in amount. Since refunds are capped to a percentage of the total
              // transaction's gas, it is best to keep them low in cases like this one, to increase the likelihood of the full
              // refund coming into effect.
              _notEntered = true;
          }
          /**
           * @dev Prevents a contract from calling itself, directly or indirectly.
           * Calling a `nonReentrant` function from another `nonReentrant` function is not supported. It is possible to
           * prevent this from happening by making the `nonReentrant` function external, and making it call a `private`
           * function that does the actual state modification.
           */
          modifier nonReentrant() {
              _preEntranceCheck();
              _preEntranceSet();
              _;
              _postEntranceReset();
          }
          /**
           * @dev Designed to prevent a view-only method from being re-entered during a call to a `nonReentrant()` state-changing method.
           */
          modifier nonReentrantView() {
              _preEntranceCheck();
              _;
          }
          // Internal methods are used to avoid copying the require statement's bytecode to every `nonReentrant()` method.
          // On entry into a function, `_preEntranceCheck()` should always be called to check if the function is being
          // re-entered. Then, if the function modifies state, it should call `_postEntranceSet()`, perform its logic, and
          // then call `_postEntranceReset()`.
          // View-only methods can simply call `_preEntranceCheck()` to make sure that it is not being re-entered.
          function _preEntranceCheck() internal view {
              // On the first call to nonReentrant, _notEntered will be true
              require(_notEntered, "ReentrancyGuard: reentrant call");
          }
          function _preEntranceSet() internal {
              // Any calls to nonReentrant after this point will fail
              _notEntered = false;
          }
          function _postEntranceReset() internal {
              // By storing the original value once again, a refund is triggered (see
              // https://eips.ethereum.org/EIPS/eip-2200)
              _notEntered = true;
          }
          // These functions are intended to be used by child contracts to temporarily disable and re-enable the guard.
          // Intended use:
          // _startReentrantGuardDisabled();
          // ...
          // _endReentrantGuardDisabled();
          //
          // IMPORTANT: these should NEVER be used in a method that isn't inside a nonReentrant block. Otherwise, it's
          // possible to permanently lock your contract.
          function _startReentrantGuardDisabled() internal {
              _notEntered = true;
          }
          function _endReentrantGuardDisabled() internal {
              _notEntered = false;
          }
      }
      // SPDX-License-Identifier: AGPL-3.0-only
      pragma solidity ^0.8.0;
      // This contract is taken from Uniswap's multi call implementation (https://github.com/Uniswap/uniswap-v3-periphery/blob/main/contracts/base/Multicall.sol)
      // and was modified to be solidity 0.8 compatible. Additionally, the method was restricted to only work with msg.value
      // set to 0 to avoid any nasty attack vectors on function calls that use value sent with deposits.
      /// @title MultiCaller
      /// @notice Enables calling multiple methods in a single call to the contract
      contract MultiCaller {
          function multicall(bytes[] calldata data) external returns (bytes[] memory results) {
              results = new bytes[](data.length);
              for (uint256 i = 0; i < data.length; i++) {
                  (bool success, bytes memory result) = address(this).delegatecall(data[i]);
                  if (!success) {
                      // Next 5 lines from https://ethereum.stackexchange.com/a/83577
                      if (result.length < 68) revert();
                      assembly {
                          result := add(result, 0x04)
                      }
                      revert(abi.decode(result, (string)));
                  }
                  results[i] = result;
              }
          }
      }
      // SPDX-License-Identifier: AGPL-3.0-only
      pragma solidity ^0.8.0;
      library Exclusive {
          struct RoleMembership {
              address member;
          }
          function isMember(RoleMembership storage roleMembership, address memberToCheck) internal view returns (bool) {
              return roleMembership.member == memberToCheck;
          }
          function resetMember(RoleMembership storage roleMembership, address newMember) internal {
              require(newMember != address(0x0), "Cannot set an exclusive role to 0x0");
              roleMembership.member = newMember;
          }
          function getMember(RoleMembership storage roleMembership) internal view returns (address) {
              return roleMembership.member;
          }
          function init(RoleMembership storage roleMembership, address initialMember) internal {
              resetMember(roleMembership, initialMember);
          }
      }
      library Shared {
          struct RoleMembership {
              mapping(address => bool) members;
          }
          function isMember(RoleMembership storage roleMembership, address memberToCheck) internal view returns (bool) {
              return roleMembership.members[memberToCheck];
          }
          function addMember(RoleMembership storage roleMembership, address memberToAdd) internal {
              require(memberToAdd != address(0x0), "Cannot add 0x0 to a shared role");
              roleMembership.members[memberToAdd] = true;
          }
          function removeMember(RoleMembership storage roleMembership, address memberToRemove) internal {
              roleMembership.members[memberToRemove] = false;
          }
          function init(RoleMembership storage roleMembership, address[] memory initialMembers) internal {
              for (uint256 i = 0; i < initialMembers.length; i++) {
                  addMember(roleMembership, initialMembers[i]);
              }
          }
      }
      /**
       * @title Base class to manage permissions for the derived class.
       */
      abstract contract MultiRole {
          using Exclusive for Exclusive.RoleMembership;
          using Shared for Shared.RoleMembership;
          enum RoleType { Invalid, Exclusive, Shared }
          struct Role {
              uint256 managingRole;
              RoleType roleType;
              Exclusive.RoleMembership exclusiveRoleMembership;
              Shared.RoleMembership sharedRoleMembership;
          }
          mapping(uint256 => Role) private roles;
          event ResetExclusiveMember(uint256 indexed roleId, address indexed newMember, address indexed manager);
          event AddedSharedMember(uint256 indexed roleId, address indexed newMember, address indexed manager);
          event RemovedSharedMember(uint256 indexed roleId, address indexed oldMember, address indexed manager);
          /**
           * @notice Reverts unless the caller is a member of the specified roleId.
           */
          modifier onlyRoleHolder(uint256 roleId) {
              require(holdsRole(roleId, msg.sender), "Sender does not hold required role");
              _;
          }
          /**
           * @notice Reverts unless the caller is a member of the manager role for the specified roleId.
           */
          modifier onlyRoleManager(uint256 roleId) {
              require(holdsRole(roles[roleId].managingRole, msg.sender), "Can only be called by a role manager");
              _;
          }
          /**
           * @notice Reverts unless the roleId represents an initialized, exclusive roleId.
           */
          modifier onlyExclusive(uint256 roleId) {
              require(roles[roleId].roleType == RoleType.Exclusive, "Must be called on an initialized Exclusive role");
              _;
          }
          /**
           * @notice Reverts unless the roleId represents an initialized, shared roleId.
           */
          modifier onlyShared(uint256 roleId) {
              require(roles[roleId].roleType == RoleType.Shared, "Must be called on an initialized Shared role");
              _;
          }
          /**
           * @notice Whether `memberToCheck` is a member of roleId.
           * @dev Reverts if roleId does not correspond to an initialized role.
           * @param roleId the Role to check.
           * @param memberToCheck the address to check.
           * @return True if `memberToCheck` is a member of `roleId`.
           */
          function holdsRole(uint256 roleId, address memberToCheck) public view returns (bool) {
              Role storage role = roles[roleId];
              if (role.roleType == RoleType.Exclusive) {
                  return role.exclusiveRoleMembership.isMember(memberToCheck);
              } else if (role.roleType == RoleType.Shared) {
                  return role.sharedRoleMembership.isMember(memberToCheck);
              }
              revert("Invalid roleId");
          }
          /**
           * @notice Changes the exclusive role holder of `roleId` to `newMember`.
           * @dev Reverts if the caller is not a member of the managing role for `roleId` or if `roleId` is not an
           * initialized, ExclusiveRole.
           * @param roleId the ExclusiveRole membership to modify.
           * @param newMember the new ExclusiveRole member.
           */
          function resetMember(uint256 roleId, address newMember) public onlyExclusive(roleId) onlyRoleManager(roleId) {
              roles[roleId].exclusiveRoleMembership.resetMember(newMember);
              emit ResetExclusiveMember(roleId, newMember, msg.sender);
          }
          /**
           * @notice Gets the current holder of the exclusive role, `roleId`.
           * @dev Reverts if `roleId` does not represent an initialized, exclusive role.
           * @param roleId the ExclusiveRole membership to check.
           * @return the address of the current ExclusiveRole member.
           */
          function getMember(uint256 roleId) public view onlyExclusive(roleId) returns (address) {
              return roles[roleId].exclusiveRoleMembership.getMember();
          }
          /**
           * @notice Adds `newMember` to the shared role, `roleId`.
           * @dev Reverts if `roleId` does not represent an initialized, SharedRole or if the caller is not a member of the
           * managing role for `roleId`.
           * @param roleId the SharedRole membership to modify.
           * @param newMember the new SharedRole member.
           */
          function addMember(uint256 roleId, address newMember) public onlyShared(roleId) onlyRoleManager(roleId) {
              roles[roleId].sharedRoleMembership.addMember(newMember);
              emit AddedSharedMember(roleId, newMember, msg.sender);
          }
          /**
           * @notice Removes `memberToRemove` from the shared role, `roleId`.
           * @dev Reverts if `roleId` does not represent an initialized, SharedRole or if the caller is not a member of the
           * managing role for `roleId`.
           * @param roleId the SharedRole membership to modify.
           * @param memberToRemove the current SharedRole member to remove.
           */
          function removeMember(uint256 roleId, address memberToRemove) public onlyShared(roleId) onlyRoleManager(roleId) {
              roles[roleId].sharedRoleMembership.removeMember(memberToRemove);
              emit RemovedSharedMember(roleId, memberToRemove, msg.sender);
          }
          /**
           * @notice Removes caller from the role, `roleId`.
           * @dev Reverts if the caller is not a member of the role for `roleId` or if `roleId` is not an
           * initialized, SharedRole.
           * @param roleId the SharedRole membership to modify.
           */
          function renounceMembership(uint256 roleId) public onlyShared(roleId) onlyRoleHolder(roleId) {
              roles[roleId].sharedRoleMembership.removeMember(msg.sender);
              emit RemovedSharedMember(roleId, msg.sender, msg.sender);
          }
          /**
           * @notice Reverts if `roleId` is not initialized.
           */
          modifier onlyValidRole(uint256 roleId) {
              require(roles[roleId].roleType != RoleType.Invalid, "Attempted to use an invalid roleId");
              _;
          }
          /**
           * @notice Reverts if `roleId` is initialized.
           */
          modifier onlyInvalidRole(uint256 roleId) {
              require(roles[roleId].roleType == RoleType.Invalid, "Cannot use a pre-existing role");
              _;
          }
          /**
           * @notice Internal method to initialize a shared role, `roleId`, which will be managed by `managingRoleId`.
           * `initialMembers` will be immediately added to the role.
           * @dev Should be called by derived contracts, usually at construction time. Will revert if the role is already
           * initialized.
           */
          function _createSharedRole(
              uint256 roleId,
              uint256 managingRoleId,
              address[] memory initialMembers
          ) internal onlyInvalidRole(roleId) {
              Role storage role = roles[roleId];
              role.roleType = RoleType.Shared;
              role.managingRole = managingRoleId;
              role.sharedRoleMembership.init(initialMembers);
              require(
                  roles[managingRoleId].roleType != RoleType.Invalid,
                  "Attempted to use an invalid role to manage a shared role"
              );
          }
          /**
           * @notice Internal method to initialize an exclusive role, `roleId`, which will be managed by `managingRoleId`.
           * `initialMember` will be immediately added to the role.
           * @dev Should be called by derived contracts, usually at construction time. Will revert if the role is already
           * initialized.
           */
          function _createExclusiveRole(
              uint256 roleId,
              uint256 managingRoleId,
              address initialMember
          ) internal onlyInvalidRole(roleId) {
              Role storage role = roles[roleId];
              role.roleType = RoleType.Exclusive;
              role.managingRole = managingRoleId;
              role.exclusiveRoleMembership.init(initialMember);
              require(
                  roles[managingRoleId].roleType != RoleType.Invalid,
                  "Attempted to use an invalid role to manage an exclusive role"
              );
          }
      }
      // SPDX-License-Identifier: AGPL-3.0-only
      pragma solidity ^0.8.0;
      import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
      /**
       * @title ERC20 interface that includes burn and mint methods.
       */
      abstract contract ExpandedIERC20 is IERC20 {
          /**
           * @notice Burns a specific amount of the caller's tokens.
           * @dev Only burns the caller's tokens, so it is safe to leave this method permissionless.
           */
          function burn(uint256 value) external virtual;
          /**
           * @dev Burns `value` tokens owned by `recipient`.
           * @param recipient address to burn tokens from.
           * @param value amount of tokens to burn.
           */
          function burnFrom(address recipient, uint256 value) external virtual returns (bool);
          /**
           * @notice Mints tokens and adds them to the balance of the `to` address.
           * @dev This method should be permissioned to only allow designated parties to mint tokens.
           */
          function mint(address to, uint256 value) external virtual returns (bool);
          function addMinter(address account) external virtual;
          function addBurner(address account) external virtual;
          function resetOwner(address account) external virtual;
      }
      // SPDX-License-Identifier: AGPL-3.0-only
      pragma solidity ^0.8.0;
      /**
       * @title Stores common interface names used throughout the DVM by registration in the Finder.
       */
      library OracleInterfaces {
          bytes32 public constant Oracle = "Oracle";
          bytes32 public constant IdentifierWhitelist = "IdentifierWhitelist";
          bytes32 public constant Store = "Store";
          bytes32 public constant FinancialContractsAdmin = "FinancialContractsAdmin";
          bytes32 public constant Registry = "Registry";
          bytes32 public constant CollateralWhitelist = "CollateralWhitelist";
          bytes32 public constant OptimisticOracle = "OptimisticOracle";
          bytes32 public constant OptimisticOracleV2 = "OptimisticOracleV2";
          bytes32 public constant OptimisticOracleV3 = "OptimisticOracleV3";
          bytes32 public constant Bridge = "Bridge";
          bytes32 public constant GenericHandler = "GenericHandler";
          bytes32 public constant SkinnyOptimisticOracle = "SkinnyOptimisticOracle";
          bytes32 public constant ChildMessenger = "ChildMessenger";
          bytes32 public constant OracleHub = "OracleHub";
          bytes32 public constant OracleSpoke = "OracleSpoke";
      }
      /**
       * @title Commonly re-used values for contracts associated with the OptimisticOracle.
       */
      library OptimisticOracleConstraints {
          // Any price request submitted to the OptimisticOracle must contain ancillary data no larger than this value.
          // This value must be <= the Voting contract's `ancillaryBytesLimit` constant value otherwise it is possible
          // that a price can be requested to the OptimisticOracle successfully, but cannot be resolved by the DVM which
          // refuses to accept a price request made with ancillary data length over a certain size.
          uint256 public constant ancillaryBytesLimit = 8192;
      }
      // SPDX-License-Identifier: AGPL-3.0-only
      pragma solidity 0.8.16;
      /**
       * @title Computes vote results.
       * @dev The result is the mode of the added votes. Otherwise, the vote is unresolved.
       */
      library ResultComputationV2 {
          /****************************************
           *   INTERNAL LIBRARY DATA STRUCTURE    *
           ****************************************/
          struct Data {
              mapping(int256 => uint128) voteFrequency; // Maps price to number of tokens that voted for that price.
              uint128 totalVotes; // The total votes that have been added.
              int256 currentMode; // The price that is the current mode, i.e., the price with the highest frequency.
          }
          /****************************************
           *            VOTING FUNCTIONS          *
           ****************************************/
          /**
           * @notice Adds a new vote to be used when computing the result.
           * @param data contains information to which the vote is applied.
           * @param votePrice value specified in the vote for the given `numberTokens`.
           * @param numberTokens number of tokens that voted on the `votePrice`.
           */
          function addVote(
              Data storage data,
              int256 votePrice,
              uint128 numberTokens
          ) internal {
              data.totalVotes += numberTokens;
              data.voteFrequency[votePrice] += numberTokens;
              if (votePrice != data.currentMode && data.voteFrequency[votePrice] > data.voteFrequency[data.currentMode])
                  data.currentMode = votePrice;
          }
          /****************************************
           *        VOTING STATE GETTERS          *
           ****************************************/
          /**
           * @notice Returns whether the result is resolved, and if so, what value it resolved to.
           * @dev `price` should be ignored if `isResolved` is false.
           * @param data contains information against which the `minTotalVotes` and `minModalVotes` thresholds are applied.
           * @param minTotalVotes min (exclusive) number of tokens that must have voted (in any direction) for the result
           * to be valid. Used to enforce a minimum voter participation rate, regardless of how the votes are distributed.
           * @param minModalVotes min (exclusive) number of tokens that must have voted for the modal outcome for it to result
           * in a resolution. This is used to avoid cases where the mode is a very small plurality.
           * @return isResolved indicates if the price has been resolved correctly.
           * @return price the price that the dvm resolved to.
           */
          function getResolvedPrice(
              Data storage data,
              uint128 minTotalVotes,
              uint128 minModalVotes
          ) internal view returns (bool isResolved, int256 price) {
              if (data.totalVotes > minTotalVotes && data.voteFrequency[data.currentMode] > minModalVotes) {
                  isResolved = true; // minTotalVotes and minModalVotes are exceeded, so the resolved price is the mode.
                  price = data.currentMode;
              }
          }
          /**
           * @notice Checks whether a `voteHash` is considered correct.
           * @dev Should only be called after a vote is resolved, i.e., via `getResolvedPrice`.
           * @param data contains information against which the `voteHash` is checked.
           * @param voteHash committed hash submitted by the voter.
           * @return bool true if the vote was correct.
           */
          function wasVoteCorrect(Data storage data, bytes32 voteHash) internal view returns (bool) {
              return voteHash == keccak256(abi.encode(data.currentMode));
          }
          /**
           * @notice Gets the total number of tokens whose votes are considered correct.
           * @dev Should only be called after a vote is resolved, i.e., via `getResolvedPrice`.
           * @param data contains all votes against which the correctly voted tokens are counted.
           * @return uint128 which indicates the frequency of the correctly voted tokens.
           */
          function getTotalCorrectlyVotedTokens(Data storage data) internal view returns (uint128) {
              return data.voteFrequency[data.currentMode];
          }
      }
      // SPDX-License-Identifier: AGPL-3.0-only
      pragma solidity ^0.8.0;
      import "../../common/implementation/Lockable.sol";
      import "../../common/implementation/MultiCaller.sol";
      import "../../common/interfaces/ExpandedIERC20.sol";
      import "../interfaces/StakerInterface.sol";
      import "@openzeppelin/contracts/access/Ownable.sol";
      import "@openzeppelin/contracts/utils/math/SafeCast.sol";
      /**
       * @title Staking contract enabling UMA to be locked up by stakers to earn a pro rata share of a fixed emission rate.
       * @dev Handles the staking, unstaking and reward retrieval logic.
       */
      abstract contract Staker is StakerInterface, Ownable, Lockable, MultiCaller {
          /****************************************
           *             STAKING STATE            *
           ****************************************/
          // Identifies a "stake" for a given voter. Each staker has an instance of this struct.
          struct VoterStake {
              uint128 stake; // UMA staked by the staker.
              uint128 pendingUnstake; // UMA in unstake cooldown period, waiting to be unstaked.
              mapping(uint32 => uint128) pendingStakes; // If a voter stakes during an active reveal, stake is pending.
              uint128 rewardsPaidPerToken; // Internal tracker used in the calculation of pro-rata share of rewards.
              uint128 outstandingRewards; // Accumulated rewards that have not yet been claimed.
              int128 unappliedSlash; // Used to track unapplied slashing in the case of bisected rounds.
              uint64 nextIndexToProcess; // The next request index that a staker is susceptible to be slashed on.
              uint64 unstakeTime; // Time that a staker can unstake. Used to determine if cooldown has passed.
              address delegate; // Address a staker has delegated to. The delegate can commit/reveal/claimRestake rewards.
          }
          mapping(address => VoterStake) public voterStakes; // Each voter is mapped to staker struct for their position.
          mapping(address => address) public delegateToStaker; // Mapping of delegates to their delegators (staker).
          uint128 public emissionRate; // Number of UMA emitted per second to incentivize stakers.
          uint128 public cumulativeStake; // Total number of UMA staked within the system.
          uint128 public rewardPerTokenStored; // Tracker used to allocate pro-rata share of rewards to stakers.
          uint64 public unstakeCoolDown; // Delay, in seconds, a staker must wait when trying to unstake their UMA.
          uint64 public lastUpdateTime; // Tracks the last time the reward rate was updated, used in reward allocation.
          ExpandedIERC20 public immutable votingToken; // An instance of the UMA voting token to mint rewards for stakers
          /****************************************
           *                EVENTS                *
           ****************************************/
          event Staked(
              address indexed voter,
              address indexed from,
              uint128 amount,
              uint128 voterStake,
              uint128 voterPendingUnstake,
              uint128 cumulativeStake
          );
          event RequestedUnstake(address indexed voter, uint128 amount, uint64 unstakeTime, uint128 voterStake);
          event ExecutedUnstake(address indexed voter, uint128 tokensSent, uint128 voterStake);
          event WithdrawnRewards(address indexed voter, address indexed delegate, uint128 tokensWithdrawn);
          event UpdatedReward(address indexed voter, uint128 newReward, uint64 lastUpdateTime);
          event SetNewEmissionRate(uint128 newEmissionRate);
          event SetNewUnstakeCoolDown(uint64 newUnstakeCoolDown);
          event DelegateSet(address indexed delegator, address indexed delegate);
          event DelegatorSet(address indexed delegate, address indexed delegator);
          /**
           * @notice Construct the Staker contract
           * @param _emissionRate amount of voting tokens that are emitted per second, split pro rata to stakers.
           * @param _unstakeCoolDown time that a voter must wait to unstake after requesting to unstake.
           * @param _votingToken address of the UMA token contract used to commit votes.
           */
          constructor(
              uint128 _emissionRate,
              uint64 _unstakeCoolDown,
              address _votingToken
          ) {
              setEmissionRate(_emissionRate);
              setUnstakeCoolDown(_unstakeCoolDown);
              votingToken = ExpandedIERC20(_votingToken);
          }
          /****************************************
           *           STAKER FUNCTIONS           *
           ****************************************/
          /**
           * @notice Pulls tokens from the sender's wallet and stakes them on his behalf.
           * @param amount the amount of tokens to stake.
           */
          function stake(uint128 amount) external {
              _stakeTo(msg.sender, msg.sender, amount);
          }
          /**
           * @notice Pulls tokens from the sender's wallet and stakes them for the recipient.
           * @param recipient the recipient address.
           * @param amount the amount of tokens to stake.
           */
          function stakeTo(address recipient, uint128 amount) external {
              _stakeTo(msg.sender, recipient, amount);
          }
          // Pull an amount of votingToken from the from address and stakes them for the recipient address.
          // If we are in an active reveal phase the stake amount will be added to the pending stake.
          // If not, the stake amount will be added to the stake.
          function _stakeTo(
              address from,
              address recipient,
              uint128 amount
          ) internal {
              require(amount > 0, "Cannot stake 0");
              VoterStake storage voterStake = voterStakes[recipient];
              // If the staker has a cumulative staked balance of 0 then we can shortcut their nextIndexToProcess to
              // the most recent index. This means we don't need to traverse requests where the staker was not staked.
              // _getStartingIndexForStaker returns the appropriate index to start at.
              if (voterStake.stake == 0) voterStake.nextIndexToProcess = _getStartingIndexForStaker();
              _updateTrackers(recipient);
              // Compute pending stakes when needed.
              _computePendingStakes(recipient, amount);
              voterStake.stake += amount;
              cumulativeStake += amount;
              // Tokens are pulled from the from address and sent to this contract.
              // During withdrawAndRestake, from is the same as the address of this contract, so there is no need to transfer.
              if (from != address(this)) votingToken.transferFrom(from, address(this), amount);
              emit Staked(recipient, from, amount, voterStake.stake, voterStake.pendingUnstake, cumulativeStake);
          }
          /**
           * @notice Request a certain number of tokens to be unstaked. After the unstake time expires, the user may execute
           * the unstake. Tokens requested to unstake are not slashable nor subject to earning rewards.
           * This function cannot be called during an active reveal phase.
           * Note there is no way to cancel an unstake request, you must wait until after unstakeTime and re-stake.
           * @param amount the amount of tokens to request to be unstaked.
           */
          function requestUnstake(uint128 amount) external nonReentrant() {
              require(!_inActiveReveal(), "In an active reveal phase");
              require(amount > 0, "Cannot unstake 0");
              _updateTrackers(msg.sender);
              VoterStake storage voterStake = voterStakes[msg.sender];
              require(voterStake.stake >= amount && voterStake.pendingUnstake == 0, "Bad amount or pending unstake");
              cumulativeStake -= amount;
              voterStake.pendingUnstake = amount;
              voterStake.stake -= amount;
              voterStake.unstakeTime = uint64(getCurrentTime()) + unstakeCoolDown;
              emit RequestedUnstake(msg.sender, amount, voterStake.unstakeTime, voterStake.stake);
          }
          /**
           * @notice  Execute a previously requested unstake. Requires the unstake time to have passed.
           * @dev If a staker requested an unstake and time > unstakeTime then send funds to staker. If unstakeCoolDown is
           * set to 0 then the unstake can be executed immediately.
           */
          function executeUnstake() external nonReentrant() {
              VoterStake storage voterStake = voterStakes[msg.sender];
              require(
                  voterStake.unstakeTime != 0 && (getCurrentTime() >= voterStake.unstakeTime || unstakeCoolDown == 0),
                  "Unstake time not passed"
              );
              uint128 tokensToSend = voterStake.pendingUnstake;
              if (tokensToSend > 0) {
                  voterStake.pendingUnstake = 0;
                  voterStake.unstakeTime = 0;
                  votingToken.transfer(msg.sender, tokensToSend);
              }
              emit ExecutedUnstake(msg.sender, tokensToSend, voterStake.stake);
          }
          /**
           * @notice Send accumulated rewards to the voter. Note that these rewards do not include slashing balance changes.
           * @return uint128 the amount of tokens sent to the voter.
           */
          function withdrawRewards() external returns (uint128) {
              return _withdrawRewards(msg.sender, msg.sender);
          }
          // Withdraws rewards for a given voter and sends them to the recipient.
          function _withdrawRewards(address voter, address recipient) internal returns (uint128) {
              _updateTrackers(voter);
              VoterStake storage voterStake = voterStakes[voter];
              uint128 tokensToMint = voterStake.outstandingRewards;
              if (tokensToMint > 0) {
                  voterStake.outstandingRewards = 0;
                  require(votingToken.mint(recipient, tokensToMint), "Voting token issuance failed");
                  emit WithdrawnRewards(voter, msg.sender, tokensToMint);
              }
              return tokensToMint;
          }
          /**
           * @notice Stake accumulated rewards. This is merely a convenience mechanism that combines the voter's withdrawal
           * and stake in the same transaction if requested by a delegate or the voter.
           * @dev The rewarded tokens simply pass through this contract before being staked on the voter's behalf.
           *  The balance of the delegate remains unchanged.
           * @return uint128 the amount of tokens that the voter is staking.
           */
          function withdrawAndRestake() external returns (uint128) {
              address voter = getVoterFromDelegate(msg.sender);
              uint128 rewards = _withdrawRewards(voter, address(this));
              _stakeTo(address(this), voter, rewards);
              return rewards;
          }
          /**
           * @notice Sets the delegate of a voter. This delegate can vote on behalf of the staker. The staker will still own
           * all staked balances, receive rewards and be slashed based on the actions of the delegate. Intended use is using a
           * low-security available wallet for voting while keeping access to staked amounts secure by a more secure wallet.
           * @param delegate the address of the delegate.
           */
          function setDelegate(address delegate) external {
              voterStakes[msg.sender].delegate = delegate;
              emit DelegateSet(msg.sender, delegate);
          }
          /**
           * @notice Sets the delegator of a voter. Acts to accept a delegation. The delegate can only vote for the delegator
           * if the delegator also selected the delegate to do so (two-way relationship needed).
           * @param delegator the address of the delegator.
           */
          function setDelegator(address delegator) external {
              delegateToStaker[msg.sender] = delegator;
              emit DelegatorSet(msg.sender, delegator);
          }
          /****************************************
           *        OWNER ADMIN FUNCTIONS         *
           ****************************************/
          /**
           * @notice  Set the token's emission rate, the number of voting tokens that are emitted per second.
           * @param newEmissionRate the new amount of voting tokens that are emitted per second, split pro rata to stakers.
           */
          function setEmissionRate(uint128 newEmissionRate) public onlyOwner {
              _updateReward(address(0));
              emissionRate = newEmissionRate;
              emit SetNewEmissionRate(newEmissionRate);
          }
          /**
           * @notice  Set the amount of time a voter must wait to unstake after submitting a request to do so.
           * @param newUnstakeCoolDown the new duration of the cool down period in seconds.
           */
          function setUnstakeCoolDown(uint64 newUnstakeCoolDown) public onlyOwner {
              unstakeCoolDown = newUnstakeCoolDown;
              emit SetNewUnstakeCoolDown(newUnstakeCoolDown);
          }
          // Updates an account internal trackers.
          function _updateTrackers(address voter) internal virtual {
              _updateReward(voter);
          }
          /****************************************
           *            VIEW FUNCTIONS            *
           ****************************************/
          /**
           * @notice Gets the pending stake for a voter for a given round.
           * @param voter the voter address.
           * @param roundId round id.
           * @return uint128 amount of the pending stake.
           */
          function getVoterPendingStake(address voter, uint32 roundId) external view returns (uint128) {
              return voterStakes[voter].pendingStakes[roundId];
          }
          /**
           * @notice Gets the voter from the delegate.
           * @param caller caller of the function or the address to check in the mapping between a voter and their delegate.
           * @return address voter that corresponds to the delegate.
           */
          function getVoterFromDelegate(address caller) public view returns (address) {
              address delegator = delegateToStaker[caller];
              // The delegate chose to be a delegate for the staker.
              if (delegator != address(0) && voterStakes[delegator].delegate == caller) return delegator;
              else return caller; // The staker chose the delegate.
          }
          /**
           * @notice  Determine the number of outstanding token rewards that can be withdrawn by a voter.
           * @param voter the address of the voter.
           * @return uint256 the outstanding rewards.
           */
          function outstandingRewards(address voter) public view returns (uint256) {
              VoterStake storage voterStake = voterStakes[voter];
              return
                  ((voterStake.stake * (rewardPerToken() - voterStake.rewardsPaidPerToken)) / 1e18) +
                  voterStake.outstandingRewards;
          }
          /**
           * @notice  Calculate the reward per token based on the last time the reward was updated.
           * @return uint256 the reward per token.
           */
          function rewardPerToken() public view returns (uint256) {
              if (cumulativeStake == 0) return rewardPerTokenStored;
              return rewardPerTokenStored + ((getCurrentTime() - lastUpdateTime) * emissionRate * 1e18) / cumulativeStake;
          }
          /**
           * @notice Returns the total amount of tokens staked by the voter, after applying updateTrackers. Specifically used
           * by offchain apps to simulate the cumulative stake + unapplied slashing updates without sending a transaction.
           * @param voter the address of the voter.
           * @return uint128 the total stake.
           */
          function getVoterStakePostUpdate(address voter) external returns (uint128) {
              _updateTrackers(voter);
              return voterStakes[voter].stake;
          }
          /**
           * @notice Returns the current block timestamp.
           * @dev Can be overridden to control contract time.
           * @return the current block timestamp.
           */
          function getCurrentTime() public view virtual returns (uint256) {
              return block.timestamp;
          }
          /****************************************
           *          INTERNAL FUNCTIONS          *
           ****************************************/
          // This function must be called before any tokens are staked. Update the voter's pending stakes when necessary.
          // The contract that inherits from Staker (e.g. VotingV2) must implement this logic by overriding this function.
          function _computePendingStakes(address voter, uint128 amount) internal virtual;
          // Add a new stake amount to the voter's pending stake for a specific round id.
          function _incrementPendingStake(
              address voter,
              uint32 roundId,
              uint128 amount
          ) internal {
              voterStakes[voter].pendingStakes[roundId] += amount;
          }
          // Determine if we are in an active reveal phase. This function should be overridden by the child contract.
          function _inActiveReveal() internal view virtual returns (bool) {
              return false;
          }
          // Returns the starting index for a staker. This function should be overridden by the implementing contract.
          function _getStartingIndexForStaker() internal virtual returns (uint64) {
              return 0;
          }
          // Calculate the reward per token based on last time the reward was updated.
          function _updateReward(address voter) internal {
              uint128 newRewardPerToken = uint128(rewardPerToken());
              rewardPerTokenStored = newRewardPerToken;
              lastUpdateTime = uint64(getCurrentTime());
              if (voter != address(0)) {
                  VoterStake storage voterStake = voterStakes[voter];
                  voterStake.outstandingRewards = uint128(outstandingRewards(voter));
                  voterStake.rewardsPaidPerToken = newRewardPerToken;
              }
              emit UpdatedReward(voter, newRewardPerToken, lastUpdateTime);
          }
      }
      // SPDX-License-Identifier: AGPL-3.0-only
      pragma solidity ^0.8.0;
      import "../interfaces/VotingInterface.sol";
      /**
       * @title Library to compute rounds and phases for an equal length commit-reveal voting cycle.
       */
      library VoteTiming {
          struct Data {
              uint256 phaseLength;
          }
          /**
           * @notice Initializes the data object. Sets the phase length based on the input.
           * @param data reference to the this library's data object.
           * @param phaseLength length of voting phase in seconds.
           */
          function init(Data storage data, uint256 phaseLength) internal {
              // This should have a require message but this results in an internal Solidity error.
              require(phaseLength > 0);
              data.phaseLength = phaseLength;
          }
          /**
           * @notice Computes the roundID based off the current time as floor(timestamp/roundLength).
           * @dev The round ID depends on the global timestamp but not on the lifetime of the system.
           * The consequence is that the initial round ID starts at an arbitrary number (that increments, as expected, for subsequent rounds) instead of zero or one.
           * @param data input data object.
           * @param currentTime input unix timestamp used to compute the current roundId.
           * @return roundId defined as a function of the currentTime and `phaseLength` from `data`.
           */
          function computeCurrentRoundId(Data storage data, uint256 currentTime) internal view returns (uint256) {
              uint256 roundLength = data.phaseLength * uint256(VotingAncillaryInterface.Phase.NUM_PHASES);
              return currentTime / roundLength;
          }
          /**
           * @notice compute the round end time as a function of the round Id.
           * @param data input data object.
           * @param roundId uniquely identifies the current round.
           * @return timestamp unix time of when the current round will end.
           */
          function computeRoundEndTime(Data storage data, uint256 roundId) internal view returns (uint256) {
              uint256 roundLength = data.phaseLength * uint256(VotingAncillaryInterface.Phase.NUM_PHASES);
              return roundLength * (roundId + 1);
          }
          /**
           * @notice Computes the current phase based only on the current time.
           * @param data input data object.
           * @param currentTime input unix timestamp used to compute the current roundId.
           * @return current voting phase based on current time and vote phases configuration.
           */
          function computeCurrentPhase(Data storage data, uint256 currentTime)
              internal
              view
              returns (VotingAncillaryInterface.Phase)
          {
              // This employs some hacky casting. We could make this an if-statement if we're worried about type safety.
              return
                  VotingAncillaryInterface.Phase(
                      (currentTime / data.phaseLength) % uint256(VotingAncillaryInterface.Phase.NUM_PHASES)
                  );
          }
      }
      // SPDX-License-Identifier: AGPL-3.0-only
      pragma solidity ^0.8.0;
      import "../../common/implementation/ExpandedERC20.sol";
      import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Snapshot.sol";
      /**
       * @title Ownership of this token allows a voter to respond to price requests.
       * @dev Supports snapshotting and allows the Oracle to mint new tokens as rewards.
       */
      contract VotingToken is ExpandedERC20, ERC20Snapshot {
          /**
           * @notice Constructs the VotingToken.
           */
          constructor() ExpandedERC20("UMA Voting Token v1", "UMA", 18) ERC20Snapshot() {}
          function decimals() public view virtual override(ERC20, ExpandedERC20) returns (uint8) {
              return super.decimals();
          }
          /**
           * @notice Creates a new snapshot ID.
           * @return uint256 Thew new snapshot ID.
           */
          function snapshot() external returns (uint256) {
              return _snapshot();
          }
          // _transfer, _mint and _burn are ERC20 internal methods that are overridden by ERC20Snapshot,
          // therefore the compiler will complain that VotingToken must override these methods
          // because the two base classes (ERC20 and ERC20Snapshot) both define the same functions
          function _transfer(
              address from,
              address to,
              uint256 value
          ) internal override(ERC20) {
              super._transfer(from, to, value);
          }
          function _mint(address account, uint256 value) internal virtual override(ERC20) {
              super._mint(account, value);
          }
          function _burn(address account, uint256 value) internal virtual override(ERC20) {
              super._burn(account, value);
          }
          function _beforeTokenTransfer(
              address from,
              address to,
              uint256 amount
          ) internal virtual override(ERC20, ERC20Snapshot) {
              super._beforeTokenTransfer(from, to, amount);
          }
      }
      // SPDX-License-Identifier: AGPL-3.0-only
      pragma solidity 0.8.16;
      import "@openzeppelin/contracts/utils/math/Math.sol";
      import "./ResultComputationV2.sol";
      import "./Staker.sol";
      import "./VoteTiming.sol";
      import "./Constants.sol";
      import "../interfaces/MinimumVotingAncillaryInterface.sol";
      import "../interfaces/FinderInterface.sol";
      import "../interfaces/IdentifierWhitelistInterface.sol";
      import "../interfaces/OracleAncillaryInterface.sol";
      import "../interfaces/OracleGovernanceInterface.sol";
      import "../interfaces/OracleInterface.sol";
      import "../interfaces/VotingV2Interface.sol";
      import "../interfaces/RegistryInterface.sol";
      import "../interfaces/SlashingLibraryInterface.sol";
      /**
       * @title VotingV2 contract for the UMA DVM.
       * @dev Handles receiving and resolving price requests via a commit-reveal voting schelling scheme.
       */
      contract VotingV2 is Staker, OracleInterface, OracleAncillaryInterface, OracleGovernanceInterface, VotingV2Interface {
          using VoteTiming for VoteTiming.Data;
          using ResultComputationV2 for ResultComputationV2.Data;
          /****************************************
           *        VOTING DATA STRUCTURES        *
           ****************************************/
          // Identifies a unique price request. Tracks ongoing votes as well as the result of the vote.
          struct PriceRequest {
              uint32 lastVotingRound; // Last round that this price request was voted on. Updated when a request is rolled.
              bool isGovernance; // Denotes whether this is a governance request or not.
              uint64 time; // Timestamp used when evaluating the request.
              uint32 rollCount; // The number of rounds that a price request has rolled. Informs if a request can be deleted.
              bytes32 identifier; // Identifier that defines how the voters should resolve the request.
              mapping(uint32 => VoteInstance) voteInstances; // A map containing all votes for this price in various rounds.
              bytes ancillaryData; // Additional data used to resolve the request.
          }
          struct VoteInstance {
              mapping(address => VoteSubmission) voteSubmissions; // Maps (voter) to their submission.
              ResultComputationV2.Data results; // The data structure containing the computed voting results.
          }
          struct VoteSubmission {
              bytes32 commit; // A bytes32 of 0 indicates no commit or a commit that was already revealed.
              bytes32 revealHash; // The hash of the value that was revealed. This is only used for computation of rewards.
          }
          struct Round {
              SlashingLibraryInterface slashingLibrary; // Slashing library used to compute voter participation slash at this round.
              uint128 minParticipationRequirement; // Minimum staked tokens that must vote to resolve a request.
              uint128 minAgreementRequirement; // Minimum staked tokens that must agree on an outcome to resolve a request.
              uint128 cumulativeStakeAtRound; // Total staked tokens at the start of the round.
              uint32 numberOfRequestsToVote; // The number of requests to vote in this round.
          }
          struct SlashingTracker {
              uint256 wrongVoteSlashPerToken; // The amount of tokens slashed per token staked for a wrong vote.
              uint256 noVoteSlashPerToken; // The amount of tokens slashed per token staked for a no vote.
              uint256 totalSlashed; // The total amount of tokens slashed for a given request.
              uint256 totalCorrectVotes; // The total number of correct votes for a given request.
              uint32 lastVotingRound; // The last round that this request was voted on (when it resolved).
          }
          enum VoteParticipation {
              DidNotVote, // Voter did not vote.
              WrongVote, // Voter voted against the resolved price.
              CorrectVote // Voter voted with the resolved price.
          }
          // Represents the status a price request has.
          enum RequestStatus {
              NotRequested, // Was never requested.
              Active, // Is being voted on in the current round.
              Resolved, // Was resolved in a previous round.
              Future, // Is scheduled to be voted on in a future round.
              ToDelete // Is scheduled to be deleted.
          }
          // Only used as a return value in view methods -- never stored in the contract.
          struct RequestState {
              RequestStatus status;
              uint32 lastVotingRound;
          }
          /****************************************
           *            VOTING STATE              *
           ****************************************/
          uint32 public lastRoundIdProcessed; // The last round pendingPriceRequestsIds were traversed in.
          uint64 public nextPendingIndexToProcess; // Next pendingPriceRequestsIds index to process in lastRoundIdProcessed.
          FinderInterface public immutable finder; // Reference to the UMA Finder contract, used to find other UMA contracts.
          SlashingLibraryInterface public slashingLibrary; // Reference to Slashing Library, used to compute slashing amounts.
          VoteTiming.Data public voteTiming; // Vote timing library used to compute round timing related logic.
          OracleAncillaryInterface public immutable previousVotingContract; // Previous voting contract, if migrated.
          mapping(uint256 => Round) public rounds; // Maps round numbers to the rounds.
          mapping(bytes32 => PriceRequest) public priceRequests; // Maps price request IDs to the PriceRequest struct.
          bytes32[] public resolvedPriceRequestIds; // Array of resolved price requestIds. Used to track resolved requests.
          bytes32[] public pendingPriceRequestsIds; // Array of pending price requestIds. Can be resolved in the future.
          uint32 public maxRolls; // The maximum number of times a request can roll before it is deleted automatically.
          uint32 public maxRequestsPerRound; // The maximum number of requests that can be enqueued in a single round.
          address public migratedAddress; // If non-zero, this contract has been migrated to this address.
          uint128 public gat; // GAT: A minimum number of tokens that must participate to resolve a vote.
          uint64 public spat; // SPAT: Minimum percentage of staked tokens that must agree on the answer to resolve a vote.
          uint64 public constant UINT64_MAX = type(uint64).max; // Max value of an unsigned integer.
          uint256 public constant ANCILLARY_BYTES_LIMIT = 8192; // Max length in bytes of ancillary data.
          /****************************************
           *                EVENTS                *
           ****************************************/
          event VoteCommitted(
              address indexed voter,
              address indexed caller,
              uint32 roundId,
              bytes32 indexed identifier,
              uint256 time,
              bytes ancillaryData
          );
          event EncryptedVote(
              address indexed caller,
              uint32 indexed roundId,
              bytes32 indexed identifier,
              uint256 time,
              bytes ancillaryData,
              bytes encryptedVote
          );
          event VoteRevealed(
              address indexed voter,
              address indexed caller,
              uint32 roundId,
              bytes32 indexed identifier,
              uint256 time,
              bytes ancillaryData,
              int256 price,
              uint128 numTokens
          );
          event RequestAdded(
              address indexed requester,
              uint32 indexed roundId,
              bytes32 indexed identifier,
              uint256 time,
              bytes ancillaryData,
              bool isGovernance
          );
          event RequestResolved(
              uint32 indexed roundId,
              uint256 indexed resolvedPriceRequestIndex,
              bytes32 indexed identifier,
              uint256 time,
              bytes ancillaryData,
              int256 price
          );
          event VotingContractMigrated(address newAddress);
          event RequestDeleted(bytes32 indexed identifier, uint256 indexed time, bytes ancillaryData, uint32 rollCount);
          event RequestRolled(bytes32 indexed identifier, uint256 indexed time, bytes ancillaryData, uint32 rollCount);
          event GatAndSpatChanged(uint128 newGat, uint64 newSpat);
          event SlashingLibraryChanged(address newAddress);
          event MaxRollsChanged(uint32 newMaxRolls);
          event MaxRequestsPerRoundChanged(uint32 newMaxRequestsPerRound);
          event VoterSlashApplied(address indexed voter, int128 slashedTokens, uint128 postStake);
          event VoterSlashed(address indexed voter, uint256 indexed requestIndex, int128 slashedTokens);
          /**
           * @notice Construct the VotingV2 contract.
           * @param _emissionRate amount of voting tokens that are emitted per second, split prorate between stakers.
           * @param _unstakeCoolDown time that a voter must wait to unstake after requesting to unstake.
           * @param _phaseLength length of the voting phases in seconds.
           * @param _maxRolls number of times a vote must roll to be auto deleted by the DVM.
           * @param _maxRequestsPerRound maximum number of requests that can be enqueued in a single round.
           * @param _gat number of tokens that must participate to resolve a vote.
           * @param _spat percentage of staked tokens that must agree on the result to resolve a vote.
           * @param _votingToken address of the UMA token contract used to commit votes.
           * @param _finder keeps track of all contracts within the system based on their interfaceName.
           * @param _slashingLibrary contract used to calculate voting slashing penalties based on voter participation.
           * @param _previousVotingContract previous voting contract address.
           */
          constructor(
              uint128 _emissionRate,
              uint64 _unstakeCoolDown,
              uint64 _phaseLength,
              uint32 _maxRolls,
              uint32 _maxRequestsPerRound,
              uint128 _gat,
              uint64 _spat,
              address _votingToken,
              address _finder,
              address _slashingLibrary,
              address _previousVotingContract
          ) Staker(_emissionRate, _unstakeCoolDown, _votingToken) {
              voteTiming.init(_phaseLength);
              finder = FinderInterface(_finder);
              previousVotingContract = OracleAncillaryInterface(_previousVotingContract);
              setGatAndSpat(_gat, _spat);
              setSlashingLibrary(_slashingLibrary);
              setMaxRequestPerRound(_maxRequestsPerRound);
              setMaxRolls(_maxRolls);
          }
          /***************************************
                          MODIFIERS
          ****************************************/
          modifier onlyRegisteredContract() {
              _requireRegisteredContract();
              _;
          }
          modifier onlyIfNotMigrated() {
              _requireNotMigrated();
              _;
          }
          /****************************************
           *  PRICE REQUEST AND ACCESS FUNCTIONS  *
           ****************************************/
          /**
           * @notice Enqueues a request (if a request isn't already present) for the identifier, time and ancillary data.
           * @dev Time must be in the past and the identifier must be supported. The length of the ancillary data is limited.
           * @param identifier uniquely identifies the price requested. E.g. BTC/USD (encoded as bytes32) could be requested.
           * @param time unix timestamp for the price request.
           * @param ancillaryData arbitrary data appended to a price request to give the voters more info from the caller.
           */
          function requestPrice(
              bytes32 identifier,
              uint256 time,
              bytes memory ancillaryData
          ) public override nonReentrant onlyIfNotMigrated onlyRegisteredContract {
              _requestPrice(identifier, time, ancillaryData, false);
          }
          /**
           * @notice Enqueues a governance action request (if not already present) for identifier, time and ancillary data.
           * @dev Only the owner of the Voting contract can call this. In normal operation this is the Governor contract.
           * @param identifier uniquely identifies the price requested. E.g. Admin 0 (encoded as bytes32) could be requested.
           * @param time unix timestamp for the price request.
           * @param ancillaryData arbitrary data appended to a price request to give the voters more info from the caller.
           */
          function requestGovernanceAction(
              bytes32 identifier,
              uint256 time,
              bytes memory ancillaryData
          ) external override onlyOwner onlyIfNotMigrated {
              _requestPrice(identifier, time, ancillaryData, true);
          }
          /**
           * @notice Enqueues a request (if a request isn't already present) for the identifier, time pair.
           * @dev Overloaded method to enable short term backwards compatibility when ancillary data is not included.
           * @param identifier uniquely identifies the price requested. E.g. BTC/USD (encoded as bytes32) could be requested.
           * @param time unix timestamp for the price request.
           */
          function requestPrice(bytes32 identifier, uint256 time) external override {
              requestPrice(identifier, time, "");
          }
          // Enqueues a request (if a request isn't already present) for the given identifier, time and ancillary data.
          function _requestPrice(
              bytes32 identifier,
              uint256 time,
              bytes memory ancillaryData,
              bool isGovernance
          ) internal {
              require(time <= getCurrentTime(), "Can only request in past");
              require(isGovernance || _getIdentifierWhitelist().isIdentifierSupported(identifier), "Unsupported identifier");
              require(ancillaryData.length <= ANCILLARY_BYTES_LIMIT, "Invalid ancillary data");
              bytes32 priceRequestId = _encodePriceRequest(identifier, time, ancillaryData);
              PriceRequest storage priceRequest = priceRequests[priceRequestId];
              // Price has never been requested.
              uint32 currentRoundId = getCurrentRoundId();
              if (_getRequestStatus(priceRequest, currentRoundId) == RequestStatus.NotRequested) {
                  uint32 roundIdToVoteOn = getRoundIdToVoteOnRequest(currentRoundId + 1);
                  ++rounds[roundIdToVoteOn].numberOfRequestsToVote;
                  priceRequest.identifier = identifier;
                  priceRequest.time = uint64(time);
                  priceRequest.ancillaryData = ancillaryData;
                  priceRequest.lastVotingRound = roundIdToVoteOn;
                  if (isGovernance) priceRequest.isGovernance = isGovernance;
                  pendingPriceRequestsIds.push(priceRequestId);
                  emit RequestAdded(msg.sender, roundIdToVoteOn, identifier, time, ancillaryData, isGovernance);
              }
          }
          /**
           * @notice Gets the round ID that a request should be voted on.
           * @param targetRoundId round ID to start searching for a round to vote on.
           * @return uint32 round ID that a request should be voted on.
           */
          function getRoundIdToVoteOnRequest(uint32 targetRoundId) public view returns (uint32) {
              while (rounds[targetRoundId].numberOfRequestsToVote >= maxRequestsPerRound) ++targetRoundId;
              return targetRoundId;
          }
          /**
           * @notice Returns whether the price for identifier, time and ancillary data is available.
           * @param identifier uniquely identifies the price requested. E.g. BTC/USD (encoded as bytes32) could be requested.
           * @param time unix timestamp of the price request.
           * @param ancillaryData arbitrary data appended to a price request to give the voters more info from the caller.
           * @return bool if the DVM has resolved to a price for the given identifier, timestamp and ancillary data.
           */
          function hasPrice(
              bytes32 identifier,
              uint256 time,
              bytes memory ancillaryData
          ) public view override onlyRegisteredContract returns (bool) {
              (bool _hasPrice, , ) = _getPriceOrError(identifier, time, ancillaryData);
              return _hasPrice;
          }
          /**
           * @notice Whether the price for identifier and time is available.
           * @dev Overloaded method to enable short term backwards compatibility when ancillary data is not included.
           * @param identifier uniquely identifies the price requested. E.g. BTC/USD (encoded as bytes32) could be requested.
           * @param time unix timestamp of the price request.
           * @return bool if the DVM has resolved to a price for the given identifier and timestamp.
           */
          function hasPrice(bytes32 identifier, uint256 time) external view override returns (bool) {
              return hasPrice(identifier, time, "");
          }
          /**
           * @notice Gets the price for identifier, time and ancillary data if it has already been requested and resolved.
           * @dev If the price is not available, the method reverts.
           * @param identifier uniquely identifies the price requested. E.g. BTC/USD (encoded as bytes32) could be requested.
           * @param time unix timestamp of the price request.
           * @param ancillaryData arbitrary data appended to a price request to give the voters more info from the caller.
           * @return int256 representing the resolved price for the given identifier, timestamp and ancillary data.
           */
          function getPrice(
              bytes32 identifier,
              uint256 time,
              bytes memory ancillaryData
          ) public view override onlyRegisteredContract returns (int256) {
              (bool _hasPrice, int256 price, string memory message) = _getPriceOrError(identifier, time, ancillaryData);
              // If the price wasn't available, revert with the provided message.
              require(_hasPrice, message);
              return price;
          }
          /**
           * @notice Gets the price for identifier and time if it has already been requested and resolved.
           * @dev Overloaded method to enable short term backwards compatibility when ancillary data is not included.
           * @dev If the price is not available, the method reverts.
           * @param identifier uniquely identifies the price requested. E.g. BTC/USD (encoded as bytes32) could be requested.
           * @param time unix timestamp of the price request.
           * @return int256 representing the resolved price for the given identifier and timestamp.
           */
          function getPrice(bytes32 identifier, uint256 time) external view override returns (int256) {
              return getPrice(identifier, time, "");
          }
          /**
           * @notice Gets the status of a list of price requests, identified by their identifier, time and ancillary data.
           * @dev If the status for a particular request is NotRequested, the lastVotingRound will always be 0.
           * @param requests array of pending requests which includes identifier, timestamp & ancillary data for the requests.
           * @return requestStates a list, in the same order as the input list, giving the status of the specified requests.
           */
          function getPriceRequestStatuses(PendingRequestAncillary[] memory requests)
              public
              view
              returns (RequestState[] memory)
          {
              RequestState[] memory requestStates = new RequestState[](requests.length);
              uint32 currentRoundId = getCurrentRoundId();
              for (uint256 i = 0; i < requests.length; i = unsafe_inc(i)) {
                  PriceRequest storage priceRequest =
                      _getPriceRequest(requests[i].identifier, requests[i].time, requests[i].ancillaryData);
                  RequestStatus status = _getRequestStatus(priceRequest, currentRoundId);
                  // If it's an active request, its true lastVotingRound is the current one, even if it hasn't been updated.
                  if (status == RequestStatus.Active) requestStates[i].lastVotingRound = currentRoundId;
                  else requestStates[i].lastVotingRound = priceRequest.lastVotingRound;
                  requestStates[i].status = status;
              }
              return requestStates;
          }
          /****************************************
           *          VOTING FUNCTIONS            *
           ****************************************/
          /**
           * @notice Commit a vote for a price request for identifier at time.
           * @dev identifier, time must correspond to a price request that's currently in the commit phase.
           * Commits can be changed.
           * @dev Since transaction data is public, the salt will be revealed with the vote. While this is the system’s
           * expected behavior, voters should never reuse salts. If someone else is able to guess the voted price and knows
           * that a salt will be reused, then they can determine the vote pre-reveal.
           * @param identifier uniquely identifies the committed vote. E.g. BTC/USD price pair.
           * @param time unix timestamp of the price being voted on.
           * @param ancillaryData arbitrary data appended to a price request to give the voters more info from the caller.
           * @param hash keccak256 hash of the price, salt, voter address, time, ancillaryData, current roundId, identifier.
           */
          function commitVote(
              bytes32 identifier,
              uint256 time,
              bytes memory ancillaryData,
              bytes32 hash
          ) public override nonReentrant {
              uint32 currentRoundId = getCurrentRoundId();
              address voter = getVoterFromDelegate(msg.sender);
              _updateTrackers(voter);
              require(hash != bytes32(0), "Invalid commit hash");
              require(getVotePhase() == Phase.Commit, "Cannot commit in reveal phase");
              PriceRequest storage priceRequest = _getPriceRequest(identifier, time, ancillaryData);
              require(_getRequestStatus(priceRequest, currentRoundId) == RequestStatus.Active, "Request must be active");
              priceRequest.voteInstances[currentRoundId].voteSubmissions[voter].commit = hash;
              emit VoteCommitted(voter, msg.sender, currentRoundId, identifier, time, ancillaryData);
          }
          /**
           * @notice Reveal a previously committed vote for identifier at time.
           * @dev The revealed price, salt, voter address, time, ancillaryData, current roundId, identifier must hash to the
           * latest hash that commitVote() was called with. Only the committer can reveal their vote.
           * @param identifier voted on in the commit phase. E.g. BTC/USD price pair.
           * @param time specifies the unix timestamp of the price being voted on.
           * @param price voted on during the commit phase.
           * @param ancillaryData arbitrary data appended to a price request to give the voters more info from the caller.
           * @param salt value used to hide the commitment price during the commit phase.
           */
          function revealVote(
              bytes32 identifier,
              uint256 time,
              int256 price,
              bytes memory ancillaryData,
              int256 salt
          ) public override nonReentrant {
              uint32 currentRoundId = getCurrentRoundId();
              _freezeRoundVariables(currentRoundId);
              VoteInstance storage voteInstance =
                  _getPriceRequest(identifier, time, ancillaryData).voteInstances[currentRoundId];
              address voter = getVoterFromDelegate(msg.sender);
              VoteSubmission storage voteSubmission = voteInstance.voteSubmissions[voter];
              require(getVotePhase() == Phase.Reveal, "Reveal phase has not started yet"); // Can only reveal in reveal phase.
              // Zero hashes are blocked in commit; they indicate a different error: voter did not commit or already revealed.
              require(voteSubmission.commit != bytes32(0), "Invalid hash reveal");
              // Check that the hash that was committed matches to the one that was revealed. Note that if the voter had
              // then they must reveal with the same account they had committed with.
              require(
                  keccak256(abi.encodePacked(price, salt, voter, time, ancillaryData, uint256(currentRoundId), identifier)) ==
                      voteSubmission.commit,
                  "Revealed data != commit hash"
              );
              delete voteSubmission.commit; // Small gas refund for clearing up storage.
              voteSubmission.revealHash = keccak256(abi.encode(price)); // Set the voter's submission.
              // Calculate the voters effective stake for this round as the difference between their stake and pending stake.
              // This allows for the voter to have staked during this reveal phase and not consider their pending stake.
              uint128 effectiveStake = voterStakes[voter].stake - voterStakes[voter].pendingStakes[currentRoundId];
              voteInstance.results.addVote(price, effectiveStake); // Add vote to the results.
              emit VoteRevealed(voter, msg.sender, currentRoundId, identifier, time, ancillaryData, price, effectiveStake);
          }
          /**
           * @notice Commits a vote and logs an event with a data blob, typically an encrypted version of the vote
           * @dev An encrypted version of the vote is emitted in an event EncryptedVote to allow off-chain infrastructure to
           * retrieve the commit. The contents of encryptedVote are never used on chain: it is purely for convenience.
           * @param identifier unique price pair identifier. E.g. BTC/USD price pair.
           * @param time unix timestamp of the price request.
           * @param ancillaryData arbitrary data appended to a price request to give the voters more info from the caller.
           * @param hash keccak256 hash of the price you want to vote for and a int256 salt.
           * @param encryptedVote offchain encrypted blob containing the voter's amount, time and salt.
           */
          function commitAndEmitEncryptedVote(
              bytes32 identifier,
              uint256 time,
              bytes memory ancillaryData,
              bytes32 hash,
              bytes memory encryptedVote
          ) public override {
              commitVote(identifier, time, ancillaryData, hash);
              emit EncryptedVote(msg.sender, getCurrentRoundId(), identifier, time, ancillaryData, encryptedVote);
          }
          /****************************************
           *        VOTING GETTER FUNCTIONS       *
           ****************************************/
          /**
           * @notice Gets the requests that are being voted on this round.
           * @dev This view method returns requests with Active status that may be ahead of the stored contract state as this
           * also filters out requests that would be resolvable or deleted if the resolvable requests were processed with the
           * processResolvablePriceRequests() method.
           * @return pendingRequests array containing identifiers of type PendingRequestAncillaryAugmented.
           */
          function getPendingRequests() public view override returns (PendingRequestAncillaryAugmented[] memory) {
              // Solidity memory arrays aren't resizable (and reading storage is expensive). Hence this hackery to filter
              // pendingPriceRequestsIds only to those requests that have an Active RequestStatus.
              PendingRequestAncillaryAugmented[] memory unresolved =
                  new PendingRequestAncillaryAugmented[](pendingPriceRequestsIds.length);
              uint256 numUnresolved = 0;
              uint32 currentRoundId = getCurrentRoundId();
              for (uint256 i = 0; i < pendingPriceRequestsIds.length; i = unsafe_inc(i)) {
                  PriceRequest storage priceRequest = priceRequests[pendingPriceRequestsIds[i]];
                  if (_getRequestStatus(priceRequest, currentRoundId) == RequestStatus.Active) {
                      unresolved[numUnresolved] = PendingRequestAncillaryAugmented({
                          lastVotingRound: priceRequest.lastVotingRound,
                          isGovernance: priceRequest.isGovernance,
                          time: priceRequest.time,
                          rollCount: _getActualRollCount(priceRequest, currentRoundId),
                          identifier: priceRequest.identifier,
                          ancillaryData: priceRequest.ancillaryData
                      });
                      numUnresolved++;
                  }
              }
              PendingRequestAncillaryAugmented[] memory pendingRequests =
                  new PendingRequestAncillaryAugmented[](numUnresolved);
              for (uint256 i = 0; i < numUnresolved; i = unsafe_inc(i)) pendingRequests[i] = unresolved[i];
              return pendingRequests;
          }
          /**
           * @notice Checks if there are current active requests.
           * @return bool true if there are active requests, false otherwise.
           */
          function currentActiveRequests() public view returns (bool) {
              uint32 currentRoundId = getCurrentRoundId();
              for (uint256 i = 0; i < pendingPriceRequestsIds.length; i = unsafe_inc(i))
                  if (_getRequestStatus(priceRequests[pendingPriceRequestsIds[i]], currentRoundId) == RequestStatus.Active)
                      return true;
              return false;
          }
          /**
           * @notice Returns the current voting phase, as a function of the current time.
           * @return Phase to indicate the current phase. Either { Commit, Reveal, NUM_PHASES }.
           */
          function getVotePhase() public view override returns (Phase) {
              return Phase(uint256(voteTiming.computeCurrentPhase(getCurrentTime())));
          }
          /**
           * @notice Returns the current round ID, as a function of the current time.
           * @return uint32 the unique round ID.
           */
          function getCurrentRoundId() public view override returns (uint32) {
              return uint32(voteTiming.computeCurrentRoundId(getCurrentTime()));
          }
          /**
           * @notice Returns the round end time, as a function of the round number.
           * @param roundId representing the unique round ID.
           * @return uint256 representing the round end time.
           */
          function getRoundEndTime(uint256 roundId) external view returns (uint256) {
              return voteTiming.computeRoundEndTime(roundId);
          }
          /**
           * @notice Returns the number of current pending price requests to be voted and the number of resolved price
             requests over all time.
           * @dev This method might return stale values if the state of the contract has changed since the last time
             `processResolvablePriceRequests()` was called. To get the most up-to-date values, call
             `getNumberOfPriceRequestsPostUpdate()` instead.
           * @return numberPendingPriceRequests the total number of pending prices requests.
           * @return numberResolvedPriceRequests the total number of prices resolved over all time.
           */
          function getNumberOfPriceRequests()
              public
              view
              returns (uint256 numberPendingPriceRequests, uint256 numberResolvedPriceRequests)
          {
              return (pendingPriceRequestsIds.length, resolvedPriceRequestIds.length);
          }
          /**
           * @notice Returns the number of current pending price requests to be voted and the number of resolved price
             requests over all time after processing any resolvable price requests.
           * @return numberPendingPriceRequests the total number of pending prices requests.
           * @return numberResolvedPriceRequests the total number of prices resolved over all time.
           */
          function getNumberOfPriceRequestsPostUpdate()
              external
              returns (uint256 numberPendingPriceRequests, uint256 numberResolvedPriceRequests)
          {
              processResolvablePriceRequests();
              return getNumberOfPriceRequests();
          }
          /**
           * @notice Returns aggregate slashing trackers for a given request index.
           * @param requestIndex requestIndex the index of the request to fetch slashing trackers for.
           * @return SlashingTracker Tracker object contains the slashed UMA per staked UMA per wrong vote and no vote, the
           * total UMA slashed in the round and the total number of correct votes in the round.
           */
          function requestSlashingTrackers(uint256 requestIndex) public view returns (SlashingTracker memory) {
              PriceRequest storage priceRequest = priceRequests[resolvedPriceRequestIds[requestIndex]];
              uint32 lastVotingRound = priceRequest.lastVotingRound;
              VoteInstance storage voteInstance = priceRequest.voteInstances[lastVotingRound];
              uint256 totalVotes = voteInstance.results.totalVotes;
              uint256 totalCorrectVotes = voteInstance.results.getTotalCorrectlyVotedTokens();
              uint256 totalStaked = rounds[lastVotingRound].cumulativeStakeAtRound;
              (uint256 wrongVoteSlash, uint256 noVoteSlash) =
                  rounds[lastVotingRound].slashingLibrary.calcSlashing(
                      totalStaked,
                      totalVotes,
                      totalCorrectVotes,
                      requestIndex,
                      priceRequest.isGovernance
                  );
              uint256 totalSlashed =
                  ((noVoteSlash * (totalStaked - totalVotes)) + (wrongVoteSlash * (totalVotes - totalCorrectVotes))) / 1e18;
              return SlashingTracker(wrongVoteSlash, noVoteSlash, totalSlashed, totalCorrectVotes, lastVotingRound);
          }
          /**
           * @notice Returns the voter's participation in the vote for a given request index.
           * @param requestIndex requestIndex the index of the request to fetch slashing trackers for.
           * @param lastVotingRound the round to get voter participation for.
           * @param voter the voter to get participation for.
           * @return VoteParticipation enum representing the voter's participation in the vote.
           */
          function getVoterParticipation(
              uint256 requestIndex,
              uint32 lastVotingRound,
              address voter
          ) public view returns (VoteParticipation) {
              VoteInstance storage voteInstance =
                  priceRequests[resolvedPriceRequestIds[requestIndex]].voteInstances[lastVotingRound];
              bytes32 revealHash = voteInstance.voteSubmissions[voter].revealHash;
              if (revealHash == bytes32(0)) return VoteParticipation.DidNotVote;
              if (voteInstance.results.wasVoteCorrect(revealHash)) return VoteParticipation.CorrectVote;
              return VoteParticipation.WrongVote;
          }
          /****************************************
           *        OWNER ADMIN FUNCTIONS         *
           ****************************************/
          /**
           * @notice Disables this Voting contract in favor of the migrated one.
           * @dev Can only be called by the contract owner.
           * @param newVotingAddress the newly migrated contract address.
           */
          function setMigrated(address newVotingAddress) external override onlyOwner {
              migratedAddress = newVotingAddress;
              emit VotingContractMigrated(newVotingAddress);
          }
          /**
           * @notice Sets the maximum number of rounds to roll a request can have before the DVM auto deletes it.
           * @dev Can only be called by the contract owner.
           * @param newMaxRolls the new number of rounds to roll a request before the DVM auto deletes it.
           */
          function setMaxRolls(uint32 newMaxRolls) public override onlyOwner {
              // Changes to max rolls can impact unresolved requests. To protect against this process requests first.
              processResolvablePriceRequests();
              maxRolls = newMaxRolls;
              emit MaxRollsChanged(newMaxRolls);
          }
          /**
           * @notice Sets the maximum number of requests that can be made in a single round. Used to bound the maximum
           * sequential slashing that can be applied within a single round.
           * @dev Can only be called by the contract owner.
           * @param newMaxRequestsPerRound the new maximum number of requests that can be made in a single round.
           */
          function setMaxRequestPerRound(uint32 newMaxRequestsPerRound) public override onlyOwner {
              require(newMaxRequestsPerRound > 0);
              maxRequestsPerRound = newMaxRequestsPerRound;
              emit MaxRequestsPerRoundChanged(newMaxRequestsPerRound);
          }
          /**
           * @notice Resets the GAT number and SPAT percentage. GAT is the minimum number of tokens that must participate in a
           * vote for it to resolve (quorum number). SPAT is the minimum percentage of tokens that must agree on a result
           * for it to resolve (percentage of staked tokens) This change only applies to subsequent rounds.
           * @param newGat sets the next round's GAT and going forward.
           * @param newSpat sets the next round's SPAT and going forward.
           */
          function setGatAndSpat(uint128 newGat, uint64 newSpat) public override onlyOwner {
              require(newGat < votingToken.totalSupply() && newGat > 0);
              require(newSpat > 0 && newSpat < 1e18);
              gat = newGat;
              spat = newSpat;
              emit GatAndSpatChanged(newGat, newSpat);
          }
          /**
           * @notice Changes the slashing library used by this contract.
           * @param _newSlashingLibrary new slashing library address.
           */
          function setSlashingLibrary(address _newSlashingLibrary) public override onlyOwner {
              slashingLibrary = SlashingLibraryInterface(_newSlashingLibrary);
              emit SlashingLibraryChanged(_newSlashingLibrary);
          }
          /****************************************
           *          STAKING FUNCTIONS           *
           ****************************************/
          /**
           * @notice Updates the voter's trackers for staking and slashing. Applies all unapplied slashing to given staker.
           * @dev Can be called by anyone, but it is not necessary for the contract to function is run the other functions.
           * @param voter address of the voter to update the trackers for.
           */
          function updateTrackers(address voter) external {
              _updateTrackers(voter);
          }
          /**
           * @notice Updates the voter's trackers for staking and voting, specifying a maximum number of resolved requests to
           * traverse. This function can be used in place of updateTrackers to process the trackers in batches, hence avoiding
           * potential issues if the number of elements to be processed is large and the associated gas cost is too high.
           * @param voter address of the voter to update the trackers for.
           * @param maxTraversals maximum number of resolved requests to traverse in this call.
           */
          function updateTrackersRange(address voter, uint64 maxTraversals) external {
              processResolvablePriceRequests();
              _updateAccountSlashingTrackers(voter, maxTraversals);
          }
          // Updates the global and selected wallet's trackers for staking and voting. Note that the order of these calls is
          // very important due to the interplay between slashing and inactive/active liquidity.
          function _updateTrackers(address voter) internal override {
              processResolvablePriceRequests();
              _updateAccountSlashingTrackers(voter, UINT64_MAX);
              super._updateTrackers(voter);
          }
          /**
           * @notice Process and resolve all resolvable price requests. This function traverses all pending price requests and
           *  resolves them if they are resolvable. It also rolls and deletes requests, if required.
           */
          function processResolvablePriceRequests() public {
              _processResolvablePriceRequests(UINT64_MAX);
          }
          /**
           * @notice Process and resolve all resolvable price requests. This function traverses all pending price requests and
           * resolves them if they are resolvable. It also rolls and deletes requests, if required. This function can be used
           * in place of processResolvablePriceRequests to process the requests in batches, hence avoiding potential issues if
           * the number of elements to be processed is large and the associated gas cost is too high.
           * @param maxTraversals maximum number of resolved requests to traverse in this call.
           */
          function processResolvablePriceRequestsRange(uint64 maxTraversals) external {
              _processResolvablePriceRequests(maxTraversals);
          }
          // Starting index for a staker is the first value that nextIndexToProcess is set to and defines the first index that
          // a staker is suspectable to receiving slashing on. This is set to current length of the resolvedPriceRequestIds.
          // Note first call processResolvablePriceRequests to ensure that the resolvedPriceRequestIds array is up to date.
          function _getStartingIndexForStaker() internal override returns (uint64) {
              processResolvablePriceRequests();
              return SafeCast.toUint64(resolvedPriceRequestIds.length);
          }
          // Checks if we are in an active voting reveal phase (currently revealing votes). This impacts if a new staker's
          // stake should be activated immediately or if it should be frozen until the end of the reveal phase.
          function _inActiveReveal() internal view override returns (bool) {
              return (currentActiveRequests() && getVotePhase() == Phase.Reveal);
          }
          // This function must be called before any tokens are staked. It updates the voter's pending stakes to reflect the
          // new amount to stake. These updates are only made if we are in an active reveal. This is required to appropriately
          // calculate a voter's trackers and avoid slashing them for amounts staked during an active reveal phase.
          function _computePendingStakes(address voter, uint128 amount) internal override {
              if (_inActiveReveal()) {
                  uint32 currentRoundId = getCurrentRoundId();
                  // Freeze round variables to prevent cumulativeActiveStakeAtRound from changing based on the stakes during
                  // the active reveal phase. This will happen if the first action within the reveal is someone staking.
                  _freezeRoundVariables(currentRoundId);
                  // Increment pending stake for voter by amount. With the omission of stake from cumulativeActiveStakeAtRound
                  // for this round, ensure that the pending stakes is not included in the slashing calculation for this round.
                  _incrementPendingStake(voter, currentRoundId, amount);
              }
          }
          // Updates the slashing trackers of a given account based on previous voting activity. This traverses all resolved
          // requests for each voter and for each request checks if the voter voted correctly or not. Based on the voters
          // voting activity the voters balance is updated accordingly. The caller can provide a maxTraversals parameter to
          // limit the number of resolved requests to traverse in this call to bound the gas used. Note each iteration of
          // this function re-uses a fresh slash variable to produce useful logs on the amount a voter is slashed.
          function _updateAccountSlashingTrackers(address voter, uint64 maxTraversals) internal {
              VoterStake storage voterStake = voterStakes[voter];
              uint64 requestIndex = voterStake.nextIndexToProcess; // Traverse all requests from the last considered request.
              // Traverse all elements within the resolvedPriceRequestIds array and update the voter's trackers according to
              // their voting activity. Bound the number of iterations to the maxTraversals parameter to cap the gas used.
              while (requestIndex < resolvedPriceRequestIds.length && maxTraversals > 0) {
                  maxTraversals = unsafe_dec_64(maxTraversals); // reduce the number of traversals left & re-use the prop.
                  // Get the slashing for this request. This comes from the slashing library and informs to the voter slash.
                  SlashingTracker memory trackers = requestSlashingTrackers(requestIndex);
                  // Use the effective stake as the difference between the current stake and pending stake. The staker will
                  //have a pending stake if they staked during an active reveal for the voting round in question.
                  uint256 effectiveStake = voterStake.stake - voterStake.pendingStakes[trackers.lastVotingRound];
                  int256 slash; // The amount to slash the voter by for this request. Reset on each entry to emit useful logs.
                  // Get the voter participation for this request. This informs if the voter voted correctly or not.
                  VoteParticipation participation = getVoterParticipation(requestIndex, trackers.lastVotingRound, voter);
                  // The voter did not reveal or did not commit. Slash at noVote rate.
                  if (participation == VoteParticipation.DidNotVote)
                      slash = -int256(Math.ceilDiv(effectiveStake * trackers.noVoteSlashPerToken, 1e18));
                      // The voter did not vote with the majority. Slash at wrongVote rate.
                  else if (participation == VoteParticipation.WrongVote)
                      slash = -int256(Math.ceilDiv(effectiveStake * trackers.wrongVoteSlashPerToken, 1e18));
                      // Else, the voter voted correctly. Receive a pro-rate share of the other voters slash.
                  else slash = int256((effectiveStake * trackers.totalSlashed) / trackers.totalCorrectVotes);
                  emit VoterSlashed(voter, requestIndex, int128(slash));
                  voterStake.unappliedSlash += int128(slash);
                  // If the next round is different to the current considered round, apply the slash to the voter.
                  if (isNextRequestRoundDifferent(requestIndex)) _applySlashToVoter(voterStake, voter);
                  requestIndex = unsafe_inc_64(requestIndex); // Increment the request index.
              }
              // Set the account's nextIndexToProcess to the requestIndex so the next entry starts where we left off.
              voterStake.nextIndexToProcess = requestIndex;
          }
          // Applies a given slash to a given voter's stake. In the event the sum of the slash and the voter's stake is less
          // than 0, the voter's stake is set to 0 to prevent the voter's stake from going negative. unappliedSlash tracked
          // all slashing the staker has received but not yet applied to their stake. Apply it then set it to zero.
          function _applySlashToVoter(VoterStake storage voterStake, address voter) internal {
              if (voterStake.unappliedSlash + int128(voterStake.stake) > 0)
                  voterStake.stake = uint128(int128(voterStake.stake) + voterStake.unappliedSlash);
              else voterStake.stake = 0;
              emit VoterSlashApplied(voter, voterStake.unappliedSlash, voterStake.stake);
              voterStake.unappliedSlash = 0;
          }
          // Checks if the next round (index+1) is different to the current round (index).
          function isNextRequestRoundDifferent(uint64 index) internal view returns (bool) {
              if (index + 1 >= resolvedPriceRequestIds.length) return true;
              return
                  priceRequests[resolvedPriceRequestIds[index]].lastVotingRound !=
                  priceRequests[resolvedPriceRequestIds[index + 1]].lastVotingRound;
          }
          /****************************************
           *      MIGRATION SUPPORT FUNCTIONS     *
           ****************************************/
          /**
           * @notice Enable retrieval of rewards on a previously migrated away from voting contract. This function is intended
           * on being removed from future versions of the Voting contract and aims to solve a short term migration pain point.
           * @param voter voter for which rewards will be retrieved. Does not have to be the caller.
           * @param roundId the round from which voting rewards will be retrieved from.
           * @param toRetrieve array of PendingRequests which rewards are retrieved from.
           * @return uint256 the amount of rewards.
           */
          function retrieveRewardsOnMigratedVotingContract(
              address voter,
              uint256 roundId,
              MinimumVotingAncillaryInterface.PendingRequestAncillary[] memory toRetrieve
          ) external returns (uint256) {
              uint256 rewards =
                  MinimumVotingAncillaryInterface(address(previousVotingContract))
                      .retrieveRewards(voter, roundId, toRetrieve)
                      .rawValue;
              return rewards;
          }
          /****************************************
           *    PRIVATE AND INTERNAL FUNCTIONS    *
           ****************************************/
          // Deletes a request from the pending requests array, based on index. Swap and pop.
          function _removeRequestFromPendingPriceRequestsIds(uint64 pendingRequestIndex) internal {
              pendingPriceRequestsIds[pendingRequestIndex] = pendingPriceRequestsIds[pendingPriceRequestsIds.length - 1];
              pendingPriceRequestsIds.pop();
          }
          // Returns the price for a given identifier. Three params are returns: bool if there was an error, int to represent
          // the resolved price and a string which is filled with an error message, if there was an error or "".
          // This method considers actual request status that might be ahead of the stored contract state that gets updated
          // only after processResolvablePriceRequests() is called.
          function _getPriceOrError(
              bytes32 identifier,
              uint256 time,
              bytes memory ancillaryData
          )
              internal
              view
              returns (
                  bool,
                  int256,
                  string memory
              )
          {
              PriceRequest storage priceRequest = _getPriceRequest(identifier, time, ancillaryData);
              uint32 currentRoundId = getCurrentRoundId();
              RequestStatus requestStatus = _getRequestStatus(priceRequest, currentRoundId);
              if (requestStatus == RequestStatus.Active) return (false, 0, "Current voting round not ended");
              if (requestStatus == RequestStatus.Resolved) {
                  VoteInstance storage voteInstance = priceRequest.voteInstances[priceRequest.lastVotingRound];
                  (, int256 resolvedPrice) = _getResolvedPrice(voteInstance, priceRequest.lastVotingRound);
                  return (true, resolvedPrice, "");
              }
              if (requestStatus == RequestStatus.Future) return (false, 0, "Price is still to be voted on");
              if (requestStatus == RequestStatus.ToDelete) return (false, 0, "Price will be deleted");
              (bool previouslyResolved, int256 previousPrice) =
                  _getPriceFromPreviousVotingContract(identifier, time, ancillaryData);
              if (previouslyResolved) return (true, previousPrice, "");
              return (false, 0, "Price was never requested");
          }
          // Check the previousVotingContract to see if a given price request was resolved.
          // Returns true or false, and the resolved price or zero, depending on whether it was found or not.
          function _getPriceFromPreviousVotingContract(
              bytes32 identifier,
              uint256 time,
              bytes memory ancillaryData
          ) private view returns (bool, int256) {
              if (address(previousVotingContract) == address(0)) return (false, 0);
              if (previousVotingContract.hasPrice(identifier, time, ancillaryData))
                  return (true, previousVotingContract.getPrice(identifier, time, ancillaryData));
              return (false, 0);
          }
          // Returns a price request object for a given identifier, time and ancillary data.
          function _getPriceRequest(
              bytes32 identifier,
              uint256 time,
              bytes memory ancillaryData
          ) private view returns (PriceRequest storage) {
              return priceRequests[_encodePriceRequest(identifier, time, ancillaryData)];
          }
          // Returns an encoded bytes32 representing a price request. Used when storing/referencing price requests.
          function _encodePriceRequest(
              bytes32 identifier,
              uint256 time,
              bytes memory ancillaryData
          ) private pure returns (bytes32) {
              return keccak256(abi.encode(identifier, time, ancillaryData));
          }
          // Stores ("freezes") variables that should not shift within an active voting round. Called on reveal but only makes
          // a state change if and only if the this is the first reveal.
          function _freezeRoundVariables(uint256 roundId) private {
              // Only freeze the round if this is the first request in the round.
              if (rounds[roundId].minParticipationRequirement == 0) {
                  rounds[roundId].slashingLibrary = slashingLibrary;
                  // The minimum required participation for a vote to settle within this round is the GAT (fixed number).
                  rounds[roundId].minParticipationRequirement = gat;
                  // The minimum votes on the modal outcome for the vote to settle within this round is the SPAT (percentage).
                  rounds[roundId].minAgreementRequirement = uint128((spat * uint256(cumulativeStake)) / 1e18);
                  rounds[roundId].cumulativeStakeAtRound = cumulativeStake; // Store the cumulativeStake to work slashing.
              }
          }
          // Traverse pending price requests and resolve any that are resolvable. If requests are rollable (they did not
          // resolve in the previous round and are to be voted in a subsequent round) then roll them. If requests can be
          // deleted (they have been rolled up to the maxRolls counter) then delete them. The caller can pass in maxTraversals
          // to limit the number of requests that are resolved in a single call to bound the total gas used by this function.
          // Note that the resolved index is stores for each round. This means that only the first caller of this function
          // per round needs to traverse the pending requests. After that subsequent calls to this are a no-op for that round.
          function _processResolvablePriceRequests(uint64 maxTraversals) private {
              uint32 currentRoundId = getCurrentRoundId();
              // Load in the last resolved index for this round to continue off from where the last caller left.
              uint64 requestIndex = lastRoundIdProcessed == currentRoundId ? nextPendingIndexToProcess : 0;
              // Traverse pendingPriceRequestsIds array and update the requests status according to the state of the request
              //(i.e settle, roll or delete request). Bound iterations to the maxTraversals parameter to cap the gas used.
              while (requestIndex < pendingPriceRequestsIds.length && maxTraversals > 0) {
                  maxTraversals = unsafe_dec_64(maxTraversals);
                  PriceRequest storage request = priceRequests[pendingPriceRequestsIds[requestIndex]];
                  // If the last voting round is greater than or equal to the current round then this request is currently
                  // being voted on or is enqueued for the next round. In this case, skip it and increment the request index.
                  if (request.lastVotingRound >= currentRoundId) {
                      requestIndex = unsafe_inc_64(requestIndex);
                      continue; // Continue to the next request.
                  }
                  // Else, we are dealing with a request that can either be: a) deleted, b) rolled or c) resolved.
                  VoteInstance storage voteInstance = request.voteInstances[request.lastVotingRound];
                  (bool isResolvable, int256 resolvedPrice) = _getResolvedPrice(voteInstance, request.lastVotingRound);
                  if (isResolvable) {
                      // If resolvable, resolve. This involves a) moving the requestId from pendingPriceRequestsIds array to
                      // resolvedPriceRequestIds array and b) removing requestId from pendingPriceRequestsIds. Don't need to
                      // increment requestIndex as from pendingPriceRequestsIds amounts to decreasing the while loop bound.
                      resolvedPriceRequestIds.push(pendingPriceRequestsIds[requestIndex]);
                      _removeRequestFromPendingPriceRequestsIds(requestIndex);
                      emit RequestResolved(
                          request.lastVotingRound,
                          resolvedPriceRequestIds.length - 1,
                          request.identifier,
                          request.time,
                          request.ancillaryData,
                          resolvedPrice
                      );
                      continue; // Continue to the next request.
                  }
                  // If not resolvable, but the round has passed its voting round, then it must be deleted or rolled. First,
                  // increment the rollCount. Use the difference between the current round and the last voting round to
                  // accommodate the contract not being touched for any number of rounds during the roll.
                  request.rollCount += currentRoundId - request.lastVotingRound;
                  // If the roll count exceeds the threshold and the request is not governance then it is deletable.
                  if (_shouldDeleteRequest(request.rollCount, request.isGovernance)) {
                      emit RequestDeleted(request.identifier, request.time, request.ancillaryData, request.rollCount);
                      delete priceRequests[pendingPriceRequestsIds[requestIndex]];
                      _removeRequestFromPendingPriceRequestsIds(requestIndex);
                      continue;
                  }
                  // Else, the request should be rolled. This involves only moving forward the lastVotingRound.
                  request.lastVotingRound = getRoundIdToVoteOnRequest(currentRoundId);
                  ++rounds[request.lastVotingRound].numberOfRequestsToVote;
                  emit RequestRolled(request.identifier, request.time, request.ancillaryData, request.rollCount);
                  requestIndex = unsafe_inc_64(requestIndex);
              }
              lastRoundIdProcessed = currentRoundId; // Store the roundId that was processed.
              nextPendingIndexToProcess = requestIndex; // Store the index traversed up to for this round.
          }
          // Returns a price request status. A request is either: NotRequested, Active, Resolved, Future or ToDelete.
          function _getRequestStatus(PriceRequest storage priceRequest, uint32 currentRoundId)
              private
              view
              returns (RequestStatus)
          {
              if (priceRequest.lastVotingRound == 0) return RequestStatus.NotRequested;
              if (priceRequest.lastVotingRound < currentRoundId) {
                  // Check if the request has already been resolved
                  VoteInstance storage voteInstance = priceRequest.voteInstances[priceRequest.lastVotingRound];
                  (bool isResolved, ) = _getResolvedPrice(voteInstance, priceRequest.lastVotingRound);
                  if (isResolved) return RequestStatus.Resolved;
                  if (_shouldDeleteRequest(_getActualRollCount(priceRequest, currentRoundId), priceRequest.isGovernance))
                      return RequestStatus.ToDelete;
                  return RequestStatus.Active;
              }
              if (priceRequest.lastVotingRound == currentRoundId) return RequestStatus.Active;
              return RequestStatus.Future; // Means than priceRequest.lastVotingRound > currentRoundId
          }
          function _getResolvedPrice(VoteInstance storage voteInstance, uint256 lastVotingRound)
              internal
              view
              returns (bool isResolved, int256 price)
          {
              return
                  voteInstance.results.getResolvedPrice(
                      rounds[lastVotingRound].minParticipationRequirement,
                      rounds[lastVotingRound].minAgreementRequirement
                  );
          }
          // Gas optimized uint256 increment.
          function unsafe_inc(uint256 x) internal pure returns (uint256) {
              unchecked { return x + 1; }
          }
          // Gas optimized uint64 increment.
          function unsafe_inc_64(uint64 x) internal pure returns (uint64) {
              unchecked { return x + 1; }
          }
          // Gas optimized uint64 decrement.
          function unsafe_dec_64(uint64 x) internal pure returns (uint64) {
              unchecked { return x - 1; }
          }
          // Returns the registered identifier whitelist, stored in the finder.
          function _getIdentifierWhitelist() private view returns (IdentifierWhitelistInterface) {
              return IdentifierWhitelistInterface(finder.getImplementationAddress(OracleInterfaces.IdentifierWhitelist));
          }
          // Reverts if the contract has been migrated. Used in a modifier, defined as a private function for gas savings.
          function _requireNotMigrated() private view {
              require(migratedAddress == address(0), "Contract migrated");
          }
          // Enforces that a calling contract is registered.
          function _requireRegisteredContract() private view {
              RegistryInterface registry = RegistryInterface(finder.getImplementationAddress(OracleInterfaces.Registry));
              require(registry.isContractRegistered(msg.sender) || msg.sender == migratedAddress, "Caller not registered");
          }
          // Checks if a request should be deleted. A non-gevernance request should be deleted if it has been rolled more than
          // the maxRolls.
          function _shouldDeleteRequest(uint256 rollCount, bool isGovernance) private view returns (bool) {
              return rollCount > maxRolls && !isGovernance;
          }
          // Returns the actual roll count of a request. This is the roll count plus the number of rounds that have passed
          // since the last voting round.
          function _getActualRollCount(PriceRequest storage priceRequest, uint32 currentRoundId)
              private
              view
              returns (uint32)
          {
              if (currentRoundId <= priceRequest.lastVotingRound) return priceRequest.rollCount;
              return priceRequest.rollCount + currentRoundId - priceRequest.lastVotingRound;
          }
      }
      // SPDX-License-Identifier: AGPL-3.0-only
      pragma solidity ^0.8.0;
      /**
       * @title Provides addresses of the live contracts implementing certain interfaces.
       * @dev Examples are the Oracle or Store interfaces.
       */
      interface FinderInterface {
          /**
           * @notice Updates the address of the contract that implements `interfaceName`.
           * @param interfaceName bytes32 encoding of the interface name that is either changed or registered.
           * @param implementationAddress address of the deployed contract that implements the interface.
           */
          function changeImplementationAddress(bytes32 interfaceName, address implementationAddress) external;
          /**
           * @notice Gets the address of the contract that implements the given `interfaceName`.
           * @param interfaceName queried interface.
           * @return implementationAddress address of the deployed contract that implements the interface.
           */
          function getImplementationAddress(bytes32 interfaceName) external view returns (address);
      }
      // SPDX-License-Identifier: AGPL-3.0-only
      pragma solidity ^0.8.0;
      /**
       * @title Interface for whitelists of supported identifiers that the oracle can provide prices for.
       */
      interface IdentifierWhitelistInterface {
          /**
           * @notice Adds the provided identifier as a supported identifier.
           * @dev Price requests using this identifier will succeed after this call.
           * @param identifier bytes32 encoding of the string identifier. Eg: BTC/USD.
           */
          function addSupportedIdentifier(bytes32 identifier) external;
          /**
           * @notice Removes the identifier from the whitelist.
           * @dev Price requests using this identifier will no longer succeed after this call.
           * @param identifier bytes32 encoding of the string identifier. Eg: BTC/USD.
           */
          function removeSupportedIdentifier(bytes32 identifier) external;
          /**
           * @notice Checks whether an identifier is on the whitelist.
           * @param identifier bytes32 encoding of the string identifier. Eg: BTC/USD.
           * @return bool if the identifier is supported (or not).
           */
          function isIdentifierSupported(bytes32 identifier) external view returns (bool);
      }
      // SPDX-License-Identifier: AGPL-3.0-only
      pragma solidity 0.8.16;
      interface MinimumVotingAncillaryInterface {
          struct Unsigned {
              uint256 rawValue;
          }
          struct PendingRequestAncillary {
              bytes32 identifier;
              uint256 time;
              bytes ancillaryData;
          }
          function retrieveRewards(
              address voterAddress,
              uint256 roundId,
              PendingRequestAncillary[] memory toRetrieve
          ) external returns (Unsigned memory);
      }
      // SPDX-License-Identifier: AGPL-3.0-only
      pragma solidity ^0.8.0;
      /**
       * @title Financial contract facing Oracle interface.
       * @dev Interface used by financial contracts to interact with the Oracle. Voters will use a different interface.
       */
      abstract contract OracleAncillaryInterface {
          /**
           * @notice Enqueues a request (if a request isn't already present) for the given `identifier`, `time` pair.
           * @dev Time must be in the past and the identifier must be supported.
           * @param identifier uniquely identifies the price requested. eg BTC/USD (encoded as bytes32) could be requested.
           * @param ancillaryData arbitrary data appended to a price request to give the voters more info from the caller.
           * @param time unix timestamp for the price request.
           */
          function requestPrice(
              bytes32 identifier,
              uint256 time,
              bytes memory ancillaryData
          ) public virtual;
          /**
           * @notice Whether the price for `identifier` and `time` is available.
           * @dev Time must be in the past and the identifier must be supported.
           * @param identifier uniquely identifies the price requested. eg BTC/USD (encoded as bytes32) could be requested.
           * @param time unix timestamp for the price request.
           * @param ancillaryData arbitrary data appended to a price request to give the voters more info from the caller.
           * @return bool if the DVM has resolved to a price for the given identifier and timestamp.
           */
          function hasPrice(
              bytes32 identifier,
              uint256 time,
              bytes memory ancillaryData
          ) public view virtual returns (bool);
          /**
           * @notice Gets the price for `identifier` and `time` if it has already been requested and resolved.
           * @dev If the price is not available, the method reverts.
           * @param identifier uniquely identifies the price requested. eg BTC/USD (encoded as bytes32) could be requested.
           * @param time unix timestamp for the price request.
           * @param ancillaryData arbitrary data appended to a price request to give the voters more info from the caller.
           * @return int256 representing the resolved price for the given identifier and timestamp.
           */
          function getPrice(
              bytes32 identifier,
              uint256 time,
              bytes memory ancillaryData
          ) public view virtual returns (int256);
      }
      // SPDX-License-Identifier: AGPL-3.0-only
      pragma solidity ^0.8.0;
      import "./OracleInterface.sol";
      import "./OracleAncillaryInterface.sol";
      /**
       * @title Financial contract facing extending the Oracle interface with governance actions.
       * @dev Interface used by financial contracts to interact with the Oracle extending governance actions. Voters will use a different interface.
       */
      abstract contract OracleGovernanceInterface is OracleInterface, OracleAncillaryInterface {
          /**
           * @notice Enqueues a request (if a request isn't already present) for the given `identifier`, `time` pair.
           * @dev Time must be in the past and the identifier must be supported.
           * @param identifier uniquely identifies the price requested. eg BTC/USD (encoded as bytes32) could be requested.
           * @param ancillaryData arbitrary data appended to a price request to give the voters more info from the caller.
           * @param time unix timestamp for the price request.
           */
          function requestGovernanceAction(
              bytes32 identifier,
              uint256 time,
              bytes memory ancillaryData
          ) external virtual;
      }
      // SPDX-License-Identifier: AGPL-3.0-only
      pragma solidity ^0.8.0;
      /**
       * @title Financial contract facing Oracle interface.
       * @dev Interface used by financial contracts to interact with the Oracle. Voters will use a different interface.
       */
      abstract contract OracleInterface {
          /**
           * @notice Enqueues a request (if a request isn't already present) for the given `identifier`, `time` pair.
           * @dev Time must be in the past and the identifier must be supported.
           * @param identifier uniquely identifies the price requested. eg BTC/USD (encoded as bytes32) could be requested.
           * @param time unix timestamp for the price request.
           */
          function requestPrice(bytes32 identifier, uint256 time) external virtual;
          /**
           * @notice Whether the price for `identifier` and `time` is available.
           * @dev Time must be in the past and the identifier must be supported.
           * @param identifier uniquely identifies the price requested. eg BTC/USD (encoded as bytes32) could be requested.
           * @param time unix timestamp for the price request.
           * @return bool if the DVM has resolved to a price for the given identifier and timestamp.
           */
          function hasPrice(bytes32 identifier, uint256 time) external view virtual returns (bool);
          /**
           * @notice Gets the price for `identifier` and `time` if it has already been requested and resolved.
           * @dev If the price is not available, the method reverts.
           * @param identifier uniquely identifies the price requested. eg BTC/USD (encoded as bytes32) could be requested.
           * @param time unix timestamp for the price request.
           * @return int256 representing the resolved price for the given identifier and timestamp.
           */
          function getPrice(bytes32 identifier, uint256 time) external view virtual returns (int256);
      }
      // SPDX-License-Identifier: AGPL-3.0-only
      pragma solidity ^0.8.0;
      /**
       * @title Interface for a registry of contracts and contract creators.
       */
      interface RegistryInterface {
          /**
           * @notice Registers a new contract.
           * @dev Only authorized contract creators can call this method.
           * @param parties an array of addresses who become parties in the contract.
           * @param contractAddress defines the address of the deployed contract.
           */
          function registerContract(address[] calldata parties, address contractAddress) external;
          /**
           * @notice Returns whether the contract has been registered with the registry.
           * @dev If it is registered, it is an authorized participant in the UMA system.
           * @param contractAddress address of the contract.
           * @return bool indicates whether the contract is registered.
           */
          function isContractRegistered(address contractAddress) external view returns (bool);
          /**
           * @notice Returns a list of all contracts that are associated with a particular party.
           * @param party address of the party.
           * @return an array of the contracts the party is registered to.
           */
          function getRegisteredContracts(address party) external view returns (address[] memory);
          /**
           * @notice Returns all registered contracts.
           * @return all registered contract addresses within the system.
           */
          function getAllRegisteredContracts() external view returns (address[] memory);
          /**
           * @notice Adds a party to the calling contract.
           * @dev msg.sender must be the contract to which the party member is added.
           * @param party address to be added to the contract.
           */
          function addPartyToContract(address party) external;
          /**
           * @notice Removes a party member to the calling contract.
           * @dev msg.sender must be the contract to which the party member is added.
           * @param party address to be removed from the contract.
           */
          function removePartyFromContract(address party) external;
          /**
           * @notice checks if an address is a party in a contract.
           * @param party party to check.
           * @param contractAddress address to check against the party.
           * @return bool indicating if the address is a party of the contract.
           */
          function isPartyMemberOfContract(address party, address contractAddress) external view returns (bool);
      }
      // SPDX-License-Identifier: AGPL-3.0-only
      pragma solidity 0.8.16;
      interface SlashingLibraryInterface {
          /**
           * @notice Calculates the wrong vote slash per token.
           * @param totalStaked The total amount of tokens staked.
           * @param totalVotes The total amount of votes.
           * @param totalCorrectVotes The total amount of correct votes.
           * @param priceRequestIndex The price request index within the resolvedPriceRequestIds array.
           * @return uint256 The amount of tokens to slash per token staked.
           */
          function calcWrongVoteSlashPerToken(
              uint256 totalStaked,
              uint256 totalVotes,
              uint256 totalCorrectVotes,
              uint256 priceRequestIndex
          ) external view returns (uint256);
          /**
           * @notice Calculates the wrong vote slash per token for governance requests.
           * @param totalStaked The total amount of tokens staked.
           * @param totalVotes The total amount of votes.
           * @param totalCorrectVotes The total amount of correct votes.
           * @param priceRequestIndex The price request index within the resolvedPriceRequestIds array.
           * @return uint256 The amount of tokens to slash per token staked.
           */
          function calcWrongVoteSlashPerTokenGovernance(
              uint256 totalStaked,
              uint256 totalVotes,
              uint256 totalCorrectVotes,
              uint256 priceRequestIndex
          ) external view returns (uint256);
          /**
           * @notice Calculates the no vote slash per token.
           * @param totalStaked The total amount of tokens staked.
           * @param totalVotes The total amount of votes.
           * @param totalCorrectVotes The total amount of correct votes.
           * @param priceRequestIndex The price request index within the resolvedPriceRequestIds array.
           * @return uint256 The amount of tokens to slash per token staked.
           */
          function calcNoVoteSlashPerToken(
              uint256 totalStaked,
              uint256 totalVotes,
              uint256 totalCorrectVotes,
              uint256 priceRequestIndex
          ) external view returns (uint256);
          /**
           * @notice Calculates all slashing trackers in one go to decrease cross-contract calls needed.
           * @param totalStaked The total amount of tokens staked.
           * @param totalVotes The total amount of votes.
           * @param totalCorrectVotes The total amount of correct votes.
           * @param priceRequestIndex The price request index within the resolvedPriceRequestIds array.
           * @param isGovernance Whether the request is a governance request.
           * @return wrongVoteSlashPerToken The amount of tokens to slash for voting wrong.
           * @return noVoteSlashPerToken The amount of tokens to slash for not voting.
           */
          function calcSlashing(
              uint256 totalStaked,
              uint256 totalVotes,
              uint256 totalCorrectVotes,
              uint256 priceRequestIndex,
              bool isGovernance
          ) external view returns (uint256 wrongVoteSlashPerToken, uint256 noVoteSlashPerToken);
      }
      // SPDX-License-Identifier: AGPL-3.0-only
      pragma solidity 0.8.16;
      import "../implementation/VotingToken.sol";
      import "../../common/interfaces/ExpandedIERC20.sol";
      interface StakerInterface {
          function votingToken() external returns (ExpandedIERC20);
          function stake(uint128 amount) external;
          function requestUnstake(uint128 amount) external;
          function executeUnstake() external;
          function withdrawRewards() external returns (uint128);
          function withdrawAndRestake() external returns (uint128);
          function setEmissionRate(uint128 newEmissionRate) external;
          function setUnstakeCoolDown(uint64 newUnstakeCoolDown) external;
          /**
           * @notice Sets the delegate of a voter. This delegate can vote on behalf of the staker. The staker will still own
           * all staked balances, receive rewards and be slashed based on the actions of the delegate. Intended use is using a
           * low-security available wallet for voting while keeping access to staked amounts secure by a more secure wallet.
           * @param delegate the address of the delegate.
           */
          function setDelegate(address delegate) external virtual;
          /**
           * @notice Sets the delegator of a voter. Acts to accept a delegation. The delegate can only vote for the delegator
           * if the delegator also selected the delegate to do so (two-way relationship needed).
           * @param delegator the address of the delegator.
           */
          function setDelegator(address delegator) external virtual;
      }
      // SPDX-License-Identifier: AGPL-3.0-only
      pragma solidity ^0.8.0;
      import "../../common/implementation/FixedPoint.sol";
      /**
       * @title Interface that voters must use to Vote on price request resolutions.
       */
      abstract contract VotingAncillaryInterface {
          struct PendingRequestAncillary {
              bytes32 identifier;
              uint256 time;
              bytes ancillaryData;
          }
          // Captures the necessary data for making a commitment.
          // Used as a parameter when making batch commitments.
          // Not used as a data structure for storage.
          struct CommitmentAncillary {
              bytes32 identifier;
              uint256 time;
              bytes ancillaryData;
              bytes32 hash;
              bytes encryptedVote;
          }
          // Captures the necessary data for revealing a vote.
          // Used as a parameter when making batch reveals.
          // Not used as a data structure for storage.
          struct RevealAncillary {
              bytes32 identifier;
              uint256 time;
              int256 price;
              bytes ancillaryData;
              int256 salt;
          }
          // Note: the phases must be in order. Meaning the first enum value must be the first phase, etc.
          // `NUM_PHASES` is to get the number of phases. It isn't an actual phase, and it should always be last.
          enum Phase { Commit, Reveal, NUM_PHASES }
          /**
           * @notice Commit a vote for a price request for `identifier` at `time`.
           * @dev `identifier`, `time` must correspond to a price request that's currently in the commit phase.
           * Commits can be changed.
           * @dev Since transaction data is public, the salt will be revealed with the vote. While this is the system’s expected behavior,
           * voters should never reuse salts. If someone else is able to guess the voted price and knows that a salt will be reused, then
           * they can determine the vote pre-reveal.
           * @param identifier uniquely identifies the committed vote. E.G. BTC/USD price pair.
           * @param time unix timestamp of the price being voted on.
           * @param hash keccak256 hash of the `price`, `salt`, voter `address`, `time`, current `roundId`, and `identifier`.
           */
          function commitVote(
              bytes32 identifier,
              uint256 time,
              bytes memory ancillaryData,
              bytes32 hash
          ) public virtual;
          /**
           * @notice Submit a batch of commits in a single transaction.
           * @dev Using `encryptedVote` is optional. If included then commitment is stored on chain.
           * Look at `project-root/common/Constants.js` for the tested maximum number of
           * commitments that can fit in one transaction.
           * @param commits array of structs that encapsulate an `identifier`, `time`, `hash` and optional `encryptedVote`.
           */
          function batchCommit(CommitmentAncillary[] memory commits) public virtual;
          /**
           * @notice commits a vote and logs an event with a data blob, typically an encrypted version of the vote
           * @dev An encrypted version of the vote is emitted in an event `EncryptedVote` to allow off-chain infrastructure to
           * retrieve the commit. The contents of `encryptedVote` are never used on chain: it is purely for convenience.
           * @param identifier unique price pair identifier. E.g. BTC/USD price pair.
           * @param time unix timestamp of for the price request.
           * @param hash keccak256 hash of the price you want to vote for and a `int256 salt`.
           * @param encryptedVote offchain encrypted blob containing the voters amount, time and salt.
           */
          function commitAndEmitEncryptedVote(
              bytes32 identifier,
              uint256 time,
              bytes memory ancillaryData,
              bytes32 hash,
              bytes memory encryptedVote
          ) public virtual;
          /**
           * @notice snapshot the current round's token balances and lock in the inflation rate and GAT.
           * @dev This function can be called multiple times but each round will only every have one snapshot at the
           * time of calling `_freezeRoundVariables`.
           * @param signature  signature required to prove caller is an EOA to prevent flash loans from being included in the
           * snapshot.
           */
          function snapshotCurrentRound(bytes calldata signature) external virtual;
          /**
           * @notice Reveal a previously committed vote for `identifier` at `time`.
           * @dev The revealed `price`, `salt`, `address`, `time`, `roundId`, and `identifier`, must hash to the latest `hash`
           * that `commitVote()` was called with. Only the committer can reveal their vote.
           * @param identifier voted on in the commit phase. EG BTC/USD price pair.
           * @param time specifies the unix timestamp of the price is being voted on.
           * @param price voted on during the commit phase.
           * @param salt value used to hide the commitment price during the commit phase.
           */
          function revealVote(
              bytes32 identifier,
              uint256 time,
              int256 price,
              bytes memory ancillaryData,
              int256 salt
          ) public virtual;
          /**
           * @notice Reveal multiple votes in a single transaction.
           * Look at `project-root/common/Constants.js` for the tested maximum number of reveals.
           * that can fit in one transaction.
           * @dev For more information on reveals, review the comment for `revealVote`.
           * @param reveals array of the Reveal struct which contains an identifier, time, price and salt.
           */
          function batchReveal(RevealAncillary[] memory reveals) public virtual;
          /**
           * @notice Gets the queries that are being voted on this round.
           * @return pendingRequests `PendingRequest` array containing identifiers
           * and timestamps for all pending requests.
           */
          function getPendingRequests() external view virtual returns (PendingRequestAncillary[] memory);
          /**
           * @notice Returns the current voting phase, as a function of the current time.
           * @return Phase to indicate the current phase. Either { Commit, Reveal, NUM_PHASES }.
           */
          function getVotePhase() external view virtual returns (Phase);
          /**
           * @notice Returns the current round ID, as a function of the current time.
           * @return uint256 representing the unique round ID.
           */
          function getCurrentRoundId() external view virtual returns (uint256);
          /**
           * @notice Retrieves rewards owed for a set of resolved price requests.
           * @dev Can only retrieve rewards if calling for a valid round and if the
           * call is done within the timeout threshold (not expired).
           * @param voterAddress voter for which rewards will be retrieved. Does not have to be the caller.
           * @param roundId the round from which voting rewards will be retrieved from.
           * @param toRetrieve array of PendingRequests which rewards are retrieved from.
           * @return total amount of rewards returned to the voter.
           */
          function retrieveRewards(
              address voterAddress,
              uint256 roundId,
              PendingRequestAncillary[] memory toRetrieve
          ) public virtual returns (FixedPoint.Unsigned memory);
          // Voting Owner functions.
          /**
           * @notice Disables this Voting contract in favor of the migrated one.
           * @dev Can only be called by the contract owner.
           * @param newVotingAddress the newly migrated contract address.
           */
          function setMigrated(address newVotingAddress) external virtual;
          /**
           * @notice Resets the inflation rate. Note: this change only applies to rounds that have not yet begun.
           * @dev This method is public because calldata structs are not currently supported by solidity.
           * @param newInflationRate sets the next round's inflation rate.
           */
          function setInflationRate(FixedPoint.Unsigned memory newInflationRate) public virtual;
          /**
           * @notice Resets the Gat percentage. Note: this change only applies to rounds that have not yet begun.
           * @dev This method is public because calldata structs are not currently supported by solidity.
           * @param newGatPercentage sets the next round's Gat percentage.
           */
          function setGatPercentage(FixedPoint.Unsigned memory newGatPercentage) public virtual;
          /**
           * @notice Resets the rewards expiration timeout.
           * @dev This change only applies to rounds that have not yet begun.
           * @param NewRewardsExpirationTimeout how long a caller can wait before choosing to withdraw their rewards.
           */
          function setRewardsExpirationTimeout(uint256 NewRewardsExpirationTimeout) public virtual;
      }
      // SPDX-License-Identifier: AGPL-3.0-only
      pragma solidity ^0.8.0;
      import "../../common/implementation/FixedPoint.sol";
      import "./VotingAncillaryInterface.sol";
      /**
       * @title Interface that voters must use to Vote on price request resolutions.
       */
      abstract contract VotingInterface {
          struct PendingRequest {
              bytes32 identifier;
              uint256 time;
          }
          // Captures the necessary data for making a commitment.
          // Used as a parameter when making batch commitments.
          // Not used as a data structure for storage.
          struct Commitment {
              bytes32 identifier;
              uint256 time;
              bytes32 hash;
              bytes encryptedVote;
          }
          // Captures the necessary data for revealing a vote.
          // Used as a parameter when making batch reveals.
          // Not used as a data structure for storage.
          struct Reveal {
              bytes32 identifier;
              uint256 time;
              int256 price;
              int256 salt;
          }
          /**
           * @notice Commit a vote for a price request for `identifier` at `time`.
           * @dev `identifier`, `time` must correspond to a price request that's currently in the commit phase.
           * Commits can be changed.
           * @dev Since transaction data is public, the salt will be revealed with the vote. While this is the system’s expected behavior,
           * voters should never reuse salts. If someone else is able to guess the voted price and knows that a salt will be reused, then
           * they can determine the vote pre-reveal.
           * @param identifier uniquely identifies the committed vote. EG BTC/USD price pair.
           * @param time unix timestamp of the price being voted on.
           * @param hash keccak256 hash of the `price`, `salt`, voter `address`, `time`, current `roundId`, and `identifier`.
           */
          function commitVote(
              bytes32 identifier,
              uint256 time,
              bytes32 hash
          ) external virtual;
          /**
           * @notice Submit a batch of commits in a single transaction.
           * @dev Using `encryptedVote` is optional. If included then commitment is stored on chain.
           * Look at `project-root/common/Constants.js` for the tested maximum number of
           * commitments that can fit in one transaction.
           * @param commits array of structs that encapsulate an `identifier`, `time`, `hash` and optional `encryptedVote`.
           */
          function batchCommit(Commitment[] memory commits) public virtual;
          /**
           * @notice commits a vote and logs an event with a data blob, typically an encrypted version of the vote
           * @dev An encrypted version of the vote is emitted in an event `EncryptedVote` to allow off-chain infrastructure to
           * retrieve the commit. The contents of `encryptedVote` are never used on chain: it is purely for convenience.
           * @param identifier unique price pair identifier. Eg: BTC/USD price pair.
           * @param time unix timestamp of for the price request.
           * @param hash keccak256 hash of the price you want to vote for and a `int256 salt`.
           * @param encryptedVote offchain encrypted blob containing the voters amount, time and salt.
           */
          function commitAndEmitEncryptedVote(
              bytes32 identifier,
              uint256 time,
              bytes32 hash,
              bytes memory encryptedVote
          ) public virtual;
          /**
           * @notice snapshot the current round's token balances and lock in the inflation rate and GAT.
           * @dev This function can be called multiple times but each round will only every have one snapshot at the
           * time of calling `_freezeRoundVariables`.
           * @param signature  signature required to prove caller is an EOA to prevent flash loans from being included in the
           * snapshot.
           */
          function snapshotCurrentRound(bytes calldata signature) external virtual;
          /**
           * @notice Reveal a previously committed vote for `identifier` at `time`.
           * @dev The revealed `price`, `salt`, `address`, `time`, `roundId`, and `identifier`, must hash to the latest `hash`
           * that `commitVote()` was called with. Only the committer can reveal their vote.
           * @param identifier voted on in the commit phase. EG BTC/USD price pair.
           * @param time specifies the unix timestamp of the price is being voted on.
           * @param price voted on during the commit phase.
           * @param salt value used to hide the commitment price during the commit phase.
           */
          function revealVote(
              bytes32 identifier,
              uint256 time,
              int256 price,
              int256 salt
          ) public virtual;
          /**
           * @notice Reveal multiple votes in a single transaction.
           * Look at `project-root/common/Constants.js` for the tested maximum number of reveals.
           * that can fit in one transaction.
           * @dev For more information on reveals, review the comment for `revealVote`.
           * @param reveals array of the Reveal struct which contains an identifier, time, price and salt.
           */
          function batchReveal(Reveal[] memory reveals) public virtual;
          /**
           * @notice Gets the queries that are being voted on this round.
           * @return pendingRequests `PendingRequest` array containing identifiers
           * and timestamps for all pending requests.
           */
          function getPendingRequests()
              external
              view
              virtual
              returns (VotingAncillaryInterface.PendingRequestAncillary[] memory);
          /**
           * @notice Returns the current voting phase, as a function of the current time.
           * @return Phase to indicate the current phase. Either { Commit, Reveal, NUM_PHASES }.
           */
          function getVotePhase() external view virtual returns (VotingAncillaryInterface.Phase);
          /**
           * @notice Returns the current round ID, as a function of the current time.
           * @return uint256 representing the unique round ID.
           */
          function getCurrentRoundId() external view virtual returns (uint256);
          /**
           * @notice Retrieves rewards owed for a set of resolved price requests.
           * @dev Can only retrieve rewards if calling for a valid round and if the
           * call is done within the timeout threshold (not expired).
           * @param voterAddress voter for which rewards will be retrieved. Does not have to be the caller.
           * @param roundId the round from which voting rewards will be retrieved from.
           * @param toRetrieve array of PendingRequests which rewards are retrieved from.
           * @return total amount of rewards returned to the voter.
           */
          function retrieveRewards(
              address voterAddress,
              uint256 roundId,
              PendingRequest[] memory toRetrieve
          ) public virtual returns (FixedPoint.Unsigned memory);
          // Voting Owner functions.
          /**
           * @notice Disables this Voting contract in favor of the migrated one.
           * @dev Can only be called by the contract owner.
           * @param newVotingAddress the newly migrated contract address.
           */
          function setMigrated(address newVotingAddress) external virtual;
          /**
           * @notice Resets the inflation rate. Note: this change only applies to rounds that have not yet begun.
           * @dev This method is public because calldata structs are not currently supported by solidity.
           * @param newInflationRate sets the next round's inflation rate.
           */
          function setInflationRate(FixedPoint.Unsigned memory newInflationRate) public virtual;
          /**
           * @notice Resets the Gat percentage. Note: this change only applies to rounds that have not yet begun.
           * @dev This method is public because calldata structs are not currently supported by solidity.
           * @param newGatPercentage sets the next round's Gat percentage.
           */
          function setGatPercentage(FixedPoint.Unsigned memory newGatPercentage) public virtual;
          /**
           * @notice Resets the rewards expiration timeout.
           * @dev This change only applies to rounds that have not yet begun.
           * @param NewRewardsExpirationTimeout how long a caller can wait before choosing to withdraw their rewards.
           */
          function setRewardsExpirationTimeout(uint256 NewRewardsExpirationTimeout) public virtual;
      }
      // TODO: add staking/snapshot interfaces to this interface file.
      // SPDX-License-Identifier: AGPL-3.0-only
      pragma solidity 0.8.16;
      /**
       * @title Interface that voters must use to Vote on price request resolutions.
       */
      abstract contract VotingV2Interface {
          struct PendingRequest {
              bytes32 identifier;
              uint256 time;
          }
          struct PendingRequestAncillary {
              bytes32 identifier;
              uint256 time;
              bytes ancillaryData;
          }
          struct PendingRequestAncillaryAugmented {
              uint32 lastVotingRound;
              bool isGovernance;
              uint64 time;
              uint32 rollCount;
              bytes32 identifier;
              bytes ancillaryData;
          }
          // Captures the necessary data for making a commitment.
          // Used as a parameter when making batch commitments.
          // Not used as a data structure for storage.
          struct Commitment {
              bytes32 identifier;
              uint256 time;
              bytes32 hash;
              bytes encryptedVote;
          }
          // Captures the necessary data for revealing a vote.
          // Used as a parameter when making batch reveals.
          // Not used as a data structure for storage.
          struct Reveal {
              bytes32 identifier;
              uint256 time;
              int256 price;
              int256 salt;
          }
          // Captures the necessary data for making a commitment.
          // Used as a parameter when making batch commitments.
          // Not used as a data structure for storage.
          struct CommitmentAncillary {
              bytes32 identifier;
              uint256 time;
              bytes ancillaryData;
              bytes32 hash;
              bytes encryptedVote;
          }
          // Captures the necessary data for revealing a vote.
          // Used as a parameter when making batch reveals.
          // Not used as a data structure for storage.
          struct RevealAncillary {
              bytes32 identifier;
              uint256 time;
              int256 price;
              bytes ancillaryData;
              int256 salt;
          }
          // Note: the phases must be in order. Meaning the first enum value must be the first phase, etc.
          // `NUM_PHASES` is to get the number of phases. It isn't an actual phase, and it should always be last.
          enum Phase { Commit, Reveal, NUM_PHASES }
          /**
           * @notice Commit a vote for a price request for `identifier` at `time`.
           * @dev `identifier`, `time` must correspond to a price request that's currently in the commit phase.
           * Commits can be changed.
           * @dev Since transaction data is public, the salt will be revealed with the vote. While this is the system’s expected behavior,
           * voters should never reuse salts. If someone else is able to guess the voted price and knows that a salt will be reused, then
           * they can determine the vote pre-reveal.
           * @param identifier uniquely identifies the committed vote. EG BTC/USD price pair.
           * @param time unix timestamp of the price being voted on.
           * @param ancillaryData arbitrary data appended to a price request to give the voters more info from the caller.
           * @param hash keccak256 hash of the `price`, `salt`, voter `address`, `time`, current `roundId`, and `identifier`.
           */
          function commitVote(
              bytes32 identifier,
              uint256 time,
              bytes memory ancillaryData,
              bytes32 hash
          ) public virtual;
          /**
           * @notice commits a vote and logs an event with a data blob, typically an encrypted version of the vote
           * @dev An encrypted version of the vote is emitted in an event `EncryptedVote` to allow off-chain infrastructure to
           * retrieve the commit. The contents of `encryptedVote` are never used on chain: it is purely for convenience.
           * @param identifier unique price pair identifier. Eg: BTC/USD price pair.
           * @param time unix timestamp of for the price request.
           * @param ancillaryData  arbitrary data appended to a price request to give the voters more info from the caller.
           * @param hash keccak256 hash of the price you want to vote for and a `int256 salt`.
           * @param encryptedVote offchain encrypted blob containing the voters amount, time and salt.
           */
          function commitAndEmitEncryptedVote(
              bytes32 identifier,
              uint256 time,
              bytes memory ancillaryData,
              bytes32 hash,
              bytes memory encryptedVote
          ) external virtual;
          /**
           * @notice Reveal a previously committed vote for `identifier` at `time`.
           * @dev The revealed `price`, `salt`, `address`, `time`, `roundId`, and `identifier`, must hash to the latest `hash`
           * that `commitVote()` was called with. Only the committer can reveal their vote.
           * @param identifier voted on in the commit phase. EG BTC/USD price pair.
           * @param time specifies the unix timestamp of the price is being voted on.
           * @param price voted on during the commit phase.
           * @param ancillaryData arbitrary data appended to a price request to give the voters more info from the caller.
           * @param salt value used to hide the commitment price during the commit phase.
           */
          function revealVote(
              bytes32 identifier,
              uint256 time,
              int256 price,
              bytes memory ancillaryData,
              int256 salt
          ) public virtual;
          /**
           * @notice Gets the requests that are being voted on this round.
           * @return pendingRequests array containing identifiers of type PendingRequestAncillaryAugmented.
           */
          function getPendingRequests() external virtual returns (PendingRequestAncillaryAugmented[] memory);
          /**
           * @notice Returns the current voting phase, as a function of the current time.
           * @return Phase to indicate the current phase. Either { Commit, Reveal, NUM_PHASES }.
           */
          function getVotePhase() external view virtual returns (Phase);
          /**
           * @notice Returns the current round ID, as a function of the current time.
           * @return uint256 representing the unique round ID.
           */
          function getCurrentRoundId() external view virtual returns (uint32);
          // Voting Owner functions.
          /**
           * @notice Disables this Voting contract in favor of the migrated one.
           * @dev Can only be called by the contract owner.
           * @param newVotingAddress the newly migrated contract address.
           */
          function setMigrated(address newVotingAddress) external virtual;
          /**
           * @notice Sets the maximum number of rounds to roll a request can have before the DVM auto deletes it.
           * @dev Can only be called by the contract owner.
           * @param newMaxRolls the new number of rounds to roll a request before the DVM auto deletes it.
           */
          function setMaxRolls(uint32 newMaxRolls) external virtual;
          /**
           * @notice Sets the maximum number of requests that can be made in a single round. Used to bound the maximum
           * sequential slashing that can be applied within a single round.
           * @dev Can only be called by the contract owner.
           * @param newMaxRequestsPerRound the new maximum number of requests that can be made in a single round.
           */
          function setMaxRequestPerRound(uint32 newMaxRequestsPerRound) external virtual;
          /**
           * @notice Resets the GAT number and SPAT percentage. The GAT is the minimum number of tokens that must participate
           * in a vote for it to resolve (quorum number). The SPAT is is the minimum percentage of tokens that must agree
           * in a vote for it to resolve (percentage of staked tokens) Note: this change only applies to rounds that
           * have not yet begun.
           * @param newGat sets the next round's GAT and going forward.
           * @param newSpat sets the next round's SPAT and going forward.
           */
          function setGatAndSpat(uint128 newGat, uint64 newSpat) external virtual;
          /**
           * @notice Changes the slashing library used by this contract.
           * @param _newSlashingLibrary new slashing library address.
           */
          function setSlashingLibrary(address _newSlashingLibrary) external virtual;
      }
      

      File 2 of 2: FixedSlashSlashingLibrary
      // SPDX-License-Identifier: AGPL-3.0-only
      pragma solidity 0.8.16;
      import "../interfaces/SlashingLibraryInterface.sol";
      /**
       * @title Slashing Library contract. Returns the how much a voter should be slashed per staked token as a function of
       * the total staked, total votes and total correct votes. Can be upgraded to a new implementation to enable more
       elaborate slashing algorithms via UMA governance.
       */
      contract FixedSlashSlashingLibrary is SlashingLibraryInterface {
          uint256 public immutable baseSlashAmount; // Slash amount per token for missed votes and wrong non-governance votes.
          uint256 public immutable governanceSlashAmount; // Slash amount per token for wrong governance votes.
          /**
           * @notice Construct the FixedSlashSlashingLibrary contract.
           * @param _baseSlashAmount Slash amount per token for missed votes and wrong non-governance votes.
           * @param _governanceSlashAmount Slash amount per token for wrong governance votes.
           */
          constructor(uint256 _baseSlashAmount, uint256 _governanceSlashAmount) {
              require(_baseSlashAmount < 1e18, "Invalid base slash amount");
              require(_governanceSlashAmount < 1e18, "Invalid governance slash amount");
              baseSlashAmount = _baseSlashAmount; // Slash amount per token for missed votes and wrong non-governance votes.
              governanceSlashAmount = _governanceSlashAmount; // Slash amount per token for wrong governance votes.
          }
          /**
           * @notice Calculates the wrong vote slash per token.
           * @param totalStaked The total amount of tokens staked.
           * @param totalVotes The total amount of votes.
           * @param totalCorrectVotes The total amount of correct votes.
           * @param priceRequestIndex The price request index within the resolvedPriceRequestIds array.
           * @return uint256 The amount of tokens to slash per token staked.
           */
          function calcWrongVoteSlashPerToken(
              uint256 totalStaked,
              uint256 totalVotes,
              uint256 totalCorrectVotes,
              uint256 priceRequestIndex
          ) public view returns (uint256) {
              return baseSlashAmount;
          }
          /**
           * @notice Calculates the wrong vote slash per token for governance requests.
           * @param totalStaked The total amount of tokens staked.
           * @param totalVotes The total amount of votes.
           * @param totalCorrectVotes The total amount of correct votes.
           * @param priceRequestIndex The price request index within the resolvedPriceRequestIds array.
           * @return uint256 The amount of tokens to slash per token staked.
           */
          function calcWrongVoteSlashPerTokenGovernance(
              uint256 totalStaked,
              uint256 totalVotes,
              uint256 totalCorrectVotes,
              uint256 priceRequestIndex
          ) public view returns (uint256) {
              return governanceSlashAmount;
          }
          /**
           * @notice Calculates the no vote slash per token.
           * @param totalStaked The total amount of tokens staked.
           * @param totalVotes The total amount of votes.
           * @param totalCorrectVotes The total amount of correct votes.
           * @param priceRequestIndex The price request index within the resolvedPriceRequestIds array.
           * @return uint256 The amount of tokens to slash per token staked.
           */
          function calcNoVoteSlashPerToken(
              uint256 totalStaked,
              uint256 totalVotes,
              uint256 totalCorrectVotes,
              uint256 priceRequestIndex
          ) public view returns (uint256) {
              return baseSlashAmount;
          }
          /**
           * @notice Calculates all slashing trackers in one go to decrease cross-contract calls needed.
           * @param totalStaked The total amount of tokens staked.
           * @param totalVotes The total amount of votes.
           * @param totalCorrectVotes The total amount of correct votes.
           * @param priceRequestIndex The price request index within the resolvedPriceRequestIds array.
           * @param isGovernance Whether the request is a governance request.
           * @return wrongVoteSlashPerToken The amount of tokens to slash for voting wrong.
           * @return noVoteSlashPerToken The amount of tokens to slash for not voting.
           */
          function calcSlashing(
              uint256 totalStaked,
              uint256 totalVotes,
              uint256 totalCorrectVotes,
              uint256 priceRequestIndex,
              bool isGovernance
          ) external view returns (uint256 wrongVoteSlashPerToken, uint256 noVoteSlashPerToken) {
              return (
                  isGovernance
                      ? calcWrongVoteSlashPerTokenGovernance(totalStaked, totalVotes, totalCorrectVotes, priceRequestIndex)
                      : calcWrongVoteSlashPerToken(totalStaked, totalVotes, totalCorrectVotes, priceRequestIndex),
                  calcNoVoteSlashPerToken(totalStaked, totalVotes, totalCorrectVotes, priceRequestIndex)
              );
          }
      }
      // SPDX-License-Identifier: AGPL-3.0-only
      pragma solidity 0.8.16;
      interface SlashingLibraryInterface {
          /**
           * @notice Calculates the wrong vote slash per token.
           * @param totalStaked The total amount of tokens staked.
           * @param totalVotes The total amount of votes.
           * @param totalCorrectVotes The total amount of correct votes.
           * @param priceRequestIndex The price request index within the resolvedPriceRequestIds array.
           * @return uint256 The amount of tokens to slash per token staked.
           */
          function calcWrongVoteSlashPerToken(
              uint256 totalStaked,
              uint256 totalVotes,
              uint256 totalCorrectVotes,
              uint256 priceRequestIndex
          ) external view returns (uint256);
          /**
           * @notice Calculates the wrong vote slash per token for governance requests.
           * @param totalStaked The total amount of tokens staked.
           * @param totalVotes The total amount of votes.
           * @param totalCorrectVotes The total amount of correct votes.
           * @param priceRequestIndex The price request index within the resolvedPriceRequestIds array.
           * @return uint256 The amount of tokens to slash per token staked.
           */
          function calcWrongVoteSlashPerTokenGovernance(
              uint256 totalStaked,
              uint256 totalVotes,
              uint256 totalCorrectVotes,
              uint256 priceRequestIndex
          ) external view returns (uint256);
          /**
           * @notice Calculates the no vote slash per token.
           * @param totalStaked The total amount of tokens staked.
           * @param totalVotes The total amount of votes.
           * @param totalCorrectVotes The total amount of correct votes.
           * @param priceRequestIndex The price request index within the resolvedPriceRequestIds array.
           * @return uint256 The amount of tokens to slash per token staked.
           */
          function calcNoVoteSlashPerToken(
              uint256 totalStaked,
              uint256 totalVotes,
              uint256 totalCorrectVotes,
              uint256 priceRequestIndex
          ) external view returns (uint256);
          /**
           * @notice Calculates all slashing trackers in one go to decrease cross-contract calls needed.
           * @param totalStaked The total amount of tokens staked.
           * @param totalVotes The total amount of votes.
           * @param totalCorrectVotes The total amount of correct votes.
           * @param priceRequestIndex The price request index within the resolvedPriceRequestIds array.
           * @param isGovernance Whether the request is a governance request.
           * @return wrongVoteSlashPerToken The amount of tokens to slash for voting wrong.
           * @return noVoteSlashPerToken The amount of tokens to slash for not voting.
           */
          function calcSlashing(
              uint256 totalStaked,
              uint256 totalVotes,
              uint256 totalCorrectVotes,
              uint256 priceRequestIndex,
              bool isGovernance
          ) external view returns (uint256 wrongVoteSlashPerToken, uint256 noVoteSlashPerToken);
      }